TypeScript - Never: never 타입 이해
안녕하세요, 야심 찬 프로그래머 여러분! 오늘 우리는 TypeScript의 더 이상의 타입인 never
타입에 대해 깊이 다루어보겠습니다. 프로그래밍 초보자라도 걱정하지 마세요 - 저는 이 개념을 단계별로 안내해드릴 것입니다. 수년 동안 수많은 학생들에게 가르쳐온 경험을 바탕으로 말이죠. 그럼 여러분의 좋아하는 음료를 마시며, TypeScript의 세계로 흥미로운 여정을 시작해보겠습니다!
never 타입이란?
TypeScript에서 never
타입은 종종 "바닥 타입" 또는 "빈 타입"으로 불립니다. 이 타입은 결코 발생하지 않아야 할 타입을 나타냅니다. 이제 여러분은 고민할 수도 있겠습니다, "왜 발생하지 않는 타입이 필요할까요?" 그러나 제가 말씀드리겠지만, 이 타입은 상상보다 더 유용합니다!
never 타입의 사용场合
- 불가능한 상황을 나타내는 데 사용
- 전체 검사를 처리하는 데 사용
- 결코 반환되지 않는 함수에서 사용
다음 예제를 통해 이 개념을 더 명확히 이해해보겠습니다.
예제 1: 불가능한 상황 나타내기
function throwError(message: string): never {
throw new Error(message);
}
let result = throwError("Oops! Something went wrong!");
console.log(result); // 이 줄은 결코 도달하지 않습니다.
이 예제에서 throwError
함수는 반드시 오류를 발생시키고 정상적으로 반환되지 않습니다. 따라서 그 반환 타입은 never
입니다.
이를 다음과 같이 생각해보세요: 만약 케이크 만드는 레시피에 "결코 굽지 마세요"라고 적혀 있다면, 그 케이크는 오븐에서 나오지 않는다는 걸 알 수 있습니다!
예제 2: 전체 검사
type Shape = "circle" | "square" | "triangle";
function getArea(shape: Shape): number {
switch (shape) {
case "circle":
return Math.PI * Math.pow(5, 2);
case "square":
return 10 * 10;
case "triangle":
return (10 * 5) / 2;
default:
const _exhaustiveCheck: never = shape;
return _exhaustiveCheck;
}
}
여기서 never
는 우리가 모든 가능한 shapes를 다루었는지 확인하는 데 도움을 줍니다. 만약 Shape
타입에 새로운 shape를 추가하고 getArea
에 대해 케이스를 추가하지 않는다면, TypeScript는 오류를 발생시킵니다. 이는 잊은 것을 상기시켜주는 유용한 어시스턴트와 같습니다!
예제 3: 결코 반환되지 않는 함수
function infiniteLoop(): never {
while (true) {
console.log("This loop never ends!");
}
}
이 함수는 영원히 실행되거나 (또는 컴퓨터의 메모리가 다 떨어질 때까지) 반환되지 않습니다. 따라서 그 반환 타입은 never
입니다. 친구에게 "결코 말을 멈추지 않겠다"고 말할 때와 같이, 그들은 긴 대화를 할 준비를 합니다!
never 타입과 void 타입의 차이
이제 여러분은 "never와 void는 무엇이 다른가요?"라는 궁금증을 가질 수도 있습니다. 훌륭한 질문입니다! 그 차이를 알아보겠습니다.
void
void
타입은 함수가 어떤 값을 반환하지 않을 때 사용됩니다. 하지만 실행을 완료합니다.
function logMessage(message: string): void {
console.log(message);
}
logMessage("Hello, TypeScript!"); // 이 함수는 undefined를 반환합니다.
never
반면에 never
타입은 함수가 결코 실행을 완료하지 않거나 항상 오류를 발생시킬 때 사용됩니다.
function failwithError(message: string): never {
throw new Error(message);
}
failwithError("This function never returns!");
이를 다음과 같이 생각해보세요: void
는 가게에서 손을 비우고 돌아오는 것처럼, never
는 여정을 떠나서 결코 돌아오지 않는 것과 같습니다!
never 타입의 실용적인 사용
never 타입의 더 많은 실용적인 예제를 살펴보겠습니다.
예제 4: 타입 가드
type Square = { kind: "square", size: number };
type Circle = { kind: "circle", radius: number };
type Shape = Square | Circle;
function assertNever(x: never): never {
throw new Error("Unexpected object: " + x);
}
function getArea(shape: Shape) {
switch (shape.kind) {
case "square": return shape.size * shape.size;
case "circle": return Math.PI * shape.radius ** 2;
default: return assertNever(shape); // Shape이 Square도 아니고 Circle도 아닐 경우 오류 발생
}
}
이 예제에서 assertNever
는 우리가 놓친 경우를 찾아주는 데 도움을 줍니다. 타입을 주고받는 것을 배울 때의 안전망과 같습니다!
예제 5: 도달할 수 없는 코드 탐지
function neverReaches(): never {
while (true) {
// 어떤 연산
}
console.log("This line will never be reached"); // TypeScript 오류
}
TypeScript는 console.log
문이 결코 도달하지 않는다는 것을 알고 오류를 발생시킵니다. 이는 GPS가 존재하지 않는 곳으로 가려고 할 때 경고를 주는 것과 같습니다!
never 타입의 메서드와 속성
이제 여러분은 never
타입에 대해 메서드나 속성이 있는지 궁금할 수도 있습니다. 사실 never
타입은 자신의 메서드나 속성이 없습니다. 하지만 TypeScript의 타입 시스템에서 중요한 역할을 합니다.
다음 표는 never
타입으로 할 수 있는(또는 할 수 없는) 작업을 요약합니다:
작업 | 결과 | 설명 |
---|---|---|
never 에 할당 |
✅ 허용 | 모든 타입이 never 에 할당 가능 |
never 을 다른 타입에 할당 |
❌ 불허용 |
never 는 다른 타입에 할당할 수 없음 |
never 에 메서드 호출 |
❌ 불허용 |
never 는 발생하지 않아야 하므로 메서드 호출 불가 |
never 을 연합 타입에서 사용 |
✅ 허용但無效 |
never 는 연합 타입에서 무시됨 |
never 을 교차 타입에서 사용 |
✅ 허용且结果为 never
|
모든 타입과 never 을 교차하면 never 가 됨 |
결론
이제 여러분은 never
타입의 세계를 여행한 것입니다. never
타입은 친구가 계획을 취소하는 것처럼, 결코 나타나지 않지만, 여전히 중요하게 여겨져야 합니다!
never
타입을 이해하는 것은처음에는 어렵게 느껴질 수 있지만, 연습을 통해 이는 TypeScript 도구 상자에서 귀중한 도구가 될 것입니다. 코드를 더 견고하게 만들고, 잠재적인 오류를 사전에 찾아내며, 함수의 동작을 깊이 이해하는 데 도움을 줄 것입니다.
계속 코딩하고, 학습하고, TypeScript에서 새로운 것을 시도하는 것에 대해 "결코"라는 말을 하지 마세요! 다음 번까지, 컴파일 오류가 적고 타입 추론이 강력하길 바랍니다!
Credits: Image by storyset