Kevin
Kevin

Reputation: 15

Typescript can class methods allow method chaining without returning 'this'?

I have made a Mycalculator class that implements the following Calculator Interface to be method chaining.

interface Calculator {
  add(a: number): void
  sub(a: number): void
  div(a: number): void
  mul(a: number): void
  display(decimalToDisplay: number): void
  allClear(): void
  reset(value: number): void
}


class MyCalculator implements Calculator {
  private _current: number;

  constructor(public value: number) {
    this._current = value
  }

  add(a: number): MyCalculator {
    this.current += a
    return this
  }
  sub(a: number): MyCalculator {
    this.current -= a
    return this
  }
  div(a: number): MyCalculator {
    this.current /= a
    return this
  }
  mul(a: number): MyCalculator {
    this.current *= a
    return this
  }

  get current (): number {
    return this._current
  }

  set current (result: number)  {
    this._current = result
  }

  reset (value: number) {
    this.current = value
    return this
  }

  display(decimalToDisplay: number = 2): MyCalculator {
    console.log(this.current.toFixed(decimalToDisplay))
    return this
  }

  allClear(): MyCalculator {
    this.current = 0
    return this
  }

}

// Test
new MyCalculator(3).add(5).mul(5).div(3).div(3).display() // 4.44
new MyCalculator(5).add(5).mul(5).div(5).display().allClear().reset(5).add(5).display() // 10.00, 10.00

In the above code, I have some questions

Thanks for any help!

Upvotes: 1

Views: 2035

Answers (1)

Schorsch
Schorsch

Reputation: 319

You do this right. Returning this is the normal way to implement method chaining. But there are some problems. The methods should the interfaces type.

interface Calculator {
  add(a: number): Calculator
  sub(a: number): Calculator
  div(a: number): Calculator
  mul(a: number): Calculator
  display(decimalToDisplay: number): void
  allClear(): void
  reset(value: number): void
}

Even in you implementation of this interface, the resulting type is Calculator. What you want is called polymorphism. The caller of the method just wants some Calculator as result and it is not important what kind of implementation he gets. So one example for such a method would look like that:

class MyCalculator implements Calculator {
// ...
  add(a: number): Calculator {
    this.current += a
    return this
  }
// ....
}

But mind that your calculator doesn't work correct. 1 + 2 * 3 is the same as 1 + (2 * 3) but your calculator would treat that as (1 + 2) * 3. Maybe you don't want this behavior.

Upvotes: 2

Related Questions