TypeScript实例化Field类报Cannot read property 'name' of undefined错如何解决
问题原因
TypeScript的类型校验仅作用于编译阶段,你从WebSocket拿到的JSON数据属于运行时外部数据,不受TS类型约束,触发报错的常见原因如下:
data.fields数组中存在undefined/null元素:比如WebSocket返回的字段列表存在空项、上游返回的数组是稀疏数组,遍历时拿到的field值为undefined,传入Field构造函数后访问data.name就会触发该报错。你打印入参时能看到正常对象,大概率是因为数组中大部分元素都是合法的,只有个别异常项你没有注意到,或者控制台打印的对象引用是后续更新后的结果。IEmbed接口中fields字段定义可能存在偏差:比如你定义fields为IField[],但实际运行时WebSocket返回的fields实际是(IField | undefined | null)[]类型,TS编译阶段不会校验运行时的JSON数据结构,导致异常值流入后续逻辑。
解决方案
方案1:遍历数组时过滤非法值
在map之前先过滤掉数组中的null和undefined项,同时校验必填字段存在,保证传入Field构造函数的参数都是合法对象:
this.fields = data.fields .filter((field): field is IField => { return !!field && typeof field === 'object' && 'name' in field && 'value' in field }) .map(field => new Field(field))
这里的类型谓词field is IField还能帮助TS做类型收窄,避免编译报错。
方案2:给Field构造函数增加参数兜底
在Field构造函数中先判断入参是否合法,不合法就抛出明确错误或者给定默认值:
constructor(data: IField) { if (!data || typeof data !== 'object') { throw new Error(`Field构造函数入参非法,收到的值为: ${JSON.stringify(data)}`) } this.name = data.name ?? '默认字段名' this.value = data.value ?? '默认字段值' this.inline = data.inline ?? false }
方案3:增加运行时数据校验逻辑
WebSocket返回的是不受TS约束的外部数据,你可以在拿到JSON解析结果之后先做一层结构校验,确认fields数组的每一项都符合IField的结构再执行后续逻辑,从源头上避免异常数据流入业务代码。
内容的提问来源于stack exchange,提问作者Aidan
相关产品推荐
相关产品推荐

