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

TypeScript中Human联合类型为何允许含部分Extra字段的无效实例?

问题原因

你遇到的问题本质是TypeScript联合类型的可赋值性规则导致的:

  • 联合类型Human = Base | (Base & Extra)的判断逻辑是:只要值能赋值给联合类型中的任意一个分支,就会被视为有效。
  • {id: "123", firstName: "Seppo"}虽然包含了firstName,但它完全符合Base类型的要求(只需要有id属性)——TypeScript默认允许对象拥有额外属性,除非开启额外属性检查(但额外属性检查只在直接给对象字面量赋值给具体接口时触发,联合类型场景下不会生效)。所以TS判定这个值可以赋值给Base分支,自然就通过了类型校验。
解决方法

如果你想严格限制Human要么是仅包含Base字段的对象,要么是包含Base+Extra所有字段的对象,可以通过以下方式实现:

方法1:使用精确类型约束

通过交叉一个“禁止额外属性”的类型来定义严格的Base分支:

interface Base {
  id: string;
}

interface Extra {
  firstName: string;
  lastName: string;
}

// 定义严格的Base,禁止拥有Extra中的字段
type StrictBase = Base & { [K in keyof Extra]?: never };
type Human = StrictBase | (Base & Extra);

const validBase: Human = { id: "123" }; // 有效
const validHuman: Human = { id: "123", firstName: "Seppo", lastName: "Taalasmaa" }; // 有效
const shouldBeInvalid: Human = { id: "123", firstName: "Seppo" }; // 类型错误:firstName不能为string类型

方法2:添加判别式字段

如果业务允许,可以给两个分支添加一个区分用的判别字段,让TS能明确区分不同分支:

interface Base {
  id: string;
  type: "base";
}

interface FullHuman extends Base {
  type: "full";
  firstName: string;
  lastName: string;
}

type Human = Base | FullHuman;

const validBase: Human = { id: "123", type: "base" }; // 有效
const validHuman: Human = { id: "123", type: "full", firstName: "Seppo", lastName: "Taalasmaa" }; // 有效
const shouldBeInvalid: Human = { id: "123", type: "full", firstName: "Seppo" }; // 类型错误:缺少lastName字段

这种方式更直观,也更符合TypeScript的类型设计思路,推荐在有业务场景支撑时使用。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 18:05:18