# 定义
infer
最早出现在此 PR (opens new window) 中, 表示在 extends
条件语句中待推断的类型变量。
infer
关键词常在条件类型中和 extends
关键词一同出现, 表示将要推断的类型, 作为类型变量可以在三元表达式的 true
部分引用。而 ReturnType
正是使用这种方式提取到了函数的返回类型。
使用 infer
, 编译器确保您已经显式声明了所有类型变量。
# 使用
type Unpacked<T> = T extends (infer U)[]
? U
: T extends (...args: any[]) => infer U
? U
: T extends Promise<infer U>
? U
: T;
type T0 = Unpacked<string>; // string
type T1 = Unpacked<string[]>; // string
type T2 = Unpacked<() => string>; // string
type T3 = Unpacked<Promise<string>>; // string
type T4 = Unpacked<Promise<string>[]>; // Promise<string>
type T5 = Unpacked<Unpacked<Promise<string>[]>>; // string
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
infer
可以用来推断联合类型
type Foo<T> = T extends {a: infer U; b: infer U} ? U : never;
type T10 = Foo<{a: string; b: string}>; // string
type T11 = Foo<{a: string; b: number}>; // string | number
1
2
3
4
2
3
4
同样,在变数位置中针对同一类型变量的多个候选会导致得出交集类型:
type Bar<T> = T extends {a: (x: infer U) => void; b: (x: infer U) => void} ? U : never;
type T20 = Bar<{a: (x: string) => void; b: (x: string) => void}>; // string
type T21 = Bar<{a: (x: string) => void; b: (x: number) => void}>; // string & number
1
2
3
2
3
# 内置类型
# 用于提取函数类型的返回值类型
/**
* 获取函数 T 的返回类型
*/
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;
1
2
3
4
2
3
4
更多有关于 ReturnType
Here
# Demo
type Func = (...args: any) => string | number;
type ReturnValue = ReturnType<Func>; // string | number
1
2
3
2
3
# 用于提取构造函数中参数 (实例) 类型
构造函数可以使用 new
来实例化, 因此它的类型通常表示如下:
type Constructor = new (...ages: any[]) => any;
1
当 infer
用于构造函数类型中, 可用于参数位置 new (...args: infer P) => any
和 返回值位置 new (...args: any[]) => infer P
。
因此就内置如下两个映射类型:
// 获取参数类型
type ConstructorParameters<T extends new (...args: any[]) => any> = T extends new (
...args: infer P
) => any
? P
: never;
// 获取实例类型
type InstanceType<T extends new (...args: any[]) => any> = T extends new (...args: any[]) => infer R
? R
: any;
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# Demo
class TestClass {
constructor(public name: string, public string: number) {}
}
type Params = ConstructorParameters<typeof TestClass>; // [string, numbder]
type Instance = InstanceType<typeof TestClass>; // TestClass
1
2
3
4
5
6
7
2
3
4
5
6
7
# 快来耍耍啊
# 🌰🌰
// template
1
# 游乐场
# 参考答案
// answer
1
# 参考资料
infer PR: Type inference in conditional types (opens new window)
typescript-2-8 (opens new window)