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

TypeScript联合类型为何允许所有指定键?如何实现严格互斥联合?

实现TypeScript严格互斥联合类型

你遇到的问题源于TypeScript默认联合类型的包容特性——只要对象符合联合中任意一个成员的结构,就会被判定为合法,因此需要通过额外约束实现严格互斥:对象只能匹配联合类型中的某一个成员,不能同时包含多个成员的属性。

解决方案1:显式添加互斥属性的never约束

直接给每个联合成员添加对方属性的never类型(设为可选,避免无属性时的报错),当对象同时包含跨成员属性时,会触发类型冲突:

type Person = 
  // 仅允许id,禁止firstName/lastName
  | { id: string; firstName?: never; lastName?: never }
  // 仅允许firstName/lastName,禁止id
  | { firstName: string; lastName: string; id?: never };

验证示例:

// 合法:仅包含id
const validPerson1: Person = { id: 'user-123' };
// 合法:仅包含名字属性
const validPerson2: Person = { firstName: 'Alice', lastName: 'Smith' };

// 报错:Type 'string' is not assignable to type 'never'(同时包含id和名字属性)
const invalidPerson1: Person = { id: 'user-456', firstName: 'Bob', lastName: 'Brown' };
// 报错:未知属性foo(符合预期)
const invalidPerson2: Person = { firstName: 'Charlie', lastName: 'Davis', foo: 'extra' };

解决方案2:封装通用工具类型

如果需要复用严格互斥逻辑,可以封装工具类型StrictUnion,自动处理联合类型的互斥约束:

type StrictUnion<T extends object> = T extends infer U 
  ? U & { [K in Exclude<keyof T, keyof U>]?: never } 
  : never;

// 用工具类型定义目标类型
type Person = StrictUnion<{ id: string } | { firstName: string; lastName: string }>;

这个工具类型的原理是:对联合类型的每个成员U,自动添加其他成员的属性并将其类型设为never,从而禁止跨成员属性共存。

原理说明

TypeScript的联合类型是包容式的——只要对象满足任意一个成员的结构要求,就会被视为合法。通过添加never类型的互斥属性,我们强制对象只能匹配联合中的某一个成员:若同时包含其他成员的属性,属性类型会发生冲突(string无法赋值给never),触发类型检查错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 21:15:37