TypeScript

[TypeScript] 타입 좁히기 (Type Narrowing)

2025년 11월 27일
1
TypeScriptStudyTypeGuardTypeNarrowing

📑 목차

타입스크립트에서 유니온(Union) 타입처럼 여러 타입이 합쳐진 변수를 다룰 때, 구체적인 상황에 맞게 타입을 추론해 나가는 과정을 타입 좁히기라고 한다. 이를 도와주는 코드를 타입 가드(Type Guard) 라고 부른다.

1. 왜 타입 좁히기가 필요한가?

다음과 같이 number 또는 string 타입을 매개변수로 받는 함수가 있다고 가정해 보자.

function func(value: number | string) {
  // value.toFixed(); // ❌ 오류 발생
  // value.toUpperCase(); // ❌ 오류 발생
}

이때 함수 내부에서 바로 메서드를 사용하려고 하면 에러가 발생한다 . value가 숫자일 수도 있고 문자열일 수도 있기 때문에, 컴파일러 입장에서는 어떤 메서드를 써야 안전한지 확신할 수 없기 때문이다.

이럴 때 조건문을 이용해 "이 블록 안에서는 value가 확실히 숫자야!" 라고 보장해 주면 에러 없이 사용할 수 있다. 이를 타입 좁히기라고 한다.


2. typeof 타입 가드

가장 기본적인 방법은 자바스크립트의 typeof 연산자를 사용하는 것이다. 주로 원시 타입(number, string, boolean 등)을 좁힐 때 사용한다.

function func(value: number | string) {
  if (typeof value === "number") {
    // 이 안에서는 value가 number 타입으로 보장됨
    console.log(value.toFixed()); 
  } else if (typeof value === "string") {
    // 이 안에서는 value가 string 타입으로 보장됨
    console.log(value.toUpperCase()); 
  }
}

조건문 내부에서 변수의 타입이 보장된 타입으로 좁혀지므로, 각 타입에 맞는 메서드를 안전하게 사용할 수 있다 .


3. instanceof 타입 가드

instanceof 연산자를 사용하면 내장 클래스(Date 등)나 직접 만든 클래스 타입을 보장할 수 있다.

function func(value: number | string | Date | null) {
  if (typeof value === "number") {
    console.log(value.toFixed());
  } else if (typeof value === "string") {
    console.log(value.toUpperCase());
  } else if (value instanceof Date) {
    // value가 Date 객체임이 보장됨
    console.log(value.getTime()); 
  }
}

주의할 점: instanceofclass에만 사용할 수 있다. 우리가 type 별칭이나 interface로 만든 사용자 정의 타입에는 사용할 수 없다.


4. in 타입 가드

직접 만든 객체 타입(Interface, Type Alias)을 좁혀야 할 때는 in 연산자를 사용한다. "객체 내부에 특정 프로퍼티가 존재하는가?" 를 확인하는 방식이다.

type Person = {
  name: string;
  age: number;
};

function func(value: number | string | Date | null | Person) {
  if (typeof value === "number") {
    console.log(value.toFixed());
  } else if (typeof value === "string") {
    console.log(value.toUpperCase());
  } else if (value instanceof Date) {
    console.log(value.getTime());
  } else if (value && "age" in value) {
    // value가 null이 아니고, 'age' 프로퍼티가 있다면 Person 타입으로 좁혀짐
    console.log(`${value.name}${value.age}살 입니다`);
  }
}

위 코드에서 value && "age" in value라고 작성한 이유는 valuenull일 수도 있기 때문이다. null이 아님을 확인(value &&)한 후, age 프로퍼티가 있는지(in) 검사하여 타입을 안전하게 좁힌 것이다.


요약

  1. 타입 좁히기: 조건문을 통해 더 구체적인 타입으로 범위를 좁히는 과정이다.
  2. typeof: number, string 등 원시 타입을 좁힐 때 사용한다.
  3. instanceof: Date 같은 내장 클래스나 사용자 정의 클래스를 좁힐 때 사용한다.
  4. in: 커스텀 객체 타입이나 인터페이스를 좁힐 때 특정 프로퍼티 유무를 확인하여 사용한다.
@taemni

@taemni

안녕하세요, 차근차근 성장 중인 조태민입니다.

instagram

댓글