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

如何传递泛型类型数组并让每个元素的泛型类型被正确推断?

TypeScript数组中Entry类型的正确校验方案

问题背景

首先定义以下TypeScript类型:

type ValueMap = {
  foo: 'FOO1' | 'FOO2';
  bar: 'BAR1' | 'BAR2' | 'BAR3';
};
type Key = keyof ValueMap;

type Value<K extends Key> = ValueMap[K];

type Entry<K extends Key> = {
  key: K;
  value: Value<K>;
}

Entry类型的key与value存在严格对应关系:比如{key: 'foo', value: 'FOO2'}是合法的,但{key: 'foo', value: 'BAR3'}不合法。

但当尝试将这类Entry组成数组传入sendArray函数时,当前实现无法正确推断每个元素的泛型类型:

function sendArray<K extends Key>(v: Array<Entry<K>>) {
  // ...
}

sendArray([{key: 'foo', value: 'FOO2'}, {key: 'bar', value: 'BAR1'}])
sendArray([{key: 'foo', value: 'FOO2'}, {key: 'bar', value: 'FOO1'}]) // 错误编译通过

此时泛型K会被推断为"foo" | "bar",导致value的类型变成所有可能值的联合,失去了单个元素的校验能力。

解决方案

方法一:直接使用联合类型数组

修改函数参数类型为Array<Entry<Key>>,让数组元素接受Entry<'foo'>或Entry<'bar'>的联合类型,TypeScript会逐个校验每个元素的key与value对应关系:

function sendArray(v: Array<Entry<Key>>) {
  // ...
}

sendArray([{key: 'foo', value: 'FOO2'}, {key: 'bar', value: 'BAR1'}]); // 合法
sendArray([{key: 'foo', value: 'FOO2'}, {key: 'bar', value: 'FOO1'}]); // 类型错误,符合预期

方法二:带泛型约束的实现(保留泛型能力)

如果需要保留泛型以获取数组的具体类型信息,可以用泛型参数约束为Entry<Key>的数组:

function sendArray<T extends Entry<Key>[]>(v: T) {
  // 可通过泛型T获取数组的具体类型
}

这种写法同样能保证每个元素的key与value匹配,同时保留泛型带来的类型推断能力。

原理说明

原写法中Array<Entry<K>>要求数组内所有元素的K必须是同一类型(或其联合),因此TypeScript会把K推断为'foo' | 'bar',导致value的类型宽松为所有可能值的联合,失去校验效果。

修改后的写法让数组元素接受Entry<Key>联合类型,TypeScript会对每个元素单独进行类型检查,确保每个元素的key对应正确的value范围,从而实现精准校验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 13:32:28