methodsof工具类型通过泛型约束、映射类型和条件类型提取对象中所有方法属性:先用t[k] extends function判断是否为函数,再用never剔除非函数键,最后用pick聚合剩余键对应的方法类型。

要手写一个能把对象中所有方法类型提取出来的高级工具类型,核心思路是:遍历对象所有属性,用条件类型判断每个属性是否为函数,如果是就保留其类型,否则剔除。结合泛型、映射类型和条件类型即可实现。
定义泛型参数并约束输入为对象
先用泛型 T 接收任意对象类型,并用 extends object 约束它必须是对象(排除原始类型或数组等)。
用映射类型 + 条件类型逐个筛选方法属性
借助 in keyof T 遍历所有键,对每个键 K 做判断:如果 T[K] 是函数类型(即 Function),就保留该键和对应类型;否则用 never 抹掉这个键。
- 判断是否为函数可用 T[K] extends Function ? ... : never
- 注意不能只写 function 或 () => any,因为函数类型有多种形态(带 this、重载、箭头函数等),Function 是最稳妥的内置类型
- 最终映射类型返回的是一个新对象类型,只含原对象中的方法属性
用 keyof + never 实现键的条件过滤
映射类型中若某个键的值被设为 never,TypeScript 会自动从结果类型中剔除该键。所以可以这样写:
type MethodKeys<t> = {
[K in keyof T]: T[K] extends Function ? K : never;
}[keyof T];</t>
这段先生成一个中间类型,把每个键映射成它自己(如果是方法)或 never(如果不是),再用 [keyof T] 索引访问,得到所有非 never 的键的联合类型(比如 "foo" | "bar")。
组合出最终的工具类型
有了方法键的联合类型,就能用 Pick
type MethodsOf<t extends object> = Pick<t in keyof t extends function k : never>;</t></t>
使用示例:
interface User {
name: string;
age: number;
getName(): string;
setName(n: string): void;
toString(): string;
}
type UserMethods = MethodsOf<user>;
// → { getName(): string; setName(n: string): void; toString(): string; }</user>
不复杂但容易忽略细节:必须用 Function 判断函数,映射类型里用 never 控制键存在性,最后靠 Pick 聚合结果。这样写既准确又保持类型完整性。











