typescript从嵌套对象中选取某个属性值类型

407 阅读1分钟

需求

对一个未知的ts嵌套对象类型,想筛选出未知层次的某个属性的值类型,如果不存在返回never

  • 如下,一个嵌套的类型定义
type Person = {
  name: string,
  age: number,
  family: {
    wife: {
      name: string,
      beauty: boolean,
      hobby: {
        buyBuyBuy: {
          level: number
        },
        eatEatEat: {
          what: string
        }
      }
    },
    self: {
      name: boolean,
      smart: {
        level: string
      }
    }
  }
}
  • 想要筛选出hobby或者what等等其他类型

实现

type DeepPick<T, K = string> = K extends keyof T
  ? T[K]
  : { [SubK in keyof T]: T[SubK] extends object ? DeepPick<T[SubK], K> : never }[keyof T];
  • 释义
  • 类型未知、key未知,显然要使用使用泛型
  • 最理想的情况,key就在根属性上,直接返回
  • 否则采用递归思路,对每一个属性值进行判断,如果是对象类型,递归筛选。
  • 重点

{ [SubK in keyof T]: T[SubK] extends object ? DeepPick<T[SubK], K> : never }[keyof T]

这句代码只是为了筛选出DeepPick<T[SubK], K>,不是太好理解,看看等价的下边的示例就明白了

有如下类型:type Animal = {name: {first: string, second: string}, age: number} 用上述的示例组合:type Test = {[K in keyof Animal]: Animal[K] extends object ? Animal[K] : never}

结果如下:图片.png 我们只是把值不为object的值类型标记为了never,但是我们还需要把值为object的类型筛选出来,所以还需要加上[keyof Animal]把非never的key筛选出来并得到对应的值类型 图片.png

回到最初

  • 通过DeepPick筛选eatEatEat的类型 图片.png
  • 如果想选择self下的name呢? 图片.png