You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 16:07:38