打字稿::条件链接函数

时间:2019-12-10 07:04:55

标签: typescript chaining

我正在尝试实现一组链接函数,但是不知何故我陷入了困境。

  const options: any = {
      chart: {
        renderTo: 'container',
        type: 'column',
        options3d: {
            enabled: true,
            alpha: 15,
            beta: 15,
            depth: 50,
            viewDistance: 25
        }
    },
    title: {
        text: 'Chart rotation demo'
    },
    subtitle: {
        text: 'Test options by dragging the sliders below'
    },
    plotOptions: {
        column: {
            depth: 25
        }
    },
    series: [{
        data: [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4]
    }]
    };
    Highcharts.chart('columnChart', options);

我想在链中归档函数的类型检查。在上面的示例中,我希望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() 中的函数specialPlusspecialMinus仅使用一次,而ISpecialCalculator可以多次使用。我对打字稿非常了解,我一直在尝试不同的方法(高级类型(ISimpleCalculatorPick),但到目前为止没有成功。我想知道在这种情况下还有其他方法可以提供帮助。

3 个答案:

答案 0 :(得分:3)

删除某些功能很简单,您只需使用Omit<this, 'specialPlus'>如果我们测试了一下就可以了,如果您调用specialPlus,则在再次调用{ {1}},但是您可以在调用specialPlus

之后调用它
specialMinus

Playground Link

这是因为在声明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() Omit将在this类型的绑定上起作用,因此testCalculator实际上将返回specialMinus,其中仍然包含Omit<ISpecialCalculator, 'specialMinus'>,即使我们先前已将其删除。我们想要的是让specialPlus处理上一个函数返回的Omit类型。如果我们使用通用类型参数为每个调用捕获this的实际类型,并且使用该类型参数的this方法而不是多态Omit的方法,则可以做到这一点。

this

Playground Link

答案 1 :(得分:1)

specialPlus(value: number): ISimpleCalculator;

调用此函数时,您将获得一个不再具有特殊功能的简单计算器。特殊接口还应该返回this并且应该可以正常工作:

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

答案 2 :(得分:1)

尝试以下操作(根据问题测试完整代码):

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): this
  specialMinus(value: number): this
}

let testCalculator: ISpecialCalculator
testCalculator
  .plus(20)
  .multiply(2)
  .specialPlus(40)
  .plus(20)
  .minus(5)
  .specialMinus(20) 
  .sum()

如果您想限制 special [Plus | Minus] 的使用,则可以在实现 ISpecialCalculator 的具体类中完成此操作界面。

下面的代码可能会给您一些想法:

class Calculator implements ISpecialCalculator {
  specialPlusUsed = false
  specialMinusUsed = false

  specialPlus(value: number): this {
    if (this.specialPlusUsed) throw new Error("SpecialPlus can be used only once!")

    this.specialPlusUsed = true
    // Related calculations here...
    return this
  }

  specialMinus(value: number): this {
    if (this.specialMinusUsed) throw new Error("SpecialMinus can be used only once!")
    this.specialMinusUsed = true
    // Related calculations here...
    return this
  }

  plus(value: number): this {
    // Related calculations here...
    return this
  }

  minus(value: number): this {
    // Related calculations here...
    return this
  }

  divide(value: number): this {
    // Related calculations here...
    return this
  }

  multiply(value: number): this {
    // Related calculations here...
    return this
  }

  sum(): void {
    // Related calculations here...
  }
}