如何在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
相关产品推荐
相关产品推荐

