TypeScript如何表示由不可变对象构成的不可变数组以满足不可修改契约?
TypeScript 类中实现数组及内部对象全不可修改的方案
报错原因
你遇到的ts(4104)错误本质是类型可变性不匹配:Readonly<Array<T>>(等价写法为readonly T[]或ReadonlyArray<T>)是只读数组类型,没有push/pop/splice等修改数组的方法,也不允许直接修改数组下标对应的元素,可变性约束比普通Array<T>更严格,因此只读数组类型的值不允许赋值给可变数组类型的变量,避免后续出现意外修改。
最优解决方案
直接将类的bars属性也声明为只读数组类型,完全符合你要求的「数组本身+内部所有对象都不可修改」的契约,修改后代码如下:
export type Foo = { foo: string }; export class Bar { // 声明为Readonly<Foo>可保证foo对象的内部属性也不可修改 readonly foo: Readonly<Foo>; // 此处将可变数组类型改为只读数组类型,两种写法等价: // readonly Readonly<Bar>[] / ReadonlyArray<Readonly<Bar>> readonly bars: readonly Readonly<Bar>[]; constructor( foo: Readonly<Foo>, bars: readonly Readonly<Bar>[], ) { this.foo = foo; this.bars = bars; } }
该方案的约束效果:
- 无法修改
Bar实例的foo属性,也无法修改foo内部的foo字段 - 无法修改
Bar实例的bars数组本身(不能增删元素、不能替换指定下标的元素) - 无法修改
bars数组内部存储的任意Bar实例的属性
不推荐的绕过方案
如果特殊场景下需要绕过类型检查,可以在赋值时添加类型断言,但该方案会破坏不可修改的约束,可能导致后续意外修改数组,仅做了解不推荐使用:
this.bars = bars as Readonly<Bar>[];
内容的提问来源于stack exchange,提问作者Ben Blank
相关产品推荐
相关产品推荐

