← 전체 글로 돌아가기

TypeScript

TypeScript에서 unknown 타입을 제대로 다루기

unknown 타입 처리로 발생하는 타입 에러들을 이해하고 안전하게 좁혀가는 방법.

TypeScript를 쓰다 보면 any 대신 unknown 타입을 쓰도록 강요받는 순간이 온다. unknownany보다 훨씬 까다롭지만, 제대로 다루면 타입 안정성이 훨씬 높아진다.

unknown은 any와 다르다

any는 거의 모든 작업을 허용하지만, unknown은 타입 가드를 거쳐야만 쓸 수 있다.

function process(value: unknown) {
  // value.method() // ❌ 컴파일 에러

  if (typeof value === 'string') {
    console.log(value.toUpperCase()); // ✅ OK
  }
}

이 차이가 실제로 버그를 방지한다.

타입 가드의 여러 방법

typeof 가드

if (typeof value === 'string') { }
if (typeof value === 'number') { }

원시형에는 이것으로 충분하다.

instanceof 가드

if (value instanceof Date) {
  value.toISOString(); // Date 메서드 가능
}

클래스 인스턴스 확인에 쓴다.

커스텀 타입 가드

function isUser(value: unknown): value is User {
  return (
    typeof value === 'object' &&
    value !== null &&
    'id' in value &&
    'name' in value
  );
}

if (isUser(value)) {
  console.log(value.name); // User 타입으로 인정됨
}

복잡한 객체 구조를 다룰 때 필수다.

자주 놓치는 실수들

null 체크 빼먹기

if (typeof value === 'object') {
  // ❌ value가 null일 수도 있음
  value.property; // 런타임 에러 가능
}

if (typeof value === 'object' && value !== null) {
  // ✅ 안전함
  value.property;
}

optional 처리 불완전

if ('property' in value) {
  // value.property는 unknown
  // 여기서 또 타입 가드를 거쳐야 함
}

API 응답 처리할 때

function handleResponse(data: unknown) {
  // API 응답을 곧바로 쓰지 말고
  const schema = z.object({
    id: z.string(),
    name: z.string()
  });

  const parsed = schema.parse(data); // Zod나 Yup 같은 라이브러리 쓰기
  return parsed;
}

API 응답은 항상 unknown으로 시작하고, 스키마 검증을 거쳐야 한다.

빌드 시 확인

npm run build

noImplicitAnystrictNullChecks를 켜둬야 unknown 관련 에러를 모두 잡을 수 있다.

정리

unknown은 결국 "이 값이 뭔지 아직 모르니까 체크하고 쓰자"는 뜻이다. 타입 가드를 한 단계 거치는 것이 처음엔 번거로워 보이지만, 결국 런타임 버그를 많이 줄여준다. 특히 API 응답이나 JSON 파싱 같은 외부 데이터를 다룰 때는 필수다.