如何让TypeScript在非错误响应时识别data必存在?
解决TypeScript中HTTP响应成功时data必存在的类型收窄问题
核心问题在于你最初定义的HTTPResponse<T>接口无法让TypeScript建立ok状态与data/error存在性的关联——即使ok为true,TypeScript仍会认为data可能未定义。要解决这个问题,最有效的方式是用联合类型拆分成功/错误响应,让类型系统直接感知状态与字段的对应关系:
1. 重新定义响应类型
将原有的单一接口拆分为成功、错误两个互斥的接口,再组合成联合类型:
// 成功响应:ok为true时,data必存在,error不存在 interface HTTPSuccessResponse<T> { ok: true; data: T; init: ResponseInit; error?: never; // 明确标记成功状态下error不可能存在 } // 错误响应:ok为false时,error必存在,data不存在 interface HTTPErrorResponse { ok: false; error: HTTPError; init: ResponseInit; data?: never; // 明确标记错误状态下data不可能存在 } // 最终的HTTP响应类型是两者的联合 type HTTPResponse<T> = HTTPSuccessResponse<T> | HTTPErrorResponse;
2. 优化类型守卫(可选)
如果你仍需要使用类型守卫函数,可以对应调整:
// 错误响应类型守卫 export function isHTTPError(object: any): object is HTTPErrorResponse { return object.ok === false && "error" in object; } // 成功响应类型守卫(可选,因为TypeScript可通过ok自动收窄) export function isHTTPSuccess<T>(object: any): object is HTTPSuccessResponse<T> { return object.ok === true && "data" in object; }
3. 使用时的类型收窄
现在无论是直接判断ok状态,还是用类型守卫,都只需一次检查,TypeScript就能自动推断字段的存在性:
方式一:直接通过ok判断
function handleResponse<T>(response: HTTPResponse<T>) { if (!response.ok) { // 此处TypeScript自动推断为HTTPErrorResponse,error必存在 console.error(response.error.message); return; } // 此处自动推断为HTTPSuccessResponse,data必存在 processData(response.data); }
方式二:使用类型守卫
function handleResponse<T>(response: HTTPResponse<T>) { if (isHTTPError(response)) { console.error(response.error); return; } // 剩余分支自动推断为成功响应,data必存在 processData(response.data); }
这种方案彻底避免了两次检查的问题,同时让类型定义更精准,符合HTTP响应的实际业务逻辑——成功时必有数据,错误时必有错误信息。
内容的提问来源于stack exchange,提问作者nilobarp
相关产品推荐
相关产品推荐

