TypeScript:我可以使用`never` 来消除标记联合的分支吗?

问题描述

我有一个名为 Result 的通用实用程序类型,用于可能返回值或可能返回错误的操作:

export type Result<T,E> =
    | {ok: true,value: T}
    | {ok: false,err: E};

// normal use
const r: Result<number,string> = performOperation1();
if (!r.ok) {
    reportError(r.err);
    return;
}
doSomething(r.values);

如果我为 never 类型参数传入 E,我知道 ok 必须是 true,但 TypeScript 没有:

const r: Result<number,number> = performOperation2();
doSomething(r.value);

有没有办法让 TypeScript 理解在此处传入 never 会消除错误分支?

注意:在这个小例子中,performOperation2 可以只返回 number 而不是 Result。但是在我的完整代码库中,所有这些“操作”函数都符合一个返回 Result 的接口。

解决方法

如果您可以更改 Result,您可以添加条件类型以在传入 never 时不添加错误分支:


export type Result<T,E> =
    | {ok: true,value: T}
    | ([E] extends [never] ? never : {ok: false,err: E} )

declare const r2: Result<number,never>
doSomething(r2.value);

Playground Link

您还可以使用 Exclude 从联合中排除 false 分支:

declare const r2: Exclude<Result<number,never>,{ ok: false}>
doSomething(r2.value);

Playground Link

这不是对您问题的直接回答,但如果您无法更改 Result