起源: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>
复制代码
就先介绍到这里啦,目前大四,明年就要去网易搬砖啦,码字不易,顺手点个赞呗,感激大佬。
结语
我是林三心,一个热心的前端菜鸟程序员。如果你上进,喜爱前端,想学习前端,那咱们能够交朋友,一起摸鱼哈哈,摸鱼群,加我请备注【思否】