如何让TypeScript根据函数名动态推断参数类型?
解决TypeScript根据函数名自动推断参数类型的问题
问题核心是:当遍历包含函数名和对应参数的联合类型数组时,TypeScript没法自动把func字段和参数类型关联起来,导致直接调用函数时类型报错。不用写一堆if/switch的话,有以下几个靠谱的方案:
方案一:写一个类型安全的泛型调用函数
通过泛型约束把函数名和参数类型绑定,让TypeScript能正确推断每个项的匹配关系:
const funcList = { f1: (val: string, opts: number) => { console.log(val, opts); }, f2: (val: number, opts: boolean) => { console.log(val, opts); }, } as const; const data = [{ func: 'f1', val: 'strval', opt: 111, }, { func: 'f2', val: 222, opt: true, }] as const; // 定义泛型调用函数 type FuncKeys = keyof typeof funcList; const callMatchingFunc = <K extends FuncKeys>(item: { func: K } & (Parameters<typeof funcList[K]> extends [infer V, infer O] ? { val: V, opt: O } : never) ) => { funcList[item.func](item.val, item.opt); }; // 直接遍历调用即可 for (const e of data) { callMatchingFunc(e); }
这个函数通过Parameters工具类型提取对应函数的参数类型,再用泛型K把func字段和val/opt的类型绑定在一起,TypeScript能完全识别每个项的类型匹配关系,不会报错,而且类型安全——如果data里的参数和函数不匹配,会直接在编译阶段提示。
方案二:用类型断言快速解决(适合简单场景)
如果不想写额外函数,可以直接用类型断言告诉TypeScript当前项的参数和函数是匹配的:
for (const e of data) { (funcList[e.func] as (val: typeof e.val, opt: typeof e.opt) => void)(e.val, e.opt); }
⚠️ 注意:这个方法是“告诉”TypeScript类型匹配,而非让它自动推断。如果data里的参数和函数类型不匹配,TypeScript不会报错,适合你能保证data类型绝对正确的简单场景。
方案三:提前定义严格关联的Data类型(更规范)
先通过映射类型生成和funcList严格对应的Data类型,确保data的每个项都和函数参数类型匹配,再配合泛型调用:
const funcList = { f1: (val: string, opts: number) => { console.log(val, opts); }, f2: (val: number, opts: boolean) => { console.log(val, opts); }, } as const; // 生成与funcList严格对应的Data项类型 type FuncMap = typeof funcList; type ValidDataItem<K extends keyof FuncMap> = { func: K; val: Parameters<FuncMap[K]>[0]; opt: Parameters<FuncMap[K]>[1]; }; type ValidData = ValidDataItem<keyof FuncMap>[]; // 此时data的类型会被严格约束,写错参数类型会直接报错 const data: ValidData = [ { func: 'f1', val: 'strval', opt: 111 }, { func: 'f2', val: 222, opt: true }, ]; // 再用泛型函数调用即可 const callMatchingFunc = <K extends keyof FuncMap>(item: ValidDataItem<K>) => { funcList[item.func](item.val, item.opt); }; for (const e of data) { callMatchingFunc(e); }
这种方式能从源头保证data的类型正确性,避免后续出现类型不匹配的问题,适合大型项目或需要严格类型约束的场景。
内容的提问来源于stack exchange,提问作者Vladimir G.
相关产品推荐
相关产品推荐

