Help us understand the problem. What is going on with this article?

ネストされたオブジェクトのプロパティをひたすらすべて列挙して、Union Typeにするワンライナー

More than 1 year has passed since last update.

どこで使えるのかはわからないけれど、ネストされたオブジェクトのプロパティをひたすらすべて列挙して、Union Typeにするワンライナーができたのでメモ

type ValueOf<T> = T[keyof T];
type Property<T> = keyof T | ValueOf<{[K in keyof T]: T[K] extends object ? Property<T[K]> : never}>

ワンライナーといいつつ2行あるのはご愛嬌

以下のような感じで使える

interface User {
  name: string,
  id: string,
  obj: {
    obj2: {
      aaa: string
    },
    bbb: string,
  }
}
type ValueOf<T> = T[keyof T];
type Property<T> = keyof T | ValueOf<{[K in keyof T]: T[K] extends object ? Property<T[K]> : never}>

type UserProperty = Property<User> //=> "name" | "id" | "obj" | "obj2" | "bbb" | "aaa"

image.png

ちなみにネストされているプロパティをチェックしなくて良いなら以下で事足りる

type Property<T> = keyof T //=> "name" | "id" | "obj"

深さ指定で所得できるようにする

もはやワンライナーではないけれど、以下のように書けば深さ指定でプロパティを所得できる

// 5階層まで対応。もっと深くまで辿りたい場合は 6:5 のように増やす
type NumMap = {
    5:4,
    4:3,
    3:2,
    2:1,
    1:1,
}

type ValueOf<T> = T[keyof T];
type Property2<T,P extends keyof NumMap> = P extends 1 ?  keyof T : ValueOf<{[K in keyof T]: T[K] extends object ? Property2<T[K], NumMap[P]> : never}>

以下のように使える

interface User {
  name: string,
  id: string,
  obj: {
    obj2: {
      aaa: string
    },
    bbb: string,
  }
}

type NumMap = {
    5:4,
    4:3,
    3:2,
    2:1,
    1:1,
}

type ValueOf<T> = T[keyof T];
type Property2<T,P extends keyof NumMap> = P extends 1 ?  keyof T : ValueOf<{[K in keyof T]: T[K] extends object ? Property2<T[K], NumMap[P]> : never}>

type UserProperty = Property2<User,2> //=> "obj2" | "bbb"

image.png

まとめ

TypeScriptすごい

参考

https://www.typescriptlang.org/docs/handbook/advanced-types.html#index-types

KuwaK
TypeScriptが好きです
fujitsu
富士通グループのソフトウェア技術者有志により運営しているコミュニティです。
http://www.fujitsu.com/jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away