Skip to content

提取类型中所有函数作为新的类型

ts
type FunctionPropertyNames<T> = {
  [K in keyof T]: T[K] extends (...args: any[]) => any ? K : never;
}[keyof T];

type FunctionProperties<T> = Pick<T, FunctionPropertyNames<T>>;

interface Part {
  id: number;
  getName(): string;
  setName(name: string): void;
}

type FuncProps = FunctionProperties<Part>;
// { getName: () => string, setName(name: string) => void }

理解 FunctionPropertyNamesFunctionProperties

这段代码定义了两个类型别名,FunctionPropertyNamesFunctionProperties,它们一起工作以从给定的类型中提取出所有函数属性。具体来说:

  1. FunctionPropertyNames<T>:提取类型 T 中所有函数属性的键。
  2. FunctionProperties<T>:使用 Pick 从类型 T 中选取由 FunctionPropertyNames<T> 提取出来的函数属性。

让我们逐步拆解并理解这两个类型别名的工作原理。

1. FunctionPropertyNames<T>

typescript
type FunctionPropertyNames<T> = {
  [K in keyof T]: T[K] extends (...args: any[]) => any ? K : never;
}[keyof T];

解析

  • [K in keyof T]:这是一个映射类型(Mapped Type),它遍历 T 类型的所有键 K
  • T[K] extends (...args: any[]) => any ? K : never:对于每个键 K,检查其对应的值类型 T[K] 是否是函数类型(即是否可以被调用)。如果是函数,则返回键 K;否则返回 never
  • [keyof T]:这一步是索引访问类型(Indexed Access Type),它将前面映射类型的结果转换为一个联合类型,其中只包含那些通过条件检查的键。

所以,FunctionPropertyNames<T> 的作用是从 T 中提取出所有函数属性的键,并返回这些键的联合类型。

2. FunctionProperties<T>

typescript
type FunctionProperties<T> = Pick<T, FunctionPropertyNames<T>>;

解析

  • Pick<T, Keys>:这是 TypeScript 内置的一个工具类型,它从类型 T 中选取指定的键 Keys,并返回一个新的类型,该类型只包含 T 中与 Keys 匹配的属性。

因此,FunctionProperties<T> 使用 Pick 来从 T 中选取由 FunctionPropertyNames<T> 提取出来的函数属性,最终返回一个新的类型,该类型只包含 T 中的函数属性。

示例解释

考虑以下接口:

typescript
interface Part {
  id: number;
  getName(): string;
}

应用 FunctionProperties<Part>

typescript
type FuncProps = FunctionProperties<Part>; // { getName: () => string }

在这个例子中:

  • FunctionPropertyNames<Part> 会提取出 Part 接口中所有函数属性的键。因为 getName 是唯一一个函数属性,所以结果是 "getName"
  • FunctionProperties<Part> 则使用 PickPart 中选取 "getName" 这个键及其对应的属性,结果是一个新类型 { getName: () => string }

实际应用案例

假设我们有一个更复杂的对象类型,并希望从中提取所有的函数属性:

typescript
interface ComplexObject {
  id: number;
  name: string;
  calculateTotal(...items: number[]): number;
  formatName(): string;
}

type FuncPropsComplex = FunctionProperties<ComplexObject>;
// 结果类型:
// {
//   calculateTotal: (...items: number[]) => number;
//   formatName: () => string;
// }

在这个例子中:

  • calculateTotalformatName 都是函数属性,因此它们会被提取出来。
  • 最终的 FuncPropsComplex 类型只包含这两个函数属性。

总结

  • FunctionPropertyNames<T>:用于提取类型 T 中所有函数属性的键。
  • FunctionProperties<T>:用于从类型 T 中选取由 FunctionPropertyNames<T> 提取出来的函数属性,创建一个新的类型。

这种模式非常有用,尤其是在需要对对象进行部分处理或操作时,例如仅关注对象中的方法而忽略其他属性。通过合理使用这些高级类型操作符,你可以构建更加健壮和灵活的类型系统,提高代码的安全性和可维护性。

Released under the MIT License.