ts의 유용한 타입 가드 방법

eeensu·2025년 8월 1일

Typescript

목록 보기
25/25

요소가 객체 또는 배열 내에서의 존재 여부를 확인하는 법?

in 연산자를 사용하는 방법이 있다. 인덱스가 해당 객체나 배열에 존재하는지 확인하는 데 사용된다. 이는 js에서도 동일하게 동작하며, ts 타입 시스템에서 이 연산자가 적절히 사용될 수 있도록 추가적인 타입 체크를 제공한다.

  • 객체의 속성 확인
interface Person {
  name: string;
  age: number;
  address?: string; // 선택적 속성
}

const person: Person = {
  name: "John",
  age: 30,
};

if ("address" in person) {
  console.log("Address exists:", person.address);
} else {
  console.log("Address does not exist");
}

  • 배열의 인덱스 확인
const arr = [10, 20, 30];

if (2 in arr) {
  console.log("Index 2 exists:", arr[2]);
} else {
  console.log("Index 2 does not exist");
}

  • 유니온 타입을 좁히는 데 사용
type Bird = { fly: () => void; };
type Fish = { swim: () => void; };

function move(animal: Bird | Fish) {
  if ("fly" in animal) {
    animal.fly(); // TypeScript는 여기서 animal을 Bird 타입으로 좁힘
  } else {
    animal.swim(); // TypeScript는 여기서 animal을 Fish 타입으로 좁힘
  }
}



리터럴 타입(as const)로 정의된 배열내의 요소들의 타입을 추출하는 법

리터럴 타입으로 정의된 각 요소에 접근할 수 있는 타입을 정의할 수 있다.

const array = [
    'Frontend',
    'Backend',
    'Full-Stack',
    'Mobile',
    43,
    23,
    {
        name: 'Design',
        stack: ['Figma', 'Sketch', 'Adobe XD'],
    },
] as const

export type ArrayItem = (typeof array)[number]

// ArrayItem 의 타입은 아래와 같다.
type ArrayItem = "Frontend" | "Backend" | "Full-Stack" | "Mobile" | 43 | 23 | {
    readonly name: "Design";
    readonly stack: readonly ["Figma", "Sketch", "Adobe XD"];
}



is 키워드를 통한 타입 추론

타입가드란, 특정 스코프 내에서 변수의 타입을 보장하는 표현식이다. 조건문 내에서 변수의 타입을 좁혀주는 역할을 한다.

is 함수의 반환 타입을 정의할 때 사용하며, 주로 사용자 정의 타입 가드를 만들 때 활용한다. as가 특정 변수하나에만 적용되는 것과 달리, is는 한정된 범위 내의 모든 변수에 대해 일괄적으로 타입을 적용한다.

is를 통해 타입가드를 적용하면, ts 컴파일러가 조건문 내에서 변수의 타입을 정확하게 추론할 수 있게 되어, 타입 안전성을 높이고 코드의 가독성도 향상시킬 수 있다.

// 기본적인 is 사용 예시
const isString = (value: any): value is string => {
  return typeof value === 'string';
};

const processValue = (value: string | number) => {
  if (isString(value)) {
    // 여기서 value는 string 타입으로 처리됨
    return value.toUpperCase();
  } else {
    // 여기서 value는 number 타입으로 처리됨
    return value * 2;
  }
};

커스텀 타입에서도 활용이 가능하다.
interface Bird {
  fly(): void;
  layEggs(): void;
}

interface Fish {
  swim(): void;
  layEggs(): void;
}

const isFish = (pet: Fish | Bird): pet is Fish => {
  return (pet as Fish).swim !== undefined;
}

const move = (pet: Fish | Bird) => {
  if (isFish(pet)) {
    // 여기서 pet은 Fish 타입으로 확정됨
    pet.swim();
  } else {
    // 여기서 pet은 Bird 타입으로 확정됨
    pet.fly();
  }
}

ts의 infer 는 조건부 타입(conditional types)과 함께 사용되는 도구로, 다른 타입에서 정보를 추론하여 사용할 수 있게 해준다. 주로 복잡한 타입을 다루거나, 함수의 리턴 타입, 제네릭 타입의 구성 요소를 자동으로 추출할 때 매우 유용하다.




infer 키워드를 통한 타입 추론

타입 내에서 특정한 부분을 추론할 때, extends 와 함께 사용할 수 있다. 이때 내부에서 다른 타입의 일부를 추론하고 그 추론된 결과를 타입 시스템에 사용할 수 있도록 한다

type Example<T> = T extends (x: infer U) => any ? U : never;

위 방법은, infer U 가 함수 타입일 때, 함수의 매개변수 타입을 추론하여 U에 할당하는 역할을 한다. any 타입에 할당 가능하다면, 매개변수 타입을 U로 추론하고 만약 T가 함수 타입이 아니라면 never를 반환하는 것이다.


함수의 리턴 타입을 자동으로 추론하여 타입으로 사용할 수 있다.

type ReturnTypeOf<T> = T extends (...args: any[]) => infer R ? R : never;

function getString(): string {
  return "Hello, TypeScript!";
}

  // Result는 string 타입이 된다.
type Result = ReturnTypeOf<typeof getString>; 

사실 위 예제는 ReturnType 이라는 이미 ts 에서 제공하는 유틸리티 타입이 있다. 그 유틸리티 타입을 직접 만들어 본것이다.


배열의 요소 타입을 추출하기

이 타입은 T가 배열일 경우 그 요소 타입을 추론해서 U에 넣고, 배열이 아닌 경우엔 그냥 T를 반환하도록 한다.

type ElementType<T> = T extends (infer U)[] ? U : T

type StringArray = string[];
type NumberArray = number[];

type StringElement = ElementType<StringArray>; // StringElement는 string 타입
type NumberElement = ElementType<NumberArray>; // NumberElement는 number 타입
profile
안녕하세요! 프론트엔드 개발자입니다! (2024/03 ~)

0개의 댓글