Property x in type ClassB is not assignable to the same property in base type ClassA

Viewed 647

I work with the following Typescript classes:

  1. I have an abstract class

    export abstract class MyAbstractClass {
    .....
    }
    
  2. Class A which implements the methods of the abstract class

    export ClassA extends MyAbstractClass {
    
    readonly MY_FIRST_CONTS = 'blaa';
    readonly MY_SECOND_CONTS = 'blaablaaa';
    
    ....
    }
    
  3. class B which extends class A and I want to override the MY_FIRST_CONTS value. No other implementation is set

    export ClassB extends ClassA {
    
    readonly MY_FIRST_CONTS = 'other blaa';
    readonly MY_SECOND_CONTS = 'other blaablaaa';
    
    ....
    }
    

I constantly get the following error at the line of MY_FIRST_CONST in ClassB:

   Property 'MY_FIRST_CONST' in type 'ClassB' is not assignable to the same property in base type 'ClassA'.

Type '"other blaa"' is not assignable to type '"blaa"'.

I do not get why this error comes and even less why it does not happen with MY_SECOND_CONST.

Any ideas? Thanks a lot!

2 Answers

You have a design problem. The technical problem comes from the fact that you are overriding a readonly attribute in a subclass, which does not make sense.

Either you want subclasses to be able to change the value, then it should not be readonly. Or you don't want subclasses to be able to change the value, then you cannot declare a different value in the subclass.

But, you might also want subclasses to be able to define a value that cannot be changed after instantiation. This can be done either with an appropriate constructor or with getters :

With a constructor :

export class ClassA extends MyAbstractClass {

  readonly foo;

  constructor(foo = 'foo') {
    super();
    this.foo = foo;
  }
}

export class B extends ClassA {

  constructor() {
    super('bar')
  }
}

With getters :

export class ClassA extends MyAbstractClass {
  get foo() {
    return 'foo';
  }
}

export class B extends ClassA {
  get foo() {
    return 'bar';
  }
}

Given that specific error message, the problem is actually that the compiler is interpreting your class A properties as being typed as specifc strings and not string itself and the error message is telling you that the the new "string" is not compatible with the only string value allowed.

You can see this if you hover over the MY_FIRST_CONTS property and see what TypeScript thinks the type is (not string but blaa!).

If we explicitly type MY_FIRST_CONTS and MY_SECOND_CONTS as string, there are no additional problems.

export abstract class MyAbstractClass {
}

class ClassA extends MyAbstractClass {
  readonly MY_FIRST_CONTS: string = 'blaa';
  readonly MY_SECOND_CONTS: string = 'blaablaaa';
}

class ClassB extends ClassA {
  readonly MY_FIRST_CONTS = 'other blaa';
  readonly MY_SECOND_CONTS = 'other blaablaaa';
}

TypeScript Playground

Related