Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
中等
Readonly 2
type MyReadonly2<T, K extends keyof T = keyof T> = Readonly<Pick<T, K>> & Omit<T, K>
- 首先使用
Pick将K类型的键挑选出来组成新的类型,然后通过Readonly变为只读的对象,这样就达到了将部分属性变为readonly的目的了 - 那么另外一部分属性就使用
Omit来创建新的类型 - 最后通过
&操作符组成交叉类型
深度 Readonly
type DeepReadonly<T> = {
readonly [P in keyof T]: T[P] extends Record<string, unknown> ? DeepReadonly<T[P]> : T[P];
}
- 主要在于判断
T[P]的值类型是不是对象,是的话要进行递归处理
元组转合集
type Mapping<T extends readonly any[]> = {
[P in T[number]]: P;
}
type TupleToUnion<T extends readonly any[]> = keyof Mapping<T>;
- 先将数组中的元素组装成一个对象类型,也就是
Mapping - 然后通过
keyof就可以获取到数组元素的联合类型了
我在解答区看到的👍比较多的答案:
type TupleToUnion<T> = T extends Array<infer Item> ? Item : never;
type TupleToUnion<T extends readonly any[]> = T[number];
可串联构造器
type Chainable<T = {}> = {
option<K extends string, V>(key: Exclude<K, keyof T>, value: V): Chainable<T & Record<K, V>>,
get(): T;
}
分成几步来进行分析:
type Chainable<T = {}> = {
option<K extends string, V>(key: K, value: V): Chainable<T & Record<K, V>>,
get(): T;
}
- 每次调用
option方法时,需用将key与value的类型组成一个对象类型,为了获取到这两个字段的类型,所以要给option()添加泛型K和V,再用Record进行组合。 - 泛型
T是用来累加键值对类型的,而每次调用时,需要跟上次的类型进行合并,所以使用了操作符&变为交叉类型 - 最后就是每次调用
option()返回的都是当前键值对累加的对象类型,这样就可以持续将该对象类型顺着链条传递下去了
由于同样的key只能使用一次,所以要对泛型K进行约束,也就有了最终的形式:
type Chainable<T = {}> = {
// 使用 Exclude 进行排除重复的 key
option<K extends string, V>(key: Exclude<K, keyof T>, value: V): Chainable<T & Record<K, V>>,
get(): T;
}
答案参考自解答区,作者还对该类型进行了扩展,感兴趣的可以了解下。