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

TypeScript: Can I use `never` to eliminate branches of a tagged union?

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

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);

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

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

有没有办法让 TypeScript 理解这里传入 never 可以消除错误分支?

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

如果你可以改变 Result 你可以添加一个条件类型,如果传入 never 则不添加 false 分支:


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