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
맀일의 μ‹œν–‰μ°©μ˜€λ₯Ό κΈ°λ‘ν•˜λŠ” κ°œλ°œμΌμ§€μž…λ‹ˆλ‹€.