TypeScript中[boolean, string?]与[boolean, string]|[boolean]为何类型不同?
TypeScript可选元组与联合元组不等价的原因
这是TypeScript团队刻意做出的设计决策,二者在语义和类型约束上存在本质差异,如果强制判定为等价会引发明确的类型漏洞,核心差异点如下:
1. length属性的类型语义不同
- 联合类型
[boolean] | [boolean, string]的length是明确的字面量联合类型1 | 2,支持基于length的类型窄化:
function handleUnion(u: [boolean] | [boolean, string]) { if (u.length === 2) { // 此处u会被自动窄化为[boolean, string],第二个元素100%为string类型 const str = u[1].toUpperCase() // 无类型报错 } }
- 可选元组
[boolean, string?]的length类型为通用number,无法基于length做类型窄化:
function handleOptional(o: [boolean, string?]) { if (o.length === 2) { // 此处u[1]的类型依旧是string | undefined,无法保证一定存在 const str = u[1].toUpperCase() // ts提示对象可能为undefined } }
2. 可选元素允许传入undefined,联合元组无此语义
可选元组的可选元素支持显式赋值为undefined,是合法的类型取值:
const opt: [boolean, string?] = [true, undefined] // 完全符合类型要求
而联合类型中[boolean, string]分支要求第二个元素必须为合法string,不允许传入undefined:
const uni: [boolean] | [boolean, string] = [true, undefined] // 类型报错
如果TS将二者判定为等价,会直接破坏联合元组的类型约束:你可以将第二个元素为undefined的可选元组赋值给联合元组,导致本该保证为string的位置出现undefined,引发运行时错误。
内容的提问来源于stack exchange,提问作者KernelDeimos
相关产品推荐
相关产品推荐

