TypeScript条件判断后无法收窄类型,报ip属性不存在错误
TypeScript类型收窄失效:Property 'ip' does not exist on type 'IpDetails | Error'
遇到如下TypeScript错误:
Property 'ip' does not exist on type 'IpDetails | Error'. Property 'ip' does not exist on type 'Error'.ts(2339)
即便使用"message" in res检查或isError类型守卫收窄类型,错误依然存在。
问题原因
你自定义的Error接口和JavaScript全局内置的Error类重名了,TypeScript会优先绑定全局的Error类型(对应原生错误对象,自带message、name等属性,但没有你定义的error属性),导致你的类型守卫无法正确识别自定义的错误结构,自然无法完成类型收窄。
解决方案
重命名自定义的错误接口,避免和全局类型冲突,同步调整相关代码即可解决:
- 重命名自定义错误接口,比如改为
ApiError - 更新类型守卫函数的参数与返回类型
- 修改
getIpData的返回Promise类型
修正后的完整代码:
interface IpDetails { ip : string, } // 重命名接口,避免和全局Error冲突 interface ApiError { error: { code : number, message: string, }, } let collection: IpDetails[] = []; // 调整类型守卫的参数和返回类型 function isApiError(res: IpDetails | ApiError): res is ApiError { return (res as ApiError).error !== undefined; } const getIpData = async (ipAddress: string, config: any = {}): Promise<IpDetails|ApiError> => { return new Promise((resolve, reject) => { resolve({ip : '1.1.1.1'}); }); } (async () => { let res = await getIpData('1.1.1.1'); if (!isApiError(res)) { let duplicate = collection.find(entry => entry.ip === res.ip); // 错误消失 } })();
如果想用in操作符做类型收窄,同样要使用重命名后的接口:
if (!('error' in res)) { let duplicate = collection.find(entry => entry.ip === res.ip); }
补充说明
全局Error是TypeScript内置的原生类型,和你自定义的结构完全不同。永远不要用内置全局类型的名称来定义自己的接口/类型,避免这类命名冲突。
内容的提问来源于stack exchange,提问作者Eugene
相关产品推荐
相关产品推荐

