前言
关于infer的简介:
- 官方解释
现在在有条件类型的 extends 子语句中,允许出现 infer 声明,它会引入一个待推断的类型变量。 这个推断的类型变量可以在有条件类型的 true 分支中被引用。 允许出现多个同类型变量的 infer。
只需要记住
- 只能出现在有条件类型
extends
的子语句中 - 引入infer会出现一个待推断的变量
- 推断的变量只能在
true
f分支中被引用 通俗的来说:想要获取哪块的变量类型就在哪里用infer
标注这个类型
结合实际范例理解一下?
1. 获取函数的参数类型(Parameters)
-
比如我们这里想把函数
fn
的参数类型取出来,该怎么办?function fn1(width: number, height: number): number { return width + height; }
-
我们可以
type getFuncParamsType<T> = T extends (...args: infer P) => any ? P : T;//声明一个getFuncParamsType<T>类型,此类型接收一个泛型参数 type a = getFuncParamsType<typeof fn1>;
整个过程呢,你可以简单的理解为getFuncParamsType
接受一个泛型,如果T
类型能被赋值给(...args:infer p) => any
则返回P
,否则返回T
。
悄悄告诉你,其实ts
中也内置了这个类型,名字叫Parameters<T>
,平时项目中你可以直接用。
由此,我们可以知道,关于infer
:
- 只能出现在有条件类型
extends
的子语句中 - 引入infer会出现一个待推断的变量
- 推断的变量只能在truef分支中被引用
通俗的来说:想要获取哪块的变量类型就在哪里用
infer
标注这个类型
我们经过上面的分析,下面的如何获取函数返回值类型,是不是已经呼之欲出了。
2. 获取函数的返回值类型(ReturnType)
function fn2(): boolean {
return true;
}
type getFuncReturnType<T> = T extends () => infer P ? P : T;
type a = getFuncReturnType<typeof fn2>;
整个过程你可以这样理解,我们声明了一个类型getFuncReturnType<T>
类型,然后我们想获取函数的返回值的类型,我们就将infer P
标成函数的返回值,如果为T
类型可以赋值给() => infer P
直接返回P
,否则直接返回T
该方法,ts已内置,名字叫ReturnType<T>
。
3. 获取构造函数参数类型(ConstructorParameters)
我们想获取构造函数的参数类型,是不是只要把infer P
标注在构造函数参数的位置就可以
class People {
name: string;
constructor(name: string) {
this.name = name;
}
}
type GetContructor<T> = T extends new (...args: infer P) => any ? P : T;
type a = GetContructor<typeof People>;
该方法,ts已内置,名字叫ConstructorParameters<T>
。
4. 获取实例类型(InstanceType)
我们想获取构造函数People
的实例类型
class People {
name: string;
constructor(name: string) {
this.name = name;
}
}
type GetInstanceType<T> = T extends new (...args: any) => infer P ? P : never;
type a = GetInstanceType<typeof People>;
该方法,ts已内置,名字叫InstanceType<T>
。
5. 获取this参数的类型(ThisParameterType)
我们想获取fn1
函数的this
类型。
function fn1(this: { name: string; age: number }) {
this.name = "杨志强";
this.age = 23;
}
type GetFuncThisType<T> = T extends (this: infer P, ...args: any) => any ? P : T;
type a = GetFuncThisType<typeof fn1>;
该方法,ts已内置,名字叫ThisParameterType<T>
。
6. 剔除this参数(OmitThisParameter)
type OmitThisParameter<T> = unknown extends ThisParameterType<T>
? T
: T extends (...args: infer A) => infer R
? (...args: A) => R
: T;
以下语法是判断是否包含this
参数。
unknown extends ThisParameterType<T>
实战中积累的infer用法
1.判断俩个类型是否相同?
type isEqual<T, U> = ((p1: T, p2: U) => void) extends ((...args: infer P) => void) ? P[number] extends T ? true : false : false;
type a = ["a"];
type b = [1];
type res = isEqual<a, b>;
我们可以这样理解:类型isEqual
接受俩个泛型,利用infer
的特性得到参数类型是一个数组,再取出下标为number
的每一项,组成一个联合类型
,接着看获取到的联合类型能否赋值给T
(U
也可以),从而就可以判断是否为相同类型。