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

TypeScript 遍历对象调用泛型函数时如何实现正确类型推导

问题原因

TypeScript 无法在循环遍历场景下自动推导key和_Map[T]的绑定关系:当key是keyof _Map联合类型时,TS会将fn_map[key]推导为所有回调的联合类型,同时将fn的第二个参数推导为接收1 | "2"的函数,由于函数参数逆变特性,接收窄类型的回调无法赋值给接收宽类型的参数,就出现了你看到的报错。

可行解决方案

方案1:使用泛型辅助遍历函数(最安全,无类型损失)

我们可以写一个专门遍历符合结构对象的泛型函数,让TS在每一次遍历迭代中都能正确绑定key和对应回调的类型关系,全程不需要使用any:

type _Map = {
    a: 1
    b: "2"
}

type Fn = <T extends keyof _Map>(key: T, cb: (value: _Map[T]) => any) => void

let fn!: Fn

const fn_map = {
    a: (v: 1): 1 => 1,
    b: (v: "2"): "2" => "2"
}

// 定义通用泛型遍历辅助函数
function traverseMap<T extends object>(map: T, callback: <K extends keyof T>(key: K, value: T[K]) => void) {
    (Object.keys(map) as Array<keyof T>).forEach(key => {
        callback(key, map[key])
    })
}

// 遍历调用,无报错,类型完全安全
traverseMap(fn_map, (key, cb) => {
    fn(key, cb)
})

// fn_map_2的场景同理适配
const fn_map_2 = {
    a: ["a", (v: 1): 1 => 1] as const,
    b: ["b", (v: "2"): "2" => "2"] as const
}

traverseMap(fn_map_2, (k, item) => {
    const [key, cb] = item
    fn(key, cb)
})

方案2:使用类型断言(更简洁,逻辑确定的场景可用)

如果你可以保证业务逻辑中key和对应回调的匹配关系绝对正确,可以直接用类型断言解决,不需要引入额外函数:

;(Object.keys(fn_map) as Array<keyof _Map>).forEach(key => {
    fn(key, fn_map[key] as Parameters<Fn>[1])
})

;(Object.keys(fn_map_2) as Array<keyof _Map>).forEach(k => {
    const [key, cb] = fn_map_2[k]
    fn(key, cb as Parameters<Fn>[1])
})

内容的提问来源于stack exchange,提问作者justTryIt

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 19:18:02