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

如何让TypeScript根据函数参数值推断数组元素的具体映射类型?

如何让TypeScript根据函数参数值推断数组元素的具体映射类型?

我明白你的困扰——你希望TypeScript能根据传入的device参数值,自动将数组arr的类型收窄到对应的EventTypes成员类型,而不用类型断言或者事后再遍历数组检查一遍。其实核心问题在于TypeScript需要明确知道device的具体类型和数组类型之间的绑定关系,而通过泛型函数就能完美解决这个问题。

解决思路

把你的func函数改成泛型函数,让它接收一个泛型参数D(约束为GestureDevice)。这样TypeScript就能全程跟踪device的具体子类型,并且把数组arr的类型直接绑定到EventTypes[D]上。当你后续检查device的值时,TypeScript会自动收窄泛型参数D的类型,进而确定数组的具体元素类型。

修正后的代码

type GestureDevice = "key" | "pointer";
type EventTypes = {
    "key": KeyboardEvent;
    "pointer": PointerEvent;
};

const k = (e: KeyboardEvent[]) => {}
const p = (e: PointerEvent[]) => {}

// 改为泛型函数,泛型D约束为GestureDevice
const func = <D extends GestureDevice>(device: D, events: Event[]) => {
    // 数组类型直接绑定到EventTypes[D]
    const arr: Array<EventTypes[D]> = [];
    for (const e of events) {
        // isEventTypeOf的泛型会自动匹配D,确保e是EventTypes[D]类型
        if (isEventTypeOf(device, e)) {
            arr.push(e); // 这里完全安全,不需要任何断言
        }
    }

    // 检查device值时,TypeScript会自动收窄D的类型
    if (device === "pointer") {
        p(arr); // 此时arr被推断为PointerEvent[],直接调用p即可
    } else {
        k(arr); // 此时arr被推断为KeyboardEvent[],直接调用k即可
    }
}

const isEventTypeOf = <D extends GestureDevice>(device: D, event: Event): event is EventTypes[D] => {
    if (device === "key") {
        return event instanceof KeyboardEvent;
     } else if (device === "pointer") {
        return event instanceof PointerEvent;
     }
     return false;
}

为什么这样有效?

  • 泛型参数D和device参数的类型绑定在一起,TypeScript会全程跟踪D的具体类型。
  • 当你检查device === "pointer"时,TypeScript会把泛型参数D收窄为"pointer",因此EventTypes[D]就变成了PointerEvent,数组arr的类型自然就是PointerEvent[],完全符合p函数的参数要求。
  • 你的isEventTypeOf函数已经是泛型的,它会根据传入的device类型返回正确的类型谓词,确保只有符合类型的事件被推入数组,所以后续不需要再重复检查整个数组。

这样就彻底解决了你在第22行遇到的问题,既不需要类型断言,也不用做冗余的数组元素检查。

备注:内容来源于stack exchange,提问作者Aayla Secura

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.16 02:53:18