如何解决泛型映射类型中参数隐式为any类型的TS错误?
问题描述
我尝试在TypeScript中创建一个泛型函数,该函数接收一个对象,对象的每个属性是由特定联合类型('foo' | 'bar')的字符串和回调函数组成的元组。回调函数的参数类型应与元组中的字符串类型一致。
我的代码如下:
type TInput = 'foo' | 'bar'; const func = <T extends object>(arg: { [N in keyof T]: { [K in TInput]: [K, (arg: K) => void] }[TInput] }) => {} func({ flash: ['bar', (ctx) => {}], // Parameter 'ctx' implicitly has an 'any' type.ts(7006) antman: ['foo', (ctx) => {}], // Parameter 'ctx' implicitly has an 'any' type.ts(7006) });
调用该函数时出现以下TypeScript错误:
Parameter 'ctx' implicitly has an 'any' type.ts(7006)
我希望ctx能根据元组的第一个元素自动推断为'foo'或'bar'类型,但TypeScript未能正确推断其类型。请问如何修改函数,使TypeScript能正确推断回调参数的类型?
解决方案
问题出在当前类型定义把每个属性解析成了联合类型的元组,TypeScript无法自动关联元组第一个元素和回调参数的类型。可以通过让泛型直接绑定每个属性的具体输入类型来解决,具体修改如下:
方案一:明确单个属性的类型绑定
type TInput = 'foo' | 'bar'; // 定义单个属性的类型:输入类型K对应回调参数为K的函数 type PropType<K extends TInput> = [K, (arg: K) => void]; // 泛型T约束为对象,每个属性都是PropType的某个实例 const func = <T extends Record<string, PropType<TInput>>>(arg: T) => {} func({ flash: ['bar', (ctx) => { // ctx 类型自动推断为 'bar' console.log(ctx.toUpperCase()); // 代码补全正常工作 }], antman: ['foo', (ctx) => { // ctx 类型自动推断为 'foo' }], });
方案二:内联类型推断逻辑
如果不想单独定义PropType,也可以直接在泛型中处理类型绑定:
type TInput = 'foo' | 'bar'; const func = <T extends Record<string, unknown>>(arg: { [P in keyof T]: T[P] extends [infer U, (...args: any[]) => void] ? U extends TInput ? [U, (arg: U) => void] : never : never }) => {} func({ flash: ['bar', (ctx) => {}], // ctx: 'bar' antman: ['foo', (ctx) => {}], // ctx: 'foo' });
核心思路是让TypeScript明确元组中第一个元素和回调参数的类型绑定关系,而非把所有可能组合转化为松散的联合类型。方案一更简洁易读,推荐使用。
内容的提问来源于stack exchange,提问作者johann1301s
相关产品推荐
相关产品推荐

