TypeScript自定义API响应类型时如何避免布尔类型拓宽报错
问题根因
TypeScript 默认推导对象字面量的布尔字段时,会将true/false自动拓宽为boolean类型,只有上下文存在明确的字面量类型约束时才会保留窄类型,你遇到的报错就是默认类型推导导致的。
你可以选择以下两种无需逐处加断言的方案解决:
方案1:封装统一响应构造函数(侵入性极低)
只需要在公共类型文件中新增两个返回固定类型的构造函数,全局复用即可:
// 放在公共类型定义文件中 export function buildSuccess<T>(data: T): SuccessfulResponse<T> { return { success: true, data }; } export function buildError(error: ERRORS): ErrorResponse { return { success: false, error }; }
之后所有接口请求的返回直接调用这两个函数即可,TS会自动匹配正确的字面量类型,不会出现类型拓宽问题:
const test = async (): APIResponse<TestContent[]> => { return axios .get("<url>") .then(({ data }) => buildSuccess(data)) .catch((error) => buildError(error)); };
这种方案还可以顺便统一做响应数据预处理、错误日志上报等通用逻辑,后续要调整响应结构只需要修改构造函数即可,不需要改动业务接口代码。
方案2:封装全局请求包装器(库级项目最优解)
如果想彻底省略所有接口的重复then/catch代码,推荐直接封装axios请求的统一 wrapper,所有接口直接调用这个 wrapper 即可:
// 公共请求工具 async function request<T>(axiosCall: Promise<{ data: T }>): APIResponse<T> { try { const response = await axiosCall; return { success: true, data: response.data }; } catch (err) { // 可在此处统一做axios错误到自定义ERRORS枚举的映射 return { success: false, error: err as ERRORS }; } }
业务接口代码可以直接简化为:
const test = async (): APIResponse<TestContent[]> => { return request(axios.get("<url>")); };
这个方案完全消除了重复的响应结构代码,后续要加请求重试、超时处理、token自动携带等通用能力都可以在wrapper里统一实现,非常适合库级项目使用。
内容的提问来源于stack exchange,提问作者WalkingPizza
相关产品推荐
相关产品推荐

