TypeScript

[TypeScript] 타입스크립트 타입 단언과 타입 가드

깅민 2025. 5. 26. 10:57

1. 타입 단언

타입 단언은 다음과 같이 적용할 수 있습니다.

A as B

 

  • A가 B의 슈퍼타입
  • A가 B의 서브타입

타입 단언은 위의 두 조건을 만족해야합니다.

 

// never는 모든 타입의 서브타입
let str1 = "a" as never;
// unknown은 모든 타입의 슈퍼타입
let str2 = "a" as unknown;
// 에러, 두 가지의 관계가 아님
let str3 = "a" as number;

 

1-1. 빈 객체로 초기화하고 싶을 때

type Jacket = {
  size: string,
  price: number
};

let jacket1: Jacket = {}; // 에러

let jacket2: Jacket = {} as Jacket;

let jacket3 = {} as Jacket;

let jacket4 = { // 초과 프로퍼티 검사
  size: "a",
  price: 1
} as Jacket

 

{} 로 초기화하려고 하면 이 빈 객체는 Jacket 타입이 아니니 오류가 발생합니다.

 

이럴 때, as 타입으로 타입을 단언할 수 있습니다.

 

1-2. const 단언

const로 변수를 선언한 것처럼 사용할 수 있습니다.

let no = 1 as const;

 

1-3. 다중 단언

다중으로 단언하는 것도 가능합니다.

let no = 1 as unknown as number;

 

1-4. Not Null 단언

값 뒤에 ! 를 붙여주면

이 값이 undefined 이거나 null 이 아닐 것으로 단언할 수 있습니다.

 

주의할 점은 컴파일에만 적용되고

실제로 값이 없다면 런타임에서 오류가 발생할 수 있습니다.

type Jacket = {
  size: string;
  price: number;
  limitedEdition?: boolean;
};

let jacket: Jacket = {
  size: "a",
  price: 10,
  limitedEdition: true,
};

const isLimited: boolean = jacket.limitedEdition; // 에러

const isLimited: boolean = jacket.limitedEdition!;

 

2. 타입 가드

typeof, instanceof, in 등을 사용해서

타입을 분기할 수 있습니다.

function guard(value: number | string) {
  if (typeof value === "number") {
    console.log("number");
  } else if (typeof value === "string") {
    console.log("string");
  }
}
guard(1);
guard("test");

 

2-1. 사용자 정의 타입 가드 (타입 가드 함수)

type Dollar = {
  name: string;
  isAmerican: boolean;
};

type Won = {
  name: string;
  isKorean: boolean;
};

type Currency = Dollar | Won;

function useCurrency(currency: Currency) {
  if ("isAmerican" in currency) {
    console.log(currency.isAmerican ? "미국인이 씁니다" : "미국인이 안 씁니다");
  } else if ("isKorean" in currency) {
    console.log(currency.isKorean ? "한국인이 씁니다" : "한국인이 안 씁니다");
  }
}

const obj = {
  name: "달러",
  isAmerican: true,
} as Dollar;

useCurrency(obj);

 

위의 예시처럼 문자열로 비교하는 것 보다는

아래 처럼 타입 가드를 만들어서 사용하는 것이 좋습니다.

type Dollar = {
  name: string;
  isAmerican: boolean;
};

type Won = {
  name: string;
  isKorean: boolean;
};

type Currency = Dollar | Won;

function isDollar(currency: Currency): currency is Dollar {
  return (currency as Dollar).isAmerican !== undefined;
}
function isWon(currency: Currency): currency is Won {
  return (currency as Won).isKorean !== undefined;
}

function useCurrency(currency: Currency) {
  if (isDollar(currency)) {
    console.log(currency.isAmerican ? "미국인이 씁니다" : "미국인이 안 씁니다");
  } else if (isWon(currency)) {
    console.log(currency.isKorean ? "한국인이 씁니다" : "한국인이 안 씁니다");
  }
}

const obj = {
  name: "달러",
  isAmerican: true,
} as Dollar;

useCurrency(obj);

 

사용자 정의 함수는

A is B 처럼 작성할 수 있습니다.

return 이 true라면 타입이 B 라고 컴파일러에게 알려줄 수 있습니다.

타입을 좁혀줄 수 있는 것이죠.