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

如何在TypeScript中实现类型安全的泛型方法包装函数foo?

TypeScript类型安全的泛型包装函数实现问题

需求描述

我想编写一个名为foo的泛型包装函数,接收对象o、键k及若干参数args,以类型安全的方式调用o[k](...args)并自动推断返回类型。示例如下:

const obj = {
   a: 1,
   b: true,
   c: (name: string) => `Hello, ${name}.`,
   d: (name: string) => `Goodbye, ${name}.`,
};

const result = foo(obj, 'c', 'Peter');
// typeof result === 'string'
console.log(result); // Hello, Peter.

尝试实现的问题

我编写了以下代码,但遇到了类型错误:

function foo<
  Args extends any[],
  Return,  
  Target,
  Key extends keyof {
    [K in keyof Target as Target[K] extends ((...args: Args) => any) ? K : never]: Target[K]
  }
>(target: Target, key: Key, ...args: Args): Return
{
  const method = target[key];
  // 报错:Type 'unknown' has no call signatures.ts(2349)
  return method(...args);
}

// 报错:Argument of type 'string' is not assignable to parameter of type 'never'.ts(2345)
const result = foo(obj, 'c');

请问能否在TypeScript中实现该函数?若可以,具体该如何实现?

补充调整后的可行版本

参考Titian Cernicova-Dragomir的答案调整后,我得到了能正确推断返回类型的版本:

type FunctionKeys<Target> = keyof {
  [K in keyof Target as Target[K] extends ((...args: any) => any) ? K : never]: Target[K]
}

function foo<
Target extends Record<Key, (...args: any) => any>,
Key extends FunctionKeys<Target>,
>(...[target, key, ...args]: [Target, Key, ...Parameters<Target[Key]>]) {
  const method = target[key];
  return method(...args) as ReturnType<Target[Key]>;
}

对比Tobias S.的写法,该版本能生成更友好的编译器错误提示:

const obj = {
  greet: (name: string) => `Hello, ${name}.`,
};

// 报错:Expected 3 arguments, but got 2.ts(2554)
fooTitian(obj, 'greet');

// 报错:Argument of type '{ greet: (name: string) => string; }' is not assignable to parameter of type 'Record<"greet", () => any>'.
//   Types of property 'greet' are incompatible.
//     Type '(name: string) => string' is not assignable to type '() => any'.ts(2345)
fooTobias(obj, 'greet');

内容的提问来源于stack exchange,提问作者hBGl

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 02:25:47