Angular动态对象绑定ngModel报TS2339属性不存在错误
报错原因
这个TS2339错误是TypeScript编译阶段的静态类型检查错误,和运行时对象属性是否真实存在无关。
你初始化newWaste元素时,TS推导的对象类型仅包含固定声明的measuredDate: Date属性,模板编译阶段TS做静态扫描时,发现代码直接访问了类型定义中不存在的Metal属性,就会直接抛出编译错误。你添加的*ngIf、hasOwnProperty判断都是运行时执行的逻辑,无法绕过编译阶段的类型校验,自然解决不了问题。
可用解决方案
根据你的动态属性场景,推荐按优先级选择以下方案:
- 方案1:给对象类型添加索引签名(适配动态属性场景的规范写法)
定义newWaste数组元素的类型时,补充字符串索引签名,明确告知TS该对象除固定属性外,支持任意字符串键名的自定义属性,示例:
改完后不仅当前访问// 定义对象类型 interface WasteRecord { measuredDate: Date; // 索引签名,键为字符串,值类型按你动态属性的实际类型调整即可 [key: string]: string | number | Date; } // 声明数组时指定类型 newWaste: WasteRecord[] = [{ measuredDate: new Date() }];Metal属性不会报错,后续你做完全模块化绑定,直接写newWaste[0][column]的动态键名访问也不会有类型问题。 - 方案2:使用方括号语法访问属性(无需修改TS类型)
把模板里的点语法属性访问,改成方括号传字符串键的形式,TS对这种写法不会做严格的固定属性存在性校验:
后续做全模块化动态绑定的时候,直接写<!-- 将原来的newWaste[0].Metal替换为方括号写法 --> <input type="text" matInput placeholder="" [(ngModel)]="newWaste[0]['Metal']" />[(ngModel)]="newWaste[0][column]"即可,本身就是动态键名访问的标准写法。 - 方案3:临时跳过类型检查(仅调试用,不推荐生产环境使用)
用Angular内置的$any()转换函数把对象转成弱类型,直接跳过该行的TS类型校验:<input type="text" matInput placeholder="" [(ngModel)]="$any(newWaste[0]).Metal" />
额外注意
你当前的input标签同时写了value="{{ emp[column] }}"和[(ngModel)]是冗余写法,ngModel本身会负责输入框和模型的值同步,额外加value属性反而可能导致值更新不同步的问题,建议删掉value属性。
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

