【发布时间】:2020-11-27 03:58:48
【问题描述】:
我构建了一个小型类型级库来简化表单函数对的编写
function a(...): T | undefined;
function b(...): T;
如果返回未定义,则通过抛出异常从 a 派生 b。基本思路如下:
export enum FailMode { CanFail, CanNotFail }
export const canFail = FailMode.CanFail;
export const canNotFail = FailMode.CanNotFail
export type Failure<F extends FailMode> = F extends FailMode.CanFail ? undefined : never;
export type Maybe<T, F extends FailMode> = T | Failure<F>;
export function failure<F extends FailMode>(mode: F): Failure<F> {
if (mode === canFail) return undefined as Failure<F>;
throw new Error("failure");
}
现在我们可以将a 和b 组合成一个函数,该函数需要一个额外的参数来区分类型:
function upperCaseIfYouCan<F extends FailMode>(x: string | undefined, mode: F): Maybe<string, F> {
if (x === undefined)
return failure<F>(mode);
return x.toUpperCase();
}
// both of these now work
let y: string = upperCaseIfYouCan("foo", canNotFail); // can throw, but will never return undefined
let z: string | undefined = upperCaseIfYouCan("foo", canFail); // cannot throw, but can return undefined
现在在大多数情况下,我想要canNotFail 变体,我想知道是否有办法将其设为“默认”,因为在这种情况下我不必传递canNotFail 参数,以便以下工作:
let y: string = upperCaseIfYouCan("foo"); // can throw
我已经确定这不能通过默认参数实现,因为默认参数的类型必须与F 统一。有没有办法以不同的方式实现这一点,这样定义像 upperCaseIfYouCan 这样的函数同样容易?
【问题讨论】:
标签: typescript generics type-inference