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

TypeScript定义互斥对象属性时可选属性应使用void还是never

互斥对象属性类型标注选择:void 还是 never

核心结论

这个场景下应该使用never,void属于语义误用。

原因说明

1. 两者语义完全不同

  • void的设计语义是标记函数无返回值,代表“值存在但不应被消费”,本身就合法接受undefined赋值,和你要表达的「这个属性根本不允许存在」的需求完全不匹配。
  • never的设计语义是“不存在任何符合该类型的值”,刚好匹配互斥场景下「禁止该属性出现有效值」的需求。

2. 为什么测试时x?: never能接受undefined

这不是never类型本身的问题,是TypeScript可选属性的默认行为导致的:

在默认配置下,只要属性加了?可选标记,TypeScript会自动给属性类型追加| undefined,也就是说a?: never等价于a?: never | undefined,自然可以接受undefined赋值。


实现严格互斥的正确写法

要彻底禁止互斥属性显式传undefined、同时禁止两个属性同时存在,只需要两步:

  1. 在tsconfig中开启exactOptionalPropertyTypes配置,开启后可选属性不会自动追加| undefined类型
{
  "compilerOptions": {
    "exactOptionalPropertyTypes": true
  }
}
  1. 用never标记互斥侧的可选属性
type T1 = {
    a?: never,
    b: string,
}

type T2 = {
    a: string,
    b?: never,
}

type TAllowed = T1 | T2

// 以下写法均合法
const t1: TAllowed = { a: 'abc' }
const t2: TAllowed = { b: 'bcd' }

// 以下写法均会抛出类型错误,达到严格互斥效果
const t3: TAllowed = { a: 'abc', b: 'cde' } // 同时存在a、b属性报错
const t4: TAllowed = { a: 'abc', b: undefined } // 互斥属性显式传undefined报错
const t5: TAllowed = { b: 'bcd', a: undefined } // 互斥属性显式传undefined报错

为什么不推荐用void

如果用a?: void标记互斥属性,哪怕开启了exactOptionalPropertyTypes,你依然可以合法给a赋值undefined——因为undefined本身就是void类型的合法值,无法达到“属性完全不允许出现”的严格互斥要求,语义上也不符合类型设计的初衷。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 15:48:18