Home > Net >  Strict typing issue with generic types in typescript
Strict typing issue with generic types in typescript

Time:12-10

I am trying to learn strict typing in Typescript.

I defined these classes:

 export abstract class MyAbstractClass<TParam extends MyParamBaseType> {
  private param: TParam;

  setInitParams(init: TParam): void {
   ...
  }

  getInitParams(): TParam {
   ....
  }
}

export class MyClass extends MyAbstractClass<AParamType> {
 private param: AParamType;

 ...
}

The problem is that I get the error " Class 'MyClass' incorrectly extends base class 'MyAbstractClass'. Types have separate declarations of a private property 'param'."

I don't understand why I get this error because AParamType type correctly extends MyParamBaseType

Can somebody helps me ? Thanks for your help.

CodePudding user response:

The private keyword is just a compile time checked. This means that the field param will be stored at runtime in the instance of the class. MyAbstractClass declares it's member private, so if MyClass were allowed to redeclare the param field it would end up accessing the same field named param in the instance at runtime breaking privacy.

You can use the ES private class fields (with #). These ensure hard privacy even at runtime and name collisions in the sub class are not an issue since each declared field is distinct even if they share the same name:

type MyParamBaseType = {}
export abstract class MyAbstractClass<TParam extends MyParamBaseType> {
  #param!: TParam;

  setInitParams(init: TParam): void {

  }

  getInitParams(): TParam {
    return this.#param;
  }
}

type AParamType = {}
export class MyClass extends MyAbstractClass<AParamType> {
  #param!: AParamType;

}

Playground Link

Or if you want to access the same field from the base class you might consider protected instead:

 type MyParamBaseType = {}
 export abstract class MyAbstractClass<TParam extends MyParamBaseType> {
  protected param!: TParam;

  setInitParams(init: TParam): void {

  }

  getInitParams(): TParam {
    return this.param
  }
}

type AParamType = {}
export class MyClass extends MyAbstractClass<AParamType> {
 protected param!: AParamType;

}

Playground Link

  • Related