TypeScript扩展参数函数调用问题:如何实现类型安全?
类型安全实现动态调用函数的解决方案
你的代码里出现两个类型错误的核心原因是:当T为keyof typeof fns的联合类型时,TypeScript无法将联合类型的函数、参数和返回值做精确的一一映射,导致函数调用时的参数扩展和返回值类型匹配都出现了推断问题。下面提供两种类型安全的解决方式:
方法一:类型断言(简洁高效)
通过类型断言明确告诉TypeScript,当前调用的函数参数和返回值是完全匹配的,适合函数数量较多的场景:
function foo(a: string) { return a; } function bar(b: number) { return b; } const fns = { foo, bar } as const; function callThing<T extends keyof typeof fns>(name: T, ...params: Parameters<(typeof fns)[T]>): ReturnType<(typeof fns)[T]> { // 断言当前函数与传入参数、返回值类型完全匹配 const result = (fns[name] as (...args: typeof params) => ReturnType<(typeof fns)[T]>) (...params); return result; } const fooResult = callThing("foo", "hello"); // 类型自动推断为string const barResult = callThing("bar", 42); // 类型自动推断为number
方法二:函数重载(类型检查更严格)
为每个函数手动定义重载签名,让TypeScript能精准匹配每个调用场景,适合函数数量较少的场景:
function foo(a: string) { return a; } function bar(b: number) { return b; } const fns = { foo, bar } as const; // 定义每个函数的重载签名 function callThing(name: "foo", a: string): string; function callThing(name: "bar", b: number): number; // 通用实现签名 function callThing(name: keyof typeof fns, ...params: any[]) { return fns[name](...params); } const fooResult = callThing("foo", "hello"); // string const barResult = callThing("bar", 42); // number // 错误示例:callThing("foo", 42) 会直接抛出类型错误,保证类型安全
两种方式都能实现类型安全的动态调用,你可以根据实际函数数量和维护成本选择合适的方案。
内容的提问来源于stack exchange,提问作者whatupdave
相关产品推荐
相关产品推荐

