交叉点类型中的用户定义类型保护结果

时间:2018-04-21 21:54:11

标签: typescript

我正在使用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)
}

1 个答案:

答案 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)
  }
}