never는 결코 발생하지 않는 값의 타입입니다 — 결코 반환하지 않는 함수(throw하거나 영원히 반복), 또는 컴파일러가 불가능하다고 증명한 분기입니다. 공집합 타입입니다: never(자기 자신 제외)에는 어떤 값도 대입할 수 없습니다.
ts
(): { (msg); }
(): { () {} }
never는 결코 발생하지 않는 값의 타입입니다 — 결코 반환하지 않는 함수(throw하거나 영원히 반복), 또는 컴파일러가 불가능하다고 증명한 분기입니다. 공집합 타입입니다: never(자기 자신 제외)에는 어떤 값도 대입할 수 없습니다.
(): { (msg); }
(): { () {} }
Union을 아무것도 남지 않을 때까지 narrowing하면, TypeScript는 남은 값을 never로 타이핑합니다. 이를 활용해 모든 케이스의 처리를 강제합니다:
type Shape =
| { kind: "circle"; r: number }
| { kind: "square"; side: number };
function area(s: Shape): number {
switch (s.kind) {
case "circle": return Math.PI * s.r ** 2;
case "square": return s.side ** 2;
default:
// 모든 케이스가 처리되면 여기서 s는 `never` — 대입 OK
const _exhaustive: never = s;
return _exhaustive;
}
}
이제 누군가 Shape에 { kind: "triangle"; ... }를 추가했지만 케이스를 빠뜨리면, default에서 s는 triangle 타입(never가 아님)이므로 const _exhaustive: never = s가 컴파일에 실패합니다 — 갱신이 필요한 정확한 switch를 가리켜줍니다.
function a(): void {} // 정상적으로 반환, 단지 값이 없음
function b(): never { throw "x"; } // 아예 반환하지 않음
never는 "모든 케이스를 처리했나?"를 런타임의 기대에서 컴파일 타임 보증으로 바꿉니다.
Discriminated union의 안전하고 미래에도 견고한 처리의 핵심입니다 — 변형을 추가하면 컴파일러가 갱신해야 할 모든 지점을 열거해줍니다.