I work with the following Typescript classes:
I have an abstract class
export abstract class MyAbstractClass { ..... }
Class A wich implements the methods of the abstract class
export ClassA extends MyAbstractClass { readonly MY_FIRST_CONTS = 'blaa'; readonly MY_SECOND_CONTS = 'blaablaaa'; .... }
class B wich 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 contantly 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!
CodePudding user response:
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';
}
}
CodePudding user response:
In order to answer this question we need to see how the compiler traduce all this in JS:
"use strict";
class AbstractClass {
}
class ClassA extends AbstractClass {
constructor() {
super(...arguments);
this.MY_FIRST_CONTS = 'blaa';
this.MY_SECOND_CONTS = 'blaablaaa';
}
}
class ClassB extends ClassA {
constructor() {
super(...arguments);
this.MY_FIRST_CONTS = 'other blaa';
this.MY_SECOND_CONTS = 'other blaablaaa';
}
}
This is easy to say, the same variable is declared twice, and Typescript give you an error because you declared the variables in ClassA
as readonly
.
If you still need the two variables both in ClassA
and ClassB
you can declared the variables in ClassA
as stricty private.
export ClassA extends MyAbstractClass {
#MY_FIRST_CONTS = 'blaa';
#MY_SECOND_CONTS = 'blaablaaa';
....
}
Now you might think to access the variables in ClassA
with a get
, but this will raise another error for the same reason.
export class ClassA extends AbstractClass {
#MY_FIRST_CONTS = 'blaa';
#MY_SECOND_CONTS = 'blaablaaa';
get MY_FIRST_CONTS() { return this.#MY_FIRST_CONTS}
get MY_SECOND_CONTS() { return this.#MY_SECOND_CONTS}
}
export class ClassB extends ClassA {
//'MY_FIRST_CONTS' is defined as an accessor in class 'ClassA', but is overridden here in 'ClassB' as an instance property.
readonly MY_FIRST_CONTS = 'other blaa';
//'MY_SECOND_CONTS' is defined as an accessor in class 'ClassA', but is overridden here in 'ClassB' as an instance property.
readonly MY_SECOND_CONTS = 'other blaablaaa';
}
So, to make this works, you have to wrap the variables in a get
method, and then override the get
methods in ClassB
:
export abstract class AbstractClass {
}
export class ClassA extends AbstractClass {
#MY_FIRST_CONTS = 'blaa';
#MY_SECOND_CONTS = 'blaablaaa';
get MY_FIRST_CONTS() { return this.#MY_FIRST_CONTS}
get MY_SECOND_CONTS() { return this.#MY_SECOND_CONTS}
}
export class ClassB extends ClassA {
#MY_FIRST_CONTS = 'other blaa';
#MY_SECOND_CONTS = 'other blaablaaa';
override get MY_FIRST_CONTS() {return this.#MY_FIRST_CONTS}
override get MY_SECOND_CONTS() {return this.#MY_SECOND_CONTS}
}
CodePudding user response:
depending on your Typescript version, did you try to specify that it is override ?
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-3.html
export class ClassB extends ClassA {
override MY_FIRST_CONTS = 'blaa';
override MY_SECOND_CONTS = 'blaablaaa';
}