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

如何解决泛型映射类型中参数隐式为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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 06:05:04