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

Typescript泛型联合类型推导顺序:如何指定values为泛型推导源

问题原因

你猜测的原因是正确的:TypeScript 默认会从泛型关联的所有输入位置同步推导类型,上述代码中items数组仅包含value: 'a',TS 会优先将泛型TValue推导为字面量类型'a',因此values中出现的b属性会被判定为多余属性,抛出类型错误。

解决方案

方案1:使用NoInfer降低推导优先级(TS 4.7+ 推荐)

TS 4.7 内置了NoInfer<T>工具类型,标记了该类型的位置不会参与泛型的自动推导,强制TS优先从其他位置推导泛型。
修改IOptions的items属性定义即可:

interface IOptions<TValue extends string> {
  values: {[key in TValue]: string};
  // 用NoInfer包裹TValue,禁止从items推导泛型
  items: IItem<NoInfer<TValue>>[];
}
interface IItem<TValue extends string> {
  value: TValue;
}

function printOptions<TValue extends string>(options: IOptions<TValue>) {
  console.log(options);
}

// 现在可以正常通过类型校验
printOptions({
  values: {a: 'a', b: 'b'},
  items: [
    { value: 'a'}
  ]
});

方案2:兼容低版本TS的实现

如果使用的TS版本低于4.7,可以手动实现NoInfer类型,效果和内置版本一致:

type NoInfer<T> = [T][T extends any ? 0 : never];

// 后续接口定义和方案1完全一致

方案3:拆分泛型参数明确区分子集

如果你需要显式区分values的全量键类型和items用到的子集类型,也可以拆分两个泛型参数实现:

interface IOptions<TAll extends string, TUsed extends TAll> {
  values: Record<TAll, string>;
  items: IItem<TUsed>[];
}
interface IItem<TValue extends string> {
  value: TValue;
}

function printOptions<TAll extends string, TUsed extends TAll>(options: IOptions<TAll, TUsed>) {
  console.log(options);
}

printOptions({
  values: {a: 'a', b: 'b'},
  items: [
    { value: 'a'}
  ]
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 21:36:03