Typescript: Conditional Types

@choi2021 ยท 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[]
@choi2021
๋งค์ผ์˜ ์‹œํ–‰์ฐฉ์˜ค๋ฅผ ๊ธฐ๋กํ•˜๋Š” ๊ฐœ๋ฐœ์ผ์ง€์ž…๋‹ˆ๋‹ค.