ts中的条件类型
- 什么是条件类型,就是满足某个条件给一个类型,不满足则给另外一个类型
举例说明:
interface Fish{
name:string,
type:'鱼'
}
interface Bird {
name:string,
type:'鸟'
}
interface Swiming{
swiming:string
}
interface Sky {
sky:string
}
type MyType<T> = T extends Bird ? Sky:Swiming
type IEnv = MyType<Fish>
思考:那么上面中type IEnv得到的是什么类型
- 解析:传入的Fish,那么他就不满足Bird类型,就得到类型type IEnv =
Swiming,就好比我们常规的三元表示式一样,满足一个条件得到前面,否则就得到后面的
type IEnv = Swiming
针对上面的例子,再次提问:如果我们传入是Fish | Bird这种格式,那么得到的是什么
type IEnv = MyType<Fish | Bird>
- 解析:得到的结果如下
type IEnv = Swiming | Sky
为什么会得到上面的结果,那就是 | 符号
是可以分发的,如果是传入的是一个联合类型,他会进行条件分发
,就好像下面这样,那么我们也可以理解到为什么可以得到上面的结论了。
Fish extends Bird | Bird extends Bird
再次提问,如果我传入的是下面情况,会得到什么:
type IEnv = MyType<Fish & Bird>
解析:
type IEnv = Sky
- 为什么会得到IEnv=sky呢?Fish & Bird是不会进行条件分发的,Fish & Bird得到的类型是never
- never是所有类型的子类型,never被认为是空的联合类型,也就是说,没有联合项的联合类型,所以还是满足上面的分配律
内置条件类型
1.Exclude
- Exclude,就好像他的名字一样,在多个类型中排除到某几个类型
用法:
- 在几个类型中,排除掉一个类型
type MyExclude = Exclude<string | number | boolean, boolean>
//得到的结果
type MyExclude = string | number
//排除掉多个类型
type MyExclude = Exclude<string | number | boolean, boolean | number>
type MyExclude = string
实现方法:
type Exclude<T,K> = T extends K ? never : T
2.Extract
- Extract,多个属性中 抽离某一个或者某几个属性,跟Exclude是反着来的
用法:
type MyExtract = Extract<string | number | boolean, boolean>
type MyExtract = boolean
实现方法:
type Extract<T, K> = T extends K ? T : never;
3.NonNullable
- NonNullable:在多个类型中排除null类型
用法:
type MyNonNullable = NonNullable<string | number | null | undefined>
实现方法:
type NonNullable<T> = T extends null | undefined ? never : T;
4.infer推断
- 需求:获取函数的返回值,infer放在那里,就是推断那里的结果
- infer 要配合extends关键字,否则无法使用 infer有推断类型的功能,可以自动推断出结果
需求1:获取函数的返回值的类型
function getSchool(x: string, y: number) {
return { name: 'zf', age: 12 }
}
- 使用ReturnType内置条件,得到返回
type MyReturnType = ReturnType<typeof getSchool>
//得到的返回值如下
type MyReturnType = {
name: string;
age: number;
}
● 实现原理
type ReturnType<T extends ((...args: any[]) => any)> = T extends ((...args: any[]) => infer R) ? R : any
需求2:获取到函数参数返回的类型
type MyConstructorParameters = ConstructorParameters<typeof Person>
type MyParameters = [x: string, y: number]
- 实现原理
type Parameters<T extends ((...args: any[]) => any)> = T extends (...args: infer P) => any ? P : any
ts中的内置类型
- 下面用到的通用例子
interface ICompany {
name: string,
address: string
}
interface IPerson {
name?: string,
age: number,
company?: ICompany
}
1.Partial
- 当我们一个接口中,不确定那些是必填的东西,想要全
部改为非必填
的 - Partial:表示选项可以是选填的 ,默认不是
深度递归
type MyPerson = Partial<IPerson>
//调用后得到如下结果,把所有选项都标识成了非必填项
type MyPerson = {
name?: string | undefined;
age?: number | undefined;
company?: ICompany | undefined;
}
- 实现原理
type Partial<T> = [K in keyof T]? : T[K]
- 但是在我们写company的时候发现,company里面的东西还都是必填的,我们没办法深层递归,所以改写一下上面的写法,利
用循环递归改成深度递归
type Partial<T> = { [K in keyof T]?: T[K] extends object ? Partial<T[K]>:T[K] }
2.Required
- 跟Partial相反,就是把所有的可选的,全部
改为必填的
type MyRequired = Required<MyPerson>
//得到如下结果
type MyRequired = {
name: string;
age: number;
company: ICompany;
}
- 实现原理,值得注意就是 -?,就是去掉?标识
type Required<T> = { [K in keyof T]-?: T[K] }
3.Readonly
- 标识只读的属性
type MyReadonly = Readonly<IPerson>
//相当于多添加了readonly属性
type MyReadonly = {
readonly name?: string | undefined;
readonly age: number;
readonly company?: ICompany | undefined;
}
- 实现原理
type Readonly<T> = { readonly [K in keyof T]: T[K] }
4.Pick
- Pick 精挑细选 (
对象里选属性
) extract 抽离可用的 (类型中选择类型
)
type MyPick = Pick<IPerson, 'age' | 'company'>
//得到如下类型
type MyPick = {
age: number;
company?: ICompany | undefined;
}
- 实现方法
type Pick<T, K extends keyof T> = { [X in K]: T[X] }
5.Omit
- 忽略属性 两个对象的合并 T & K
type MyType = Omit<IPerson, 'name'> & { name: string };
//得到如下
type MyType = Omit<IPerson, "name"> & {
name: string;
}
- 实现方法
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>