打字稿::条件链接函数

Nel*_*ang 6 chaining typescript

我正在尝试实现一组链式函数,但不知何故我卡在这里了。

interface ISimpleCalculator {
  plus(value: number): this;
  minus(value: number): this;
  divide(value: number): this;
  multiply(value: number): this;
  sum(): void
}

interface ISpecialCalculator extends ISimpleCalculator {
  specialPlus(value: number): ISimpleCalculator;
  specialMinus(value: number): ISimpleCalculator;
}

let testCalculator: ISpecialCalculator;
testCalculator  
  .plus(20)
  .multiply(2)
  .specialPlus(40)  
  .plus(20)
  .minus(5)
  .specialMinus(20)  //<-- Error! Property 'specialMinus' does not exist on type 'ISimpleCalculator'.
  .sum()
Run Code Online (Sandbox Code Playgroud)

我想存档链中函数的类型检查。在上面的例子中,我希望函数specialPlusspecialMinusinISpecialCalculator只使用一次,ISimpleCalculator可以多次使用。我对打字稿很陌生,到目前为止我一直在尝试不同的方法(高级类型(Pick& Omit))但没有成功。我想知道在这种情况下有没有其他方法可以提供帮助。

Tit*_*mir 3

删除一些函数很简单,你可以使用Omit<this, 'specialPlus'>如果我们测试它几乎可以工作,如果你调用,specialPlus如果你在另一个调用之后立即调用它,你会得到一个错误,specialPlus但是你可以在调用之后调用它 specialMinus

interface ISpecialCalculator extends ISimpleCalculator {
  specialPlus(value: number): Omit<this, 'specialPlus'>;
  specialMinus(value: number): Omit<this, 'specialMinus'>;
}

declare let testCalculator: ISpecialCalculator;
testCalculator  
  .specialPlus(40)
   // .specialPlus(40) // error 
  .specialMinus(20)
  .specialPlus(40) //ok 
  .sum()
Run Code Online (Sandbox Code Playgroud)

游乐场链接

这是因为它将在声明时Omit作用于this类型绑定,因此实际上将返回,即使我们之前删除了它,它仍然会包含它。我们想要的是处理前一个函数返回的类型。如果我们使用泛型类型参数捕获每个调用的实际类型,并且使用此类型参数而不是多态的方法,我们就可以做到这一点。testCalculatorspecialMinusOmit<ISpecialCalculator, 'specialMinus'>specialPlusOmitthisthisOmitthis

interface ISimpleCalculator {
  plus<TThis>(this: TThis,value: number): TThis;
  minus<TThis>(this: TThis,value: number): TThis;
  divide<TThis>(this: TThis,value: number): TThis;
  multiply<TThis>(this: TThis,value: number): TThis;
  sum(): void
}

interface ISpecialCalculator extends ISimpleCalculator {
  specialPlus<TThis>(this: TThis, value: number): Omit<TThis, 'specialPlus'>;
  specialMinus<TThis>(this: TThis, value: number): Omit<TThis, 'specialMinus'>;
}

declare let testCalculator: ISpecialCalculator;
testCalculator
  .specialPlus(40)
  // .specialPlus(40) // error 
  .specialMinus(20)
  .plus(10)
  .specialPlus(40) // also error 
  .plus(10)
  .sum()
Run Code Online (Sandbox Code Playgroud)

游乐场链接