学好TS,就靠这个系列(二)

1,025 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

序言:

这是搞定 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; 
// }

分析:题目是,将参数中的属性变为可选,其他不变,我们分析得出结论

  1. 首先获取到要变为可选的参数,我们用 pick 获取到参数中的属性,然后用Partial 将他们全部变为可选。
  2. 使用 Pick 和 Exclude 将不变化的参数拿出来.
  3. 将两个结果交叉类型,然后扁平处理
//获取处理完的交叉类型
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}

分析:题目要求我们可以过滤出给定类型的属性。我们的思路可以按照如下分析

  1. 遍历每一个属性,将他的类型约束于给定的类型,符合约束把该属性的类型赋值为属性名,不符合约束变成never
  2. 然后再把用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>>