小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
序言:
这是搞定 TS 第二篇,如果没有基础的小伙伴想要从零搞定 TS ,请从第一篇开始juejin.cn/post/701033…
第一题
如何定义一个 SetOptional 工具类型,支持把给定的 keys 对应的属性变成可选的
type Foo = {
a: number;
b?: string;
c: boolean;
}
// 测试用例
type SomeOptional = SetOptional<Foo, 'a' | 'b'>;
// type SomeOptional = {
// a?: number; // 该属性已变成可选的
// b?: string; // 保持不变
// c: boolean;
// }
分析:题目是,将参数中的属性变为可选,其他不变,我们分析得出结论
- 首先获取到要变为可选的参数,我们用 pick 获取到参数中的属性,然后用Partial 将他们全部变为可选。
- 使用 Pick 和 Exclude 将不变化的参数拿出来.
- 将两个结果交叉类型,然后扁平处理
//获取处理完的交叉类型
type setOptional <T , K extends keyof T> =
Partial<Pick<T , k>> & Pick< T, Exclude<keyof T ,K>>
//数组扁平处理
type flattening <T> =
{[P in keyof T] : T[P]}
//最终版本
type flattening <T> =
{[P in keyof T] : T[P]}
type setOptional <T , K extends keyof T> =
flattening<Partial<Pick<T , k>> & Pick< T, Exclude<keyof T ,K>>>
第二题
何定义一个 ConditionalPick 工具类型,支持根据指定的 Condition 条件来生成新的类型,对应的使用示例如下
interface Example {
a: string;
b: string | number;
c: () => void;
d: {};
}
// 测试用例:
type StringKeysOnly = ConditionalPick<Example, string>;
//=> {a: string}
分析:题目要求我们可以过滤出给定类型的属性。我们的思路可以按照如下分析
- 遍历每一个属性,将他的类型约束于给定的类型,符合约束把该属性的类型赋值为属性名,不符合约束变成never
- 然后再把用pick 从 对象中 把不为never的属性拿出来
//首先我们定义一个拿出符合要求的key的方法
type ConditionalKeys<T, K> = {
[P in keyof T ] : T[P] extends K ? P: never
}[keyof T]
/**
结果为:{a:a;b:never:c:never:d:never}[a|b|c|d]=>
a|never|never|never=>
a
**/
//然后我们通过Pick将符合的key对应的属性拿出来
type ConditionalPick<T ,Conditional> = Pick< T , ConditionalKeys<T, Conditional>>