我正在使用Typescript,并试图看看我是否可以创建Either
类型的概念来表示成功和失败路径。我创建了一个用户定义的类型保护,通过使用符号来明确缩小成功/失败的类型。我无法弄清楚为什么isFailure分支中either
的值显示为Data & CustomError
的交集类型而不仅仅是CustomError
。
const FailureSymbol = Symbol('Failure');
interface IFailure {
symbol: Symbol;
}
type Success<T> = T
type Failure<T extends IFailure> = T
type Either<T, U extends IFailure> = Success<T> | Failure<U>
function isFailure<T, U extends IFailure>(either: Either<T, U>): either is Failure<U> {
const candidateFailure = either as Failure<U>;
return candidateFailure.symbol && candidateFailure.symbol === FailureSymbol;
}
interface Data {
data: string;
}
interface CustomFailure {
symbol: Symbol;
errorMessage: string;
}
let either: Either<Data, CustomFailure> = { data: 'success' };
if (isFailure<Data, CustomFailure>(either)) {
// inside this branch the type of either is shown to be: Data & CustomFailure
console.log('failure', either);
} else {
// inside this branch the type of either is show to be: Data
console.log('success', either)
}
答案 0 :(得分:2)
为什么isFailure分支中的任何一个的值都显示为 交叉型数据&amp; CustomError而不仅仅是CustomError
因为isFailure
在使用either
类型的值初始化Data
后立即进行检查。编译器会在适当时推断类型并使用控制流分析,因此在这种情况下,它会记住either
值具有Data
类型。如果您尝试将either
分配给声明为Data
的内容,则可以看到它,您不会收到任何错误:
const either2: Data = either; //no error, either has `Data` type here
当either
类型没有缩小时,它会按预期工作。控制流分析在函数边界处停止,因此如果函数内部具有相同的代码,则仅将其推断为CustsomFailure
:
function test(either: Either<Data, CustomFailure>) {
if (isFailure<Data, CustomFailure>(either)) {
// here either is CustomFailure
console.log('failure', either);
} else {
// inside this branch the type of either is show to be: Data
console.log('success', either)
}
}