Typescript: Conditional Types

@Troy Β· December 19, 2023 Β· 3 min read

Conditional Types 🀩

νƒ€μž…μŠ€ν¬λ¦½νŠΈμ—μ„œ 쑰건뢀 νƒ€μž…μ€ T extends U ? X : Y와 같은 ν˜•νƒœλ‘œ μ‚¬μš©λœλ‹€. μ΄λŠ” Tκ°€ U에 ν• λ‹Ή κ°€λŠ₯ν•œμ§€μ— λ”°λΌμ„œ X와 Y쀑 ν•˜λ‚˜μ˜ νƒ€μž…μ„ μ„ νƒν•˜κ²Œ λœλ‹€.

μ΄λŸ¬ν•œ λͺ¨μŠ΅μ€ κΈ°μ‘΄ javascript의 μ‚Όν•­μ—°μ‚°μžμ™€ μœ μ‚¬ν•˜κ²Œ λŠκ»΄μ§„λ‹€. (condition ? trueExpression : falseExpression)

interface Animal {
  live(): void;
}
interface Dog extends Animal {
  woof(): void;
}
 
type Example1 = Dog extends Animal ? number : string; // type Example1 = number
        

type Example2 = RegExp extends Animal ? number : string; // type Example2 = string

Genericκ³Ό ν•¨κ»˜ μ‚¬μš©ν•˜κΈ°

Genericκ³Ό ν•¨κ»˜ μ‚¬μš©ν•˜λ©΄ 더 μœ μš©ν•˜κ²Œ μ‚¬μš©ν•  수 μžˆλ‹€. λ‹€μŒ 예제λ₯Ό 보자.

// μ˜ˆμ‹œ 1  
type MessageOf<T> = T extends { message: unknown } ? T["message"] : never;

interface Email {
    message: string;
}

interface Dog {
    bark(): void;
}

type EmailMessageContents = MessageOf<Email>; // string

type DogMessageContents = MessageOf<Dog>; // never

// μ˜ˆμ‹œ 2
type Flatten<T> = T extends any[] ? T[number] : T;

// Extracts out the element type.
type Str = Flatten<string[]>; // type Str = string

// Leaves the type alone.
type Num = Flatten<number>; // type Num = number

Infer와 ν•¨κ»˜ μ‚¬μš©ν•˜κΈ°

inferλŠ” νƒ€μž…μŠ€ν¬λ¦½νŠΈμ—μ„œ νƒ€μž…μ„ μΆ”λ‘ ν•˜λŠ” ν‚€μ›Œλ“œμ΄λ‹€. inferλ₯Ό μ‚¬μš©ν•˜λ©΄ 쑰건뢀 νƒ€μž…μ„ μ‚¬μš©ν•΄ λ™μ μœΌλ‘œ νƒ€μž…μ„ μΆ”λ‘ ν•  λ•Œ μœ μš©ν•˜κ²Œ μ‚¬μš©ν•  수 μžˆλ‹€.

// μ˜ˆμ‹œ1
type Flatten<Type> = Type extends Array<infer Item> ? Item : Type;

//μ˜ˆμ‹œ2
type GetReturnType<Type> = Type extends (...args: never[]) => infer Return
  ? Return
  : never;
 
type Num = GetReturnType<() => number>; // number
 
type Str = GetReturnType<(x: string) => string>; // string

type Bools = GetReturnType<(a: boolean, b: boolean) => boolean[]>; // boolean[]

μ˜ˆμ‹œ 2λ₯Ό 보면 ν•¨μˆ˜μ˜ λ°˜ν™˜νƒ€μž…μ„ λ™μ μœΌλ‘œ λ³€κ²½ν•  수 있게 inferλ₯Ό μ΄μš©ν•΄ μΆ”λ‘ ν•œ μ˜ˆμ œλ‹€.

Distributive Conditional Types

Distributive Conditional TypesλŠ” 쑰건뢀 νƒ€μž…μ΄ μ‚¬μš©λ  λ•Œ μ „λ‹¬λ˜λŠ” νƒ€μž…μ΄ union으둜 κ΅¬μ„±λ˜μ–΄ 있으면 각각의 νƒ€μž…μ— 쑰건뢀 νƒ€μž…μ„ μ μš©ν•œ ν›„ union으둜 λ‹€μ‹œ 합쳐진닀.

type ToArray<Type> = Type extends any ? Type[] : never;
 
type StrArrOrNumArr = ToArray<string | number>; // string[] | number[]
@Troy
맀일의 μ‹œν–‰μ°©μ˜€λ₯Ό κΈ°λ‘ν•˜λŠ” κ°œλ°œμΌμ§€μž…λ‹ˆλ‹€.