본문 바로가기

TIL

TIL - 타입스크립트 타입 가드와 타입 좁히기

개요

오늘은 타입스크립트의 타입 가드와 타입 좁히기 개념을 복습했습니다. 이러한 기능은 특정 스코프 내에서 올바른 타입을 보장하여 더 안전하고 정확한 코드를 작성할 수 있게 해줍니다. 주요 내용은 다음과 같습니다.

 

타입 가드와 타입 좁히기

2-1. typeof와 instanceof

타입 가드는 특정 스코프 내에서 변수의 타입을 보장하는 표현식입니다. 이를 통해 더 안전하고 명확한 코드를 작성할 수 있습니다.

 

function printAll(strs: string | string[] | null) {
    if (typeof strs === "string") {
        console.log(strs.toUpperCase());
    } else if (Array.isArray(strs)) {
        strs.forEach(s => console.log(s));
    } else {
        console.log("This is null");
    }
}

class Dog {
    bark() { console.log("Woof!"); }
}

class Cat {
    meow() { console.log("Meow!"); }
}

function animalSound(animal: Dog | Cat) {
    if (animal instanceof Dog) {
        animal.bark();
    } else {
        animal.meow();
    }
}

 

 

 

  • typeof는 기본 타입을 체크할 때 사용합니다.
  • instanceof는 클래스 인스턴스를 체크할 때 사용합니다.

 

2-2. in 연산자

in 연산자는 객체 내에 특정 속성이 존재하는지 확인할 때 유용합니다.

interface Admin {
    name: string;
    privileges: string[];
}

interface Employee {
    name: string;
    startDate: Date;
}

type UnknownEmployee = Employee | Admin;

function printEmployeeInfo(emp: UnknownEmployee) {
    console.log(`Name: ${emp.name}`);
    if ("privileges" in emp) {
        console.log(`Privileges: ${emp.privileges.join(", ")}`);
    }
    if ("startDate" in emp) {
        console.log(`Start Date: ${emp.startDate}`);
    }
}

 

 

2-3. 사용자 정의 타입 가드

사용자 정의 타입 가드는 타입 프레디케이트를 사용하여 타입스크립트에 특정 스코프 내의 타입을 알리는 방법입니다.

interface Bird {
    fly(): void;
    layEggs(): void;
}

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

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

function move(pet: Fish | Bird) {
    if (isFish(pet)) {
        pet.swim();
    } else {
        pet.fly();
    }
}

 

pet is Fish는 타입 프레디케이트로, isFish(pet) 함수가 true를 반환하면 pet이 Fish 타입임을 타입스크립트에 알려줍니다.

 

 

2-4. 식별 가능한 유니온 타입

식별 가능한 유니온 타입은 공통 속성을 사용하여 유니온 내의 다른 타입을 구분하는 방법입니다. 이는 타입 안정성을 높이고 코드의 명확성을 향상시킵니다.

interface Square {
    kind: "square";
    size: number;
}

interface Rectangle {
    kind: "rectangle";
    width: number;
    height: number;
}

interface Circle {
    kind: "circle";
    radius: number;
}

type Shape = Square | Rectangle | Circle;

function calculateArea(shape: Shape) {
    switch (shape.kind) {
        case "square":
            return shape.size * shape.size;
        case "rectangle":
            return shape.width * shape.height;
        case "circle":
            return Math.PI * shape.radius ** 2;
        default:
            return _exhaustiveCheck(shape);
    }
}

function _exhaustiveCheck(param: never): never {
    throw new Error(`Unhandled case: ${param}`);
}

 

 

  • 식별 가능한 유니온 타입을 사용하면 타입 안정성을 높이고, 코드의 가독성을 개선할 수 있습니다.
  • never 타입을 사용한 마지막 default 케이스는 모든 케이스를 처리했는지 컴파일 시점에 확인할 수 있게 해줍니다.

요약

타입스크립트의 타입 가드와 타입 좁히기 기능을 이해하고 활용하면 코드의 안전성과 가독성을 크게 향상시킬 수 있습니다. 오늘의 학습을 통해 이러한 중요한 개념들을 다시 한 번 되새기고, 앞으로의 프로젝트에서 더 나은 코드 품질을 유지할 수 있도록 하겠습니다.