string转object对象_TypeScript 随记 —— 如何推导出 interface 中值为string的key的类型...

TypeScript 随记 —— 如何推导出 interface 中值为string的key的类型

在使用TypeScript的时候,我们有时需要提取某个 interface/object 中某些类型的key的类型来作为高阶函数的参数或者某个函数的返回值。

下面的例子里,我们有一个用户的object,其具有一些基本属性和方法,现在我们希望对外提供一个方法来获取用户的某项信息。

在只使用TypeScript的基本特性时,你需要这样做:

interface User {
  name: string
  location: string
  job: string
}
​
let user: User = {
  name: 'ArrayZoneYour',
  location: 'Beijing',
  job: 'FE',
  update: (info: User) => {
    user = { ...user, ...info }
  }
}
​
const getUserInfo: (key: 'name' | 'location' | 'job'): string => user[key]

看到这里我们需要手动标注属性为字符串的键的类型 'name'|'location'|'job',但是在user这个对象有很多的key的时候是很麻烦且不具有扩展性的。我们更希望可以有一个泛型方法来帮我们来提取这些key

const getUserInfo: (key: ExtractStringKey<typeof user>) => user[key]

那么如何实现这样一个方法呢?


思考空间


解决这个问题之前,我们先从另一个问题(如何在TypeScript 2.8之前实现Omit)的解决方案出发:

// Functionally the same as Exclude, but for strings only.
type Diff<T extends string, U extends string> = ({[P in T]: P } & {[P in U]: never } & { [x: string]: never })[T]
type Omit<T, K extends keyof T> = Pick<T, Diff<keyof T, K>>

注意上面的Diff方法,它构造了一个 key: (key / never) 的object,T中出现过的key如果在U中出现了,key的value会被覆写为never,而此时再用所有的key [T] 去访问,可能获得的类型已经不包括被U覆写的key了。

那么我们是不是也可以构造两个object,原来的object的key的类型作为T,然后再生成一份object的key的类型,并将非string类型的key的值类型置为never,然后再用[T]去访问可获得的类型呢?

// 生成一份object的key的类型,并将非 T 继承类型的key的值类型置为 never
type ExtractType<O, T> = { [K in keyof O]: O[K] extends T ? O[K] : unknown }
​
// 组合两个 object 的类型
type Diff<T extends string, U> = ({ [P in T]: P } &
  { [P in keyof U]: U[P] extends string ? string : never } & {
    [x: string]: never
  })[T]
​
// 这里我们只以 string 类型的key作为示例
type ExtractStringKey<A> = Diff<
 Extract<keyof A, string>,
 ExtractType<A, string>
>

以浏览器的Location类型为例Check一下:

7d11db6da91b559cae282f0a402ef797.png

replace, reload 是方法的键

72f84a4ceca28c02a0e6f19edcf7c8d3.png

Done.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值