본문 바로가기
프론트엔드/TS 공부

타입 좁히기 - 타입 가드의 종류

by 학습하는 청년 2024. 5. 28.

최종 수정 : 2024-05-29

타입 좁히기

조건문 등을 이용해 타입을 상황에 따라 좁히는 방법


타입 가드(Type Guard)

타입 좁히기를 도와준다.

특정 스코프 내에서 사용되는 타입을 런타임에 체크하는 일종의 표현이다.

종류

typeof, instanceof, 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') {
  // typeof value === 'object'라고 하면 'Date | null'로 추론되어 불가능
    console.log(value.getTime());
  } else if (value && 'age' in value) {
    console.log(`${value.name}은 ${value.age}살 입니다`);
  }
};

 

1) typeof

원시 타입에 대해 적합하다.

추후 기입

 

2) instanceof

객체가 특정한 클래스에 속해 있는지 확인할 수 있다.

class Foo {
  common = '123';
  foo = 123;
}

class Bar {
  common = '123';
  bar = 123;
}

const func = (arg: Foo | Bar) => {
  if (arg instanceof Foo) {
    console.log(arg.foo);
    console.log(arg.bar); // Error
  }
  if (arg instanceof Bar) {
    console.log(arg.foo); // Error
    console.log(arg.bar);
  }
  
  console.log(arg.common);
  console.log(arg.foo); // Error
  console.log(arg.bar); // Error
};

func(new Foo());
func(new Bar());

 

3) in

객체 내부에 특정 프로퍼티가 존재하는지 확인하는 연산자

interface Human {
  think: () => void;
}

interface Dog {
  tail: string;
  bark: () => void;
}

const func = (x: Human | Dog) => {
  if ('tail in x) {
    x.bark(); // type x: Dog
  } else {
    x.think(); // type x : Human
  }
};

 

4) 리터럴 타입 가드

리터럴 타입은 ===, ==, !==, != 연산자 또는 switch를 통해 타입 가드할 수 있다. 특히 요소가 많아질수록 swich의 가독성과 성능이 더 좋다.

리터럴 타입 : 특정 타입에 속하는 구체적인 값들
type States = 'pending' | 'fulfilled' | 'rejected';

// 방법 1. 동등, 일치 연산자
const func = (state: States) => {
  if (states === 'pending') {
    pendingFunc(); // type state : 'pending'
  } else if (state === 'fulfilled') {
    fulfilledFunc(); // type state : 'fulfilled'
  } else {
    rejectedFunc(); // type stste : 'rejected'
  }
};

// 방법 2. switch
const func = (state: States) => {
  switch (state) {
    case 'pending':
      pendingFunc(); // type state : 'pending'
      break;
    case 'fulfilled':
      fulfilledFunc(); // type state : 'fulfilled'
      break;
    case 'rejected':
      rejectedFunc(); // type state : 'rejected'
      break;
  }
};

 

5) 서로소 유니온 타입

교집합이 없는 타입들로만 만든 유니온 타입이다. 주로 tag로 구분지어 표현하기 때문에 taged union 타입이라 불리기도 한다.

ex) 권한에 대한 / 비동기 작업의 결과를 처리하는 객체를 표현하기에 좋다.

type Admin = {
  tag: "ADMIN",
  name: string;
  kickCount: number;
};

type Member = {
  tag: "MEMBER",
  name: string;
  point: number;
};

type Guest = {
  tag: "Guest",
  name: string;
  visitCount: number;
};

type User = Admin | Member | Guest;

function login(user:User) {
  if ("kickCount" in user) {
    console.log(`${user.name}님 현재까지 ${user.kickCount}명 강퇴했습니다.`);
  } else if ("point" in user) }
    console.log(`${user.name}님 현재까지 ${user.point} 모았습니다.`);
  } else {
  	console.log(`${user.name}님 현재까지 ${user.visitCount}번 방문하셨습니다.`);
  }
};


위의 코드는 직관적이지 않다. 서로소 유니온 타입을 활용하여 바꾸면 훨씬 직관적이다.

function login(user: User) {
  switch (user.tag) {
    case "ADMIN": {
      console.log(`${user.name}님 현재까지 ${user.kickCount}명 강퇴했습니다.`);
      break;
    }
    case "MEMBER" {
      console.log(`${user.name}님 현재까지 ${user.point} 모았습니다.`);
      break;
    }
    case "GUEST" {
      console.log(`${user.name}님 현재까지 ${user.visitCount}번 방문하셨습니다.`);
      break;
    }
  }
}

 

6) 사용자 정의 타입가드

사용자 정의 타입 가드는 주로 isTypeName 형태의 함수명을 많이 사용한다.

type Dog = {
  name: string;
  isBark: boolean;
};

type Cat = {
  name: string;
  isScratch: boolean;
};

type Animal = Dog | Cat;

function isDog(animal: Animal): animal is Dog {
  return (animal as Dog).isBark !== undefined
}

function isCat(animal: Animal): animal is Cat {
  return (animal as Cat).isScratch !== undefined;
}

function warning(animal: Animal) {
  if (isDog(animal)) {
    animal;
  } else if (isCat(naimal)) {
    animal;
  }
}

'프론트엔드 > TS 공부' 카테고리의 다른 글

함수 타입의 호환성  (0) 2024.05.28
함수 타입 정의 / 함수 타입 표현식과 호출 시그니처  (0) 2024.05.28
타입 단언  (0) 2024.05.28
타입 추론  (0) 2024.05.28
설치하기  (0) 2024.05.27

댓글