如何在TypeScript函数返回值中正确使用判别式联合
问题:TypeScript中如何优化判别式联合在函数返回值中的使用
我是TypeScript新手,想了解如何在函数返回值中运用判别式联合。我有一个调用两个接口的async函数,希望根据每个API的调用结果为返回值正确标注类型。
目前已定义以下类型:
interface GetDetailSuccess { status: "success"; data: MovieDetailResult; } interface GetDetailFail { status: "failed"; error: any; } interface GetCastSuccess { status: "success"; data: MovieCastResult } interface GetCastFail { status: "failed"; error: any; } type MovieDetail = GetDetailSuccess | GetDetailFail; type MovieCast = GetCastSuccess | GetCastFail; type ReturnValue = { movieDetail: MovieDetail; movieCast: MovieCast; };
简化版函数代码:
export const getMovieDetailAndCast = async ():Promise<ReturnValue> => { const movDet = {} as MovieDetail; const movCas = {} as MovieCast; await Promise.allSettled([ api.getMovieDetail(), api.getMovieCast(), ]) .then((responses) => { responses.forEach((res, index) => { if (index === 0) { if (res.status === "fulfilled") { movDet.status = "success"; if (movDet.status === "success") { movDet.data = res.value.data; } } if (res.status === "rejected") { movDet.status = "failed"; if (movDet.status === "failed") { movDet.error = res.reason.response.data.status_message; } } } if (index === 1) { if (res.status === "fulfilled") { movCas.status = "success"; if (movCas.status === "success") { movCas.data = res.value.data; } } if (res.status === "rejected") { movCas.status = "failed"; if (movCas.status === "failed") { movCas.error = res.reason.response.data.status_message; } } } }); }) .catch((err) => { console.error(err); }); return { movieDetail: movDet, movieCast: movCas, }; }
目前IDE没有报错,但不确定这种写法是否正确,尤其是类型收窄的部分,以及使用as断言空对象的操作。请问可以如何优化上述代码?
优化方案
1. 移除不安全的空对象断言
用{} as MovieDetail是空对象强制断言为联合类型,本质上不符合类型结构(空对象既没有status也没有data/error),属于不安全操作。应该直接根据API结果创建对应类型的完整对象。
2. 简化冗余的类型收窄逻辑
设置movDet.status = "success"后,TypeScript会自动将movDet的类型收窄为GetDetailSuccess,不需要额外加if (movDet.status === "success")判断,这部分是冗余代码。
3. 抽离通用逻辑,提升可读性
把单个API结果的处理逻辑抽成独立函数,避免在forEach中写大量分支判断,代码结构更清晰。
4. 统一使用async/await语法
混用await和.then/.catch会让代码逻辑割裂,统一用async/await更符合异步代码的可读性要求。
优化后的完整代码
// 抽离通用API结果处理函数 const handleApiResponse = <T>( result: PromiseSettledResult<{ data: T }> ): { status: "success"; data: T } | { status: "failed"; error: any } => { if (result.status === "fulfilled") { return { status: "success", data: result.value.data }; } return { status: "failed", error: result.reason.response.data.status_message }; }; export const getMovieDetailAndCast = async (): Promise<ReturnValue> => { // 直接获取所有API的settled结果 const [detailRes, castRes] = await Promise.allSettled([ api.getMovieDetail(), api.getMovieCast(), ]); // 处理结果并直接生成符合类型的对象 const movieDetail = handleApiResponse<MovieDetailResult>(detailRes) as MovieDetail; const movieCast = handleApiResponse<MovieCastResult>(castRes) as MovieCast; return { movieDetail, movieCast }; };
可选优化:明确错误类型
把error: any替换为具体的错误接口,让类型更严谨:
interface ApiError { status_message: string; // 可以添加其他错误字段,比如状态码等 } // 更新失败类型定义 interface GetDetailFail { status: "failed"; error: ApiError; } interface GetCastFail { status: "failed"; error: ApiError; }
优化后的代码既符合判别式联合的类型要求,TypeScript能通过status字段准确收窄类型,又避免了不安全的类型断言,代码可读性和可维护性都大幅提升。
内容的提问来源于stack exchange,提问作者chetmanleyy
相关产品推荐
相关产品推荐

