Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to approach this method chaining in TypeScript? Error ts(2339)

I’m receiving a ts(2339) error in attempting to use method chaining on flexible methods that can be used to both get and set a private properties.

Suppose I have the following class:

export default class A {

  private _propertyA!: number;
  private _propertyB!: string;

  constructor() {
    this._propertyA;
    this._propertyB;
    this._init();
  }

  private _init() {
    // Do something in initializing the class.
  };

  public getPropertyA() {
    return this._propertyA;
  }

  public getPropertyB() {
    return this._propertyB;
  }

  public propertyA(value?: number): number | this {
    if (value === undefined) return this.getPropertyA();
    this.setPropertyA(value);
    return this;
  }

  public propertyB(value?: string): string | this {
    if (value === undefined) return this.getPropertyB();
    this.setPropertyB(value);
    return this;
  }

  public setPropertyA(value: number): this {
    this._propertyA = value;
    return this;
  }

  public setPropertyB(value: string): this {
    this._propertyB = value;
    return this;
  }

}

I have "getters" via get prefix on methods and "setters" via set prefix on methods. Then there are "shorthand" methods that are flexible that can either get or set a private property depending on whether or not an argument is provided to the method.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

When I attempt to use the following method chaining, it results in a TypeScript error (see code comments):

import A from './a';

// Results in the following TypeScript error:
const a = new A()
  .propertyA(100)
  .propertyB('value');
// Property 'propertyB' does not exist on type 'number | A'.
// Property 'propertyB' does not exist on type 'number'.ts(2339)

// Results in the following TypeScript error:
const a = new A()
  .propertyB('value')
  .propertyA(100);
// Property 'propertyA' does not exist on type 'string | A'.
// Property 'propertyA' does not exist on type 'string'.ts(2339)

// This works but we are not chaining.
const a = new A()
  .propertyA(100);

// Works as expected.
const a = new A()
  .setPropertyA(100)
  .setPropertyB('value');

TypeScript Version 4.6.3

It seems to me that TypesSript is not recognizing the return type is this when there is no argument provided to these methods and the value parameter is undefined. And the error is introduced in method chaining.

Is there a bug that I’m overlooking or how can this be adjusted to make these shorthand methods work?

Many thanks!

>Solution :

Use overloads:

  public propertyA(): number;
  public propertyA(value: number): this;
  public propertyA(value?: number): number | this {
    if (value === undefined) return this.getPropertyA();
    this.setPropertyA(value);
    return this;
  }

Then when you call without parameters it returns a number, and if you provide a value it’s this:

new A().propertyA(); // number

new A()
  .propertyA(100)
  .propertyB("foo") // assuming you did the same for propertyB
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading