起源:https://juejin.cn/post/705294...
作者:Angus安格斯

前言

最近在写React时定义变量类型时,无心点到了ElementType,而后在node_modules/@types/react/index.d.ts 中发现了这段代码:

牛啊,尽管我没太看懂,然而就是感觉挺牛的。

Google一下

然而起初咱一Google,发现网上管这个叫类型过滤,是一个实用的TS写法。\
来看上面这个:

 interface Example{     a:string;     b:number;     c:number;     d:string;     ...      }复制代码

咱们有一个Example的接口,然而咱们当初想对这个接口做一些解决,只心愿留下类型为string的属性,这样咱们应该咋做?就能够应用咱们本人定义的FilterType。

    type newExample = FilterType<Example,string> // {a:string;d:string;...}复制代码

咱们来看看FilterType是如何实现的:

    type FilterType<Source, Types> = Pick<      Source,       {        [K in keyof Source]: Source[K] extends Types ? K : never      }[keyof Source]    >;复制代码

剖析

首先咱们先来看看代码中呈现的几个utility types。(大佬间接跳过)

in

in 能够遍历枚举类型,相似 for...in

type Example = 'a' | 'b' | 'c' | 'd'type Obj = {  [T in Example]: string;  // 遍历Example,把每个key都赋值string类型}/* 等价于   type Obj = {    a: string;    b: string;    c: string;    d: string;  }*/复制代码

keyof

TS官网文档中把它称作索引类型查问操作符,其实就是取到类型的key,相似Object.keys() 尽管我不晓得这样类比对不对。

interface Example {    a: string;    b: string;    c: number;    d: boolean;}    type Keys = keyof Example   // 等价于 type Keys = 'a' | 'b' | 'c' | 'd'复制代码

条件判断

interface A {    a:string;}interface B extends A {    b:string;} // B是否继承于A?若是,则为number类型;若不是,则为string类型type C = B extends A ? number : string  // 等价于 type C = number复制代码

开始分析

先看一个,揭开她的面纱,不,是口罩:

type Mask<source,types> = {    [K in keyof source]:source[K] extends types ? K : never;}interface Example{    name:string;    height:number}type newType = Mask<Example,string> // { name:'name'; height:never}复制代码

这时候咱们看到一个{ name:'name'; height:never} ,what??? 这有啥用?

别急!接下来咱们持续看上面这个例子,揭开她的外套:\
来看一个能够记在笔记本上的小知识点:索引拜访接口属性

type person = {     name:"Angus";    height:185;}["name" | "height"]复制代码

等价于:

type person = "Angus" | 185复制代码

留神的是,当value为never时,就会拜访不到

type person = {     name:"Angus";    height:185;    girlFriend:never;}["name" | "height" | "girlFriend"]复制代码

等价于

type person = "Angus" | 185复制代码

(singleDog的自嘲

那晓得了索引拜访接口属性有啥用呢?来看上面这个,揭开她的clothes:

type Clothes<source,types> = {    [K in keyof source]:source[K] extends types ? K : never;}[keyof source]interface Example{    name:string;    height:number;    home:string}type newType = Clothes<Example,string> // type newType = "name | home"复制代码

这样咱们就能拿到咱们想要的类型的联结类型。\
最初一步,咱们揭开*\
hold on ,咱们先理解一下Pick。\
Pick是在一个类型对象中,筛选几个类型,组成一个新的的类型。

interface Angus{    name:string;    height:number;    wight:number;}type newAngus = Pick<Angus,'name' | 'height'> //{name:string;height:number}复制代码

它的实现:

    type Pick<T,K extends keyof T> = {        [P in K] : T[P];    }复制代码

而后咱们来看Google上的那个:

type FilterType<Source, Types> = Pick<      Source,       {        [K in keyof Source]: Source[K] extends Types ? K : never      }[keyof Source]    >;复制代码

是不是茅厕顿开!!!通过Pick就能够筛选咱们想要的属性了。

    {       [K in keyof Source]: Source[K] extends Types ? K : never     }[keyof Source]复制代码

这两行的代码就能拿到咱们想要的属性。再通过Pick一下就完事。有没有被秀到?

拓展

那咱们再来看看TS中其余的一些工具类型吧

Omit

Omit(a,b) 接管两个参数,第一个是要编辑的根本类型,第二个是你要删除的类型。

    type Person = {        name:string;        sex:string;    }    type newPerson = Omit<Person,'name'> // {sex:string}复制代码

看看它咋实现的:

    type Omit <T,K extends keyof any> = Pick<T,Exclude<keyof T,K>>;复制代码

Partial

Partial 能够疾速把某个接口类型中定义的属性变成可选的(Optional)

    type Person = {        name:string;        sex:string;    }    type newPerson = Partial<Person> // {name?:string;sex?:string}复制代码

看看它咋实现的:\

    type Partial <T> = {        [P in keyof T]?: T[P]    }复制代码

Exclude

用于删除类型汇合中的指定类型.

    type a = string | number    type newPerson = Exclude<a,string>  //number复制代码

实现:

    type Exclude<T, U> = T extends U ? never : T复制代码

Readonly

将接口所有属性变为只读的.

    type Person = {        name:string;        sex:string;    }    type newPerson = Readonly<Person>     // type newPerson = {readonly name: string;readonly sex: string;}复制代码

实现:

    type Readonly<T> = { readonly [P in keyof T]: T[P]; }复制代码

ReturnType

ReturnType的作用是用于获取函数 T 的返回类型。\

    type T0 = ReturnType<() => string>; // string     type T1 = ReturnType<(s: string) => void>; // void    type T2 = ReturnType<() => T>; // {}     type T3 = ReturnType<() => T>; // number[]     type T4 = ReturnType; // any     type T5 = ReturnType; // any     type T6 = ReturnType; // Error     type T7 = ReturnType; // Error复制代码

实现:

    type ReturnType any> = T extends (...args: any) => infer R ? R : any;复制代码

Parameters

Parameters的作用是用于获取函数 T 的参数类型。

type getuserInfo = (user: string) => void// Parameters<T>的作用是用于获取函数 T 的参数类型。type ParametersUserInfo = Parameters<getuserInfo>复制代码

就先介绍到这里啦,目前大四,明年就要去网易搬砖啦,码字不易,顺手点个赞呗,感激大佬。

结语

我是林三心,一个热心的前端菜鸟程序员。如果你上进,喜爱前端,想学习前端,那咱们能够交朋友,一起摸鱼哈哈,摸鱼群,加我请备注【思否】