主题
infer extends 简化类型编程
infer
关键字
infer
关键字是在 TypeScript 2.8 引入的,用于在条件类型中创建临时类型变量,允许我们从已有的类型中提取信息。它通常与条件类型(extends
)一起使用来动态地推断类型
typescript
type GetReturnType<T> = T extends (...args: any[]) => infer R ? R : never;
function foo() {
return { x: 10, y: 3 };
}
type FooReturnType = GetReturnType<typeof foo>; // { x: number; y: number; }
在这个例子中,infer R
就是用来捕获函数返回类型的占位符。当 TypeScript 遇到 T extends (...args: any[]) => infer R
的时候,它会试图匹配 T
是否符合函数签名的形式,并将实际的返回类型赋给 R
extends
关键字
extends
关键字则主要用于指定泛型参数的约束或定义类与接口之间的继承关系。在条件类型中,extends
可以用来比较两个类型是否兼容,并根据结果选择不同的分支
条件类型中的 extends
在条件类型中,extends
被用来检查左边的类型是否可以分配给右边的类型。如果可以,则选择 true
分支;否则选择 false
分支。
例如,我们可以使用 extends
来过滤出联合类型中满足特定约束的成员:
typescript
type IsString<T> = T extends string ? true : false;
type Test1 = IsString<"hello">; // true
type Test2 = IsString<42>; // false
结合使用 infer
和 extends
当你需要从复杂类型中提取部分类型信息时,infer
和 extends
的组合变得特别有用。以下是一些常见的应用场景:
提取函数参数类型:
typescripttype ParametersType<T> = T extends (...args: infer P) => any ? P : never;
提取数组元素类型:
typescripttype ElementType<T> = T extends (infer U)[] ? U : never;
提取Promise解析值类型:
typescripttype UnwrapPromise<T> = T extends Promise<infer U> ? U : never;
这些模式展示了如何利用 infer
和 extends
简化原本可能需要手动定义的类型操作。例如,如果你想提取一个对象属性的类型,你可以这样写:
typescript
type PropType<T, K extends keyof T> = T extends { [P in K]: infer U } ? U : never;
这比直接为每个属性手动定义类型要高效得多,特别是在处理大型或动态数据结构时。