在可辨识联合(discriminated union)中使用 async/await 的核心做法是:确保联合类型中的每个分支都返回相同的基础 promise 类型,并在处理函数中通过 switch 语句对标签属性进行匹配,直接 await 各分支的异步操作。这样做能利用 typescript 的类型收窄特性,保证每个分支返回值的类型安全,避免混合不同结构的 promise 导致类型推断失败。

如何定义支持异步操作的联合类型结构
定义联合类型时,必须为每个对象字面量添加唯一的字符串字面量类型作为判别字段(如 type),并确保所有分支的返回值类型统一收敛到同一个 Promise 泛型中。例如,定义一个包含 fetch 和 cache 两种策略的联合类型,两者都必须返回 Promise<data></data>,这样在后续处理时才能安全地进行类型收窄。

interface FetchStrategy {
type: 'fetch';
url: string;
}
interface CacheStrategy {
type: 'cache';
key: string;
}
type Strategy = FetchStrategy | CacheStrategy;
async function executeStrategy(strategy: Strategy): Promise<string> {
if (strategy.type === 'fetch') {
return await fetch(strategy.url).then(r => r.text());
} else {
return await getCachedData(strategy.key);
}
}
上述代码中,executeStrategy 函数接收一个 Strategy 联合类型。当 strategy.type 被判断为 'fetch' 时,TypeScript 知道此时 strategy 的具体类型为 FetchStrategy,因此可以安全访问 url 属性。同理,在 else 分支中,类型自动收窄为 CacheStrategy,可以访问 key 属性。两个分支最终都返回 Promise<string></string>,符合函数签名要求。
立即学习“Java免费学习笔记(深入)”;
如何在 switch 语句中正确展开异步逻辑
使用 switch 语句处理联合类型时,需要在每个 case 块内直接执行对应的异步操作并 await 结果。关键在于每个 case 必须明确返回数据,且不能遗漏任何联合类型中的分支,否则 TypeScript 会报错提示非穷尽匹配。同时,要确保每个分支的异步操作完成后返回的数据类型一致。

async function processRequest(strategy: Strategy) {
switch (strategy.type) {
case 'fetch':
const response = await fetch(strategy.url);
if (!response.ok) throw new Error('Network error');
return await response.json();
case 'cache':
const cached = await db.lookup(strategy.key);
if (!cached) throw new Error('Cache miss');
return cached;
default:
const _exhaustiveCheck: never = strategy;
throw new Error('Unknown strategy');
}
}
在 processRequest 函数中,switch 语句根据 strategy.type 的值分发逻辑。在 'fetch' 分支中,先 await HTTP 请求,再 await JSON 解析,最终返回解析后的对象。在 'cache' 分支中,await 数据库查询并返回结果。最后的 default 分支使用了 never 类型检查,如果未来新增联合类型分支而未在此处处理,编译器会报错,从而保证类型的完整性。
当异步操作抛出异常时如何处理类型收窄
在可辨识联合的异步处理中,如果某个分支的异步操作抛出异常,类型收窄依然有效,但需要确保错误处理逻辑覆盖所有分支。通常的做法是在每个 case 内部捕获异常或让异常向上冒泡,同时在函数顶层使用 try/catch 统一处理。由于每个分支返回的是相同的 Promise 类型,异常也会以统一的 Promise<rejected></rejected> 形式传播,不会影响联合类型的结构一致性。


















