我正在尝试实现一组链接函数,但是不知何故我被卡在了这里。
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()
我想在链中归档函数的类型检查。在上面的示例中,我希望
specialPlus
中的函数specialMinus
和ISpecialCalculator
只能使用一次,而ISimpleCalculator
可以多次使用。我对打字稿非常了解,我一直在尝试不同的方法(高级类型(Pick
和Omit
)),但到目前为止没有成功。我想知道在这种情况下还有其他方法可以提供帮助。 最佳答案
删除某些功能很简单,您可以使用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()
Playground Link
这是因为
Omit
在声明this
时将在testCalculator
类型绑定上起作用,因此specialMinus
实际上将返回Omit<ISpecialCalculator, 'specialMinus'>
,尽管我们先前已将其删除,但它仍包含specialPlus
。我们想要的是Omit
在上一个函数返回的this
类型上工作。如果我们使用通用类型参数捕获每个调用的this
的实际类型,并且使用此类型参数的Omit
方法而不是多态this
的方法,则可以执行此操作。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()
Playground Link