본문 바로가기
프로그래밍/타입스크립트

타입스크립트 - 조건부 타입

by Programmer.Junny 2025. 2. 18.

1. 조건부 타입

두 가지의 타입에 조건을 걸어 특정 타입으로 반환하는 것을 의미한다.

type ObjA = {
    a: number,
}

type ObjB = {
    a: number,
    b: number,
}
type B = ObjB extends ObjA ? string : number;

ObjA가 ObjB에 속하는지를 삼항연산자로 작성하면 된다.

B타입은 ObjA가 ObjB에 속하므로 string을 반환하게 된다.

제네릭 조건부 타입

type StringNumberSwitch<T> = T extends number ? string : number;

let varA: StringNumberSwitch<number>    //string
let varB: StringNumberSwitch<string>    //number

제네릭과 조건부 타입을 결합할 수 있다. number와 string을 서로 변경하는 로직이다.

function removeSpaces<T>(text: T): T extends string? string : undefined;
function removeSpaces(text: any) {
    if (typeof text === 'string') {
        return text.replace(' ', '');
    } else {
        return undefined;
    }
}

let result = removeSpaces('hi good very');
result.toUpperCase();

let result2 = removeSpaces(undefined);

위의 로직은 매개변수인 text의 타입이 string인 경우엔 string을 그 외엔 undefined를 반환하도록 한다.

다만 메서드 내부에서는 T의 타입이 특정 타입으로 지정될 수 없기 때문에 as 문법을 써야하나 그러한 불편함을 해결하기 위해 오버로딩 시그니처로 해결한 로직이다.

2. 분산적 조건부 타입

type StringNumberSwitch<T> = T extends number ? string : number;
//타입을 유니온타입으로 지정하면, 분산적인 조건부 타입으로 변경된다.
let varC: StringNumberSwitch<number | string>
// StringNumberSwitch<number>   -> string
// StringNumberSwitch<string>   -> number
// 그러므로 varC 는 string | number 유니온 타입이 된다.

제네릭 조건부 타입에 유니온 타입으로 작성하게 되면, 기존 조건부 타입이 아닌 '분산적 조건부 타입' 으로 변경된다.

let d: StringNumberSwitch<boolean | number | string>;
// StringNumberSwitch<boolean>   -> number
// StringNumberSwitch<number>   -> string
// StringNumberSwitch<string>   -> number

각 타입별로 조건부 연산을 진행한 후 그 결과가 유니온 타입으로 반환된다.

type Exclude<T, U> = T extends U ? never : T;

type A = Exclude<number | string | boolean, string>;
// Exclude<number, string>  -> 거짓이므로 T가 되니깐 number
// Exclude<string, string>  -> 참이므로 never가 된다.
// Exclude<boolean, string> -> 거짓이므로 T가 되니깐 boolean
type Extract<T, U> = T extends U ? string : never;

type B = Extract<number | string | boolean, string>;

특정 타입을 제외하거나 특정 타입만을 포함하거나 하는 문법을 구현할 수 있게 된다.

3. infer (추론)

type ReturnType<T> = T extends () => infer R ? R : never;

inference의 약자인 infer는 추론을 의미한다.

infer R 은 () => R타입이 T에 속한다면 R 타입을을 반환하고 아닌 경우엔 never 타입을 반환한다.

type FuncA = () => string;
type FuncB = () => number;
type A = ReturnType<FuncA>; //string
type B = ReturnType<FuncB>; //number

type C = ReturnType<number>;    //never

FuncA는 () => string이고 이것이 () => string 타입에 속하므로 (부모 - 자식 관계) string을 반환한다.

type PromiseUnpack<T> = T extends Promise<infer R> ? R : never;

좀 더 자세한 예제로 Promise<Type>일 경우에 Type을 반환하도록 하는 예제이다.

type PromiseA = PromiseUnpack<Promise<number>>;	//number
type PromiseB = PromiseUnpack<Promise<string>>;	//string

최근댓글

최근글

skin by © 2024 ttuttak