0Pricing
TypeScript Academy · 강의

never를 사용한 완전성 검사

never로 처리되지 않은 경우를 컴파일 시점에 포착합니다.

never를 사용한 완전성 검사은(는) CoddyKit의 무료 TypeScript Academy 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 TypeScript Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. TypeScript Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

모든 경우를 처리해야 하는 문제

새 유니온 멤버를 추가하면 어딘가에서 해당 멤버를 처리하는 것을 잊기 쉽습니다. 완전성 검사를 사용하면 이런 누락이 컴파일 오류로 나타납니다.

type Shape =
  | { kind: "circle"; radius: number }
  | { kind: "square"; side: number };

// If we add "triangle" later, we want every switch to complain.

never 타입

never 타입은 절대 발생할 수 없는 값을 나타냅니다. 모든 경우를 처리하면 기본 분기에 도달하는 값의 타입은 never가 됩니다.

function fail(): never {
  throw new Error("unreachable");
}
// never is assignable to nothing except never itself.

기본 case에서 never에 할당하기

default 분기에서 값을 never 변수에 할당합니다. 모든 변형을 처리하면 할당이 컴파일되고, 그렇지 않으면 오류가 발생합니다.

type Shape =
  | { kind: "circle"; radius: number }
  | { kind: "square"; side: number };

function area(s: Shape): number {
  switch (s.kind) {
    case "circle": return Math.PI * s.radius ** 2;
    case "square": return s.side ** 2;
    default:
      const _exhaustive: never = s;
      return _exhaustive;
  }
}
console.log(area({ kind: "square", side: 3 }));

case를 잊으면 어떻게 될까요

triangle 멤버를 추가하고 해당 case를 잊으면 default의 s는 더 이상 never가 아니므로 컴파일 시 할당에 실패합니다.

// type Shape = ... | { kind: "triangle"; base: number; height: number };
// Now in default, s is { kind: "triangle"; ... }
// const _exhaustive: never = s; // Error: triangle not assignable to never

assertNever 도우미

재사용 가능한 assertNever 함수로 이 패턴을 한곳에 모을 수 있습니다. 이 함수는 never를 받고 예외를 발생시키며, 해당 분기에 도달할 수 없어야 한다는 점을 명확히 보여 줍니다.

function assertNever(value: never): never {
  throw new Error("Unhandled case: " + JSON.stringify(value));
}
console.log(typeof assertNever);

switch에서 assertNever 사용하기

default case에서 assertNever(s)를 호출합니다. 컴파일 시 모든 경우를 처리하도록 강제하고, 실제로 해당 분기에 도달하면 명확한 런타임 오류를 발생시킵니다.

function assertNever(value: never): never {
  throw new Error("Unhandled: " + JSON.stringify(value));
}
type Shape =
  | { kind: "circle"; radius: number }
  | { kind: "square"; side: number };

function area(s: Shape): number {
  switch (s.kind) {
    case "circle": return Math.PI * s.radius ** 2;
    case "square": return s.side ** 2;
    default: return assertNever(s);
  }
}
console.log(area({ kind: "circle", radius: 1 }).toFixed(2));

컴파일 시 안전성과 런타임 안전성

never 검사는 코드를 실행하기 전에 누락된 경우를 찾아내며, 발생한 오류는 타입 검사를 통과한 문제가 런타임에 나타날 때 보호 장치가 됩니다.

function assertNever(x: never): never {
  throw new Error("Unhandled: " + String(x));
}
// Compile error if a case is missing; runtime throw as a backstop.
console.log("two layers of safety");

default 없이 완전성 검사하기

함수에 명시적인 반환 타입이 있고 switch가 모든 경우를 포함하면 TypeScript는 반환 누락도 알려 줄 수 있습니다. 이것 역시 완전성 검사의 한 형태입니다.

type Light = "red" | "yellow" | "green";
function next(l: Light): Light {
  switch (l) {
    case "red": return "green";
    case "yellow": return "red";
    case "green": return "yellow";
  }
  // No default needed; all cases return.
}
console.log(next("red"));

if/else 연결에서 완전성 검사하기

같은 방식은 if/else에도 적용됩니다. 각 변형을 처리하고 나면 마지막 else는 never 값을 받습니다.

function assertNever(x: never): never { throw new Error("bad"); }
type Shape =
  | { kind: "circle"; radius: number }
  | { kind: "square"; side: number };

function name(s: Shape): string {
  if (s.kind === "circle") return "circle";
  else if (s.kind === "square") return "square";
  else return assertNever(s);
}
console.log(name({ kind: "square", side: 2 }));

never가 적합한 도구인 이유

never는 어떤 것에도 할당될 수 없으므로 남아 있는 변형이 있으면 할당이 실패합니다. 따라서 처리되지 않은 경우를 찾아내는 데 never가 가장 적합합니다.

// Only never is assignable to never.
let x: never;
// x = "hi"; // Error
// Any concrete leftover type fails the same way.
console.log("never catches gaps");

리팩터링의 안전망으로 사용하는 완전성 검사

모든 곳에서 assertNever를 사용하면 유니온 멤버를 추가했을 때 업데이트해야 하는 모든 위치를 정확히 가리키는 정리된 컴파일 오류 목록이 만들어집니다.

function assertNever(x: never): never { throw new Error("unhandled"); }
type Status = "idle" | "busy";
function render(s: Status): string {
  switch (s) {
    case "idle": return "Idle";
    case "busy": return "Busy";
    default: return assertNever(s);
  }
}
console.log(render("idle"));

빠른 확인: 완전성 검사

완전성 검사에 대한 이해도를 확인해 보세요.

복습: never를 사용한 완전성 검사

기본값을 never에 할당하거나 assertNever에 전달하면 컴파일러가 모든 변형을 처리하도록 강제한다는 것을 배웠습니다. 이를 통해 잊어버린 경우가 컴파일 오류로 나타납니다.

function assertNever(x: never): never { throw new Error("unhandled"); }
type Shape = { kind: "circle"; radius: number } | { kind: "square"; side: number };
function f(s: Shape) {
  switch (s.kind) {
    case "circle": return s.radius;
    case "square": return s.side;
    default: return assertNever(s);
  }
}
console.log(f({ kind: "circle", radius: 5 }));

자주 묻는 질문

“never를 사용한 완전성 검사” 강의는 무료인가요?

네 — “never를 사용한 완전성 검사” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 TypeScript Academy 강의 전체를 잠금 해제할 수 있습니다. TypeScript Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“never를 사용한 완전성 검사”에서 뭘 배우나요?

never로 처리되지 않은 경우를 컴파일 시점에 포착합니다. 브라우저에서 직접 실행하는 실습 코드로 TypeScript Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

TypeScript Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 TypeScript Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.

“never를 사용한 완전성 검사” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 TypeScript Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 TypeScript Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. 판별 유니언 구축
  2. 판별 속성에 따른 타입 좁히기
  3. never를 사용한 완전성 검사
  4. 상태 머신 모델링
← TypeScript Academy(으)로 돌아가기