升级Angular12/TypeScript4.3.5后对象属性赋值报只读错误
报错原因与解决方案
根因说明
你遇到的Cannot assign to read only property 'x' of object报错不是TypeScript 4.3的语法规则变更直接导致的,触发原因有两个核心点:
- Angular 12默认开启了严格模式,开发环境下会对输入属性(@Input)、状态管理返回的数据集做不可变校验,部分场景下会自动用
Object.freeze冻结对象,禁止直接修改属性 - TypeScript 4.3增强了
readonly修饰符的推断能力,如果你获取metrics数组的接口/方法返回的是带readonly标记的类型,编译期不会抛出显性错误,但运行期会触发Angular的不可变修改拦截
你之前的排查结论是正确的:循环中用const声明metric只会限制变量本身不能被重新赋值,不会限制内部成员修改;你定义的ScaMetricGraphType类的属性也没有被标记为只读,问题出在你拿到的metrics数组实例本身是不可变的。
可行解决方案
方案1:浅拷贝对象后修改(最推荐,符合不可变最佳实践)
不修改原数组的对象,通过浅拷贝生成新对象后赋值,后续用新生成的数组做业务逻辑:
const updatedMetrics = metrics.map(metric => ({ ...metric, focalThemeSubArea: metric.focalThemeSubArea ?? metric.focalTheme }))
方案2:类型断言绕开只读限制
如果你确认必须修改原对象,可以通过工具类型移除只读标记:
// 全局定义通用可变类型工具 type Mutable<T> = { -readonly [P in keyof T]: T[P] }; for (const metric of metrics as Mutable<ScaMetricGraphType>[]) { if (!metric.focalThemeSubArea) { metric.focalThemeSubArea = metric.focalTheme; } }
如果你不想定义工具类型,也可以临时断言为any,但会丢失类型校验能力,不推荐。
方案3:关闭Angular严格模式校验(不推荐)
如果是开发模式的输入属性校验触发的报错,你可以在angular.json中关闭对应的严格校验规则,但会丢失类型安全收益,仅作为临时调试方案使用:
{ "projects": { "你的项目名": { "architect": { "build": { "options": { "strictTemplates": false, "strictInputTypes": false } } } } } }
内容的提问来源于stack exchange,提问作者FunkMonkey33
相关产品推荐
相关产品推荐

