[TYPESCRIPT] any, unknown, never 차이와 올바른 사용법 -TypeScript 타입 시스템의 심장부 이해하기

TypeScript를 처음 접할 때 가장 혼동되는 타입이 any, unknown, never 입니다. 모두 특별한 의미를 가진 타입으로, TypeScript의 타입 시스템을 깊이 이해하기 위해 반드시 익혀야 하는 중요한 요소입니다. 

 

any - 타입 검사를 끄는 위험한 타입

any는 “어떤 타입이든 허용한다”는 의미로, TypeScript의 타입 검사를 완전히 우회합니다. 즉, JavaScript처럼 자유롭게 값을 넣을 수 있지만, 타입 안전성을 잃어버립니다.

let value: any = 123;
value = "hello";
value = true;
value = {};
value.nonExistMethod(); // ❗ 컴파일 시 오류 없음 → 런타임에서 터짐

any를 사용하면 좋은 경우

  • 정말 타입을 알 수 없고 빠르게 프로토타입을 만들 때
  • 기존 JavaScript 코드를 TypeScript로 점진 이동하는 초기 단계
  • 서드파티 라이브러리가 타입 정보를 제공하지 않을 때

any를 사용하면 위험한 이유

  • IDE 자동완성·타입 검사 기능 사라짐
  • 코드 품질·가독성 저하
  • 런타임 오류 증가
  • 프로젝트 전체에 타입 불안정성 확산

실무에서는 any 남용 = 유지보수 지옥으로 직결되므로 지양해야 합니다.

 

unknown - any보다 안전한 “모르는 타입”

unknown은 “타입을 알 수 없다”는 뜻은 동일하지만, any와 결정적으로 다른 점은 unknown 값은 바로 사용할 수 없다는 것입니다.

let data: unknown = "hello";

data.toUpperCase();
// ❌ 오류: unknown은 바로 사용 불가능

사용하려면 먼저 타입 체크가 필수입니다.

if (typeof data === "string") {
  console.log(data.toUpperCase()); // ✔ 안전하게 사용 가능
}

unknown이 any보다 좋은 이유

unknown은 다음과 같은 장점을 가집니다.

  • 타입 체크가 강제되므로 런타임 오류 감소
  • 타입 보호(Type Guard)가 필수 → 코드의 안정성 증가
  • 외부 API 응답 타입처럼 "정확히 알 수 없는 값"을 다룰 때 적합

추천되는 사용 사례

  • JSON 파싱 결과 처리
  • 외부 API, 메시지 큐에서 넘어오는 데이터
  • 사용자 입력(form, CLI, 이벤트 등)
function parseJson(json: string): unknown {
  return JSON.parse(json);
}

unknown은 실무에서 “타입을 알 수 없는 경우 but any는 쓰기 싫은 경우” 최선의 선택입니다.

 

never - 절대 발생할 수 없는 타입

never는 “값이 존재할 수 없다”는 뜻으로, TypeScript에서 가장 특수한 타입입니다. 다음과 같은 상황에서 never가 발생합니다.

1. 항상 오류를 발생시키는 함수

function throwError(msg: string): never {
  throw new Error(msg);
}

2. 무한 루프 함수

function infinite(): never {
  while (true) {}
}

3. 타입 좁히기(Narrowing)에서 모든 경우가 처리된 후 남는 타입

type Shape = "circle" | "square";

function draw(shape: Shape) {
  if (shape === "circle") {
    // ...
  } else if (shape === "square") {
    // ...
  } else {
    const neverValue: never = shape; 
    // ❌ shape가 never가 아니면 오류 → 모든 case가 처리되었음을 보장
  }
}

이 패턴은 실무에서 switch-case exhaustive 체크에 매우 유용합니다.

 

세 타입 비교 요약

타입 설명 특징 사용 권장 여부
any 모든 타입 허용 타입 검사 없음 → 위험 가급적 사용 금지
unknown 타입을 알 수 없음 사용 전 타입 체크 필요 → 안전 추천
never 값이 존재할 수 없음 오류/무한루프/타입 좁히기에서 사용 특별한 상황에서만 사용

 

실무 상황별 정리

1) 외부 입력 값 → unknown

function handleInput(input: unknown) {
  if (typeof input === "string") {
    // 안전하게 문자열로 처리
  }
}

2) 초기 개발 단계 → any(최소 사용 권장)

let temp: any; // 점진적 마이그레이션 시 사용 가능

3) 모든 경우의 수를 처리해야 할 때 → never

function assertNever(value: never): never {
  throw new Error("Unhandled case: " + value);
}

4) 기획 변경으로 enum 값이 늘어날 때 자동 감지 → never 활용

이 패턴은 서비스 규모가 커질수록 매우 유용합니다.

 

 

any, unknown, never는 TypeScript의 타입 시스템에서 매우 중요한 역할을 합니다. 각각의 목적이 분명히 다르며, 제대로 사용하면 코드의 안전성과 유지보수성을 획기적으로 개선할 수 있습니다.

  • any는 마지막 수단, 타입 안전성을 포기하는 선택
  • unknown은 “안전한 any”, 가장 추천되는 대체 타입
  • never는 특정 상황에서 타입 검사 강화