TypeScript 联合类型访问属性报不存在错误,如何让TS正确识别?
报错原因
TypeScript 对联合类型默认只允许访问所有类型成员共有的属性,placeName、postalCode 是 AddressBookingStop 独有的属性,place_name、postal_code 是 ShowBookingStop 独有的属性,所以直接访问会触发类型错误,和运行时的兼容逻辑无关。
解决方案
以下是几种常用的修复方案:
方案1:使用
in运算符做类型收窄(推荐)
TS 原生支持识别in运算符的判断逻辑,自动收窄联合类型,无额外运行时代码,类型安全:function formatAddress(stop: AddressBookingStop|ShowBookingStop): string { const place = 'placeName' in stop ? stop.placeName : stop.place_name; let address = [stop.street || place, stop.city, stop.province].filter(s => s).join(', '); const postalCode = 'postalCode' in stop ? stop.postalCode : stop.postal_code; if (postalCode) { address += ` ${postalCode}`; } return address; }方案2:自定义类型守卫
如果多处需要判断这两个类型,可以抽成可复用的类型守卫函数:function isAddressBookingStop(stop: AddressBookingStop|ShowBookingStop): stop is AddressBookingStop { return 'placeName' in stop; } function formatAddress(stop: AddressBookingStop|ShowBookingStop): string { const place = isAddressBookingStop(stop) ? stop.placeName : stop.place_name; let address = [stop.street || place, stop.city, stop.province].filter(s => s).join(', '); const postalCode = isAddressBookingStop(stop) ? stop.postalCode : stop.postal_code; if (postalCode) { address += ` ${postalCode}`; } return address; }方案3:类型断言(快速修复)
如果你确认逻辑没有问题,可以用类型断言绕过校验,改造成本最低:function formatAddress(stop: AddressBookingStop|ShowBookingStop): string { let address = [stop.street || (stop as AddressBookingStop).placeName || (stop as ShowBookingStop).place_name, stop.city, stop.province].filter(s => s).join(', '); const postalCode = (stop as AddressBookingStop).postalCode || (stop as ShowBookingStop).postal_code; if (postalCode) { address += ` ${postalCode}`; } return address; }方案4:定义统一兼容类型
如果多个函数都需要处理这两种类型,可以预先定义包含所有可能属性的类型,原有逻辑不用修改:type UnifiedBookingStop = (AddressBookingStop | ShowBookingStop) & { placeName?: string; place_name?: string; postalCode?: string; postal_code?: string; } function formatAddress(stop: UnifiedBookingStop): string { let address = [stop.street || stop.placeName || stop.place_name, stop.city, stop.province].filter(s => s).join(', '); const postalCode = stop.postalCode || stop.postal_code; if (postalCode) { address += ` ${postalCode}`; } return address; }
内容的提问来源于stack exchange,提问作者mpen
相关产品推荐
相关产品推荐

