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

TypeScript生成可区分联合类型时出现赋值错误求助

TypeScript可区分联合类型赋值报错原因与解决方法

报错核心原因

你遇到的错误本质是:虽然RickAndMortyCharacterChange是正确的可区分联合类型,但TypeScript在applyPropertyChange函数内部无法自动关联change.property和change.value的对应关系。当直接赋值时,TS会把obj[change.property]推断为原类型所有属性类型的交集(也就是string & { name: string; url: string; },这是一个不存在的矛盾类型),而change.value是联合类型string | { name: string; url: string; },自然无法赋值。

这是因为函数参数的联合类型在没有显式类型缩小逻辑时,TS无法跟踪property和value的一一绑定关系,只能将它们视为独立的联合成员处理。

两种可行解决方案

方案1:用泛型绑定属性与值的类型

通过泛型约束,让TypeScript准确识别property对应的value类型,彻底解决类型不匹配问题:

type RickAndMortyCharacter = {
  name: string;
  origin: { name: string; url: string };
};

// 生成可区分联合类型
type RickAndMortyCharacterChange = {
  [K in keyof RickAndMortyCharacter]: {
    property: K;
    value: RickAndMortyCharacter[K];
  }
}[keyof RickAndMortyCharacter];

// 泛型约束的处理函数
function applyPropertyChange<T extends RickAndMortyCharacter, K extends keyof T>(
  obj: T,
  change: { property: K; value: T[K] }
) {
  obj[change.property] = change.value; // 无类型报错
}

// 测试用例
const character: RickAndMortyCharacter = {
  name: "Rick Sanchez",
  origin: { name: "Earth (C-137)", url: "https://example.com" }
};

// 合法调用(TS会自动校验类型)
applyPropertyChange(character, { property: "name", value: "Rick Sanchez Jr." });
applyPropertyChange(character, { property: "origin", value: { name: "Earth (Replacement Dimension)", url: "https://example.com/replacement" } });

// 非法调用会被TS拦截(符合预期)
// applyPropertyChange(character, { property: "name", value: { name: "Test", url: "test" } });

方案2:添加类型缩小的分支判断

如果不想用泛型,可以通过switch分支基于property字段做类型缩小,让TS能识别每个分支中value的具体类型:

function applyPropertyChange(obj: RickAndMortyCharacter, change: RickAndMortyCharacterChange) {
  switch (change.property) {
    case "name":
      obj.name = change.value; // TS明确知道这里value是string类型
      break;
    case "origin":
      obj.origin = change.value; // TS明确知道这里value是origin对应的对象类型
      break;
  }
}

关于Angular项目无报错的说明

Angular项目中可能因为开启了宽松的TypeScript配置(比如关闭strictNullChecks、strictFunctionTypes),或者使用的TS版本较低,对类型推断的严格程度要求不高,所以没有触发这个报错。但从严格类型规范的角度,当前原始写法确实存在类型关联缺失的问题,上述两种方案是更严谨的解决方式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 22:57:33