≪ Today I learned. RSS購読
公開日
タグ
TypeScript
著者
ダーシノ(@bc_rikko)

オブジェクトのプロパティを連結してUnion型をつくる

オブジェクトのプロパティを連結してFoo | Foo.Bar | Foo.Bar.BazのようなUnion Typeがほしいときがある。

type Primitive =
  | null
  | undefined
  | string
  | number
  | boolean
  | symbol
  | bigint

type PathImpl<K extends string | number, V> =
  V extends Primitive
    ? `${K}`
    :`${K}` | `${K}.${Path<V>}`

type Path<T> =
  T extends ReadonlyArray<infer V>
    ? PathImpl<number, V>
    : {
      [K in keyof T]-?: PathImpl<K & string, T[K]>
    }[keyof T]

これをこうすると…

type Item = {
  Foo: {
    Bar: {
      Baz: string
    }
  }
  Hoge: {
    Fuga: string
  }
}

type test = Path<Item>
//   ^? 'Foo' | 'Foo.Bar' | 'Foo.Bar.Baz' | 'Hoge' | 'Hoge.Fuga'