为什么TypeScript允许const声明的对象中存在重复索引属性?
当你在TypeScript中声明带有重复静态属性名的常量时,编译器会给出明确的错误提示。
const doesNotCompile1 = { a: 1, a: 2 }; const doesNotCompile2 = { ['a']: 1, ['a']: 2 }; const doesNotCompile3 = { a: 1, ['a']: 2 };
严格模式下对象字面量不能包含多个同名属性。(1117)
重复的标识符 'a'。(2300)
如果你声明了一个常量字符串字面量,将其与静态常量同名混用也会触发相同的错误:
const a = 'a'; const doesNotCompile4 = { a: 1, [a]: 2 }; const doesNotCompile5 = { ['a']: 1, [a]: 2 };
但如果将同一个常量作为两个独立属性的键,却不会触发编译报错:
const a = 'a'; const b = 'a'; const compiles1 = { [a]: 1, [a]: 2 }; const compiles2 = { [a]: 1, [b]: 2 };
行为原因说明
这种看似矛盾的表现是TypeScript的刻意设计,核心出于两个层面的考量:
- 编译性能的权衡:重复属性的校验逻辑只会针对编译期可以直接判定为完全相等的属性键生效,包括静态字面量键、直接包裹字面量的计算键、以及直接和字面量键等值的常量引用。如果要支持跨变量的等值校验,需要TS在编译阶段做全链路的常量传播和等值追踪,对于大型项目来说,这会带来不可接受的编译性能损耗。
- 校验边界的一致性:JavaScript本身就允许对象字面量存在重复的属性键,后定义的属性会直接覆盖之前的属性,属于标准允许的运行时行为。TypeScript的静态校验只会覆盖可以100%确定存在问题、且不会带来额外编译负担的场景,跨变量的等值判定很容易出现误判(比如后续变量类型被修改为联合类型),所以TS没有把这种场景纳入校验范围。
如果你的项目需要避免这种属性覆盖的问题,可以通过ESLint的no-dupe-keys规则扩展自定义检测逻辑来实现。
内容的提问来源于stack exchange,提问作者dx_over_dt
相关产品推荐
相关产品推荐

