如何在TypeScript中实现类似Lodash bindKey的类型化函数?
实现
obj.func.bind(obj)的类型安全简化函数 先直接给出满足需求的实现,支持智能提示和正确的类型推断:
type FunctionPropertyNames<T> = { [K in keyof T]: T[K] extends (...args: any[]) => any ? K : never; }[keyof T]; function bound<T extends object, K extends FunctionPropertyNames<T>>( thisObj: T, fnKey: K ): (...args: Parameters<T[K]>) => ReturnType<T[K]> { return thisObj[fnKey].bind(thisObj); }
测试验证
const obj = { a: "abc", b() { console.log(this.a); return 123; }, c(num: number) { return this.a + num; }, d: "非函数属性" }; // 智能提示只会显示"b"、"c"这两个函数类型的键 const f = bound(obj, "b"); // 类型推断为 () => number f(); // 输出"abc",返回123 const g = bound(obj, "c"); // 类型推断为 (num: number) => string g(456); // 输出"abc456"
为什么你的原写法有问题?
你之前的泛型定义顺序和约束逻辑存在缺陷:
function bound< K extends string, F extends (...args: any[]) => any, T extends {[key in K]: F} >(thisObj: T, fnKey: K): (...args: Parameters<F>) => ReturnType<F> { ... }
这里泛型参数F先于T定义,TypeScript无法从传入的obj(即T)中反向推导F的具体类型,只能默认退化为(...args: any[]) => any,导致返回类型丢失了具体的参数和返回值信息。
避免any时的报错原因
当你尝试用F extends (...args: never[]) => unknown约束时,ReturnType<F>会被推断为unknown,但fn.bind(thisObj)的返回类型是原函数的具体类型,和unknown类型不兼容,因此触发报错。核心问题是没有让F从对象属性中动态推导,而是提前做了过于严格的静态约束。
更简洁的实现(无需额外类型别名)
如果不想定义单独的类型别名,可以直接用条件类型内联处理:
function bound<T extends object, K extends keyof T>( thisObj: T, fnKey: T[K] extends (...args: any[]) => any ? K : never ): T[K] extends (...args: infer A) => infer R ? (...args: A) => R : never { return thisObj[fnKey].bind(thisObj); }
这个写法和之前的实现效果完全一致,只是把类型判断逻辑整合到了泛型约束和返回类型中。
内容的提问来源于stack exchange,提问作者Coolstrong
相关产品推荐
相关产品推荐

