Reputation: 257
Using typescript 3.0+. See the following simple setup involving generic typed variables:
abstract class BaseClass {
public abstract merge<T>(model?: T): T;
}
class MyClass extends BaseClass {
public Value: string;
public merge<MyClass>(model?: MyClass): MyClass {
this.Value += model.Value; // <--Property 'Value' does not exist on type 'MyClass'
return this; // <--Type 'this' is not assignable to type 'MyClass'.
// Type 'MyClass' is not assignable to type 'MyClass'.
// Two different types with this name exist, but they are unrelated.
}
}
I noted the errors described from the Typescript compiler but these errors don't make sense to me. Why is this wrong?
UPDATED
I understand now that the original code above the merge method in MyClass was defining a new generic typed variable with the same name as "MyClass", which explains the error. So I make the change as seen below. This still produces an error, which I commented above the merge method:
abstract class BaseClass {
public abstract merge<T>(model?: T): T;
}
class MyClass extends BaseClass {
public Value: string;
/*
Property 'merge' in type 'MyClass' is not assignable to the same property in base type 'BaseClass'.
Type '(model?: MyClass) => MyClass' is not assignable to type '<T>(model?: T) => T'.
Types of parameters 'model' and 'model' are incompatible.
Type 'T' is not assignable to type 'MyClass'.
*/
public merge(model?: MyClass): MyClass {
this.Value += model.Value;
return this;
}
}
Why can't I use MyClass as the variable type here? In fact, I can't seem to replace it with any other type that would make it work (e.g. string, number, another class).
Even if I try to define T as a type that extends BaseClass:
abstract class BaseClass {
public abstract merge<T extends BaseClass>(model?: T): T;
}
This still generates the same error in MyClass. Note that this works fine with TypeScript 2.2.1. I only noticed this not working with any TypeScript version 2.4+.
Upvotes: 1
Views: 3758
Reputation: 34403
The <MyClass>
in public merge<MyClass>
introduces another type (generic), which is different from the class MyClass
, but has the same name. Nothing is known about this generic type, therefore you get the error Property 'Value' does not exist on type 'MyClass'
.
The this
of type class MyClass
, the model
is of the generic type.
If your base class defines the method as merge<T>(model?: T): T
, the derived class needs to use the same definition. You promised in your base class you will process any parameter (generic T without any restrictions), you cannot restrict it only to MyClass
in a derived class.
Upvotes: 4