Monday, June 3, 2024
 Popular · Latest · Hot · Upcoming
94
rated 0 times [  101] [ 7]  / answers: 1 / hits: 15871  / 6 Years ago, thu, april 19, 2018, 12:00:00

I have a base class that I am trying to extend:



export class BaseClass<T extends SomeOtherClass> {
constructor(param: ParamType) {
}

doSomething(param1: Param1Type): BaseClass<T> {
// do something with param1;
return this;
}
}


My class:



export class MyClass<T extends SomeOtherClass> extends BaseClass<T> {

constructor(param: ParamType) {
super(param);
}

doSomething(param1: Param1Type, param2: Param2Type): MyClass<T> {
// super.doSomething(param1);
// do something with param2;
return this;
}
}


but I'm getting a warning:



Property 'doSomething' in type 'MyClass<T>' is not assignable to the same property in base type 'BaseClass<T>'.
Type '(param1: Param1Type, param2: Param2Type) => MyClass<T>' is not assignable to type '(param1: Param1Type) => BaseClass<T>'.


Is it not possible to extend method signatures in typescript? How do I extend the capabilities of the BaseClass if I need to add a parameter to the overridden method and is this the correct way of calling the parent method in es6 syntax. I'm aware that prior to es6 I could have called BaseClass.prototype.doSomething.call(this, param1).


More From » typescript

 Answers
8

The problem as pointed out by others is that if param2 is required it breaks polymorphism:



// We should be able to do this assignment 
let baseRef: BaseClass<SomeOtherClass> = new MyClass<SomeOtherClass>();
baseRef.doSomething() // param2 is not required by the base class so MyClass will not receive it even though it NEEDS it


One solution, is to make the second parameter optional, so the call baseRef.doSomething() is valid for the derived type as well :



export class MyClass<T extends SomeOtherClass> extends BaseClass<T> {

constructor(param: string) {
super(param);
}

doSomething(param1: string, param2?: string): MyClass<T> {
super.doSomething(param1);
return this;
}
}


A second solution, if we only want to share code between the classes, is to disallow the assignment let baseRef: BaseClass<SomeOtherClass> = new MyClass<SomeOtherClass>(); by not really inheriting BaseClass but rather inherit a class that excludes the doSomething method:



type PartialBaseClass = new <T> (param: string)  => { [P in Exclude<keyof BaseClass<T>, 'doSomething'>] : BaseClass<T>[P] }
const PartialBaseClass:PartialBaseClass = BaseClass

export class MyClass<T extends SomeOtherClass> extends PartialBaseClass<T> {

constructor(param: string) {
super(param);
}

doSomething(param1: string, param2: string): MyClass<T> {
BaseClass.prototype.doSomething.call(this, param1);
return this;
}
}
// This is now invalid !
let baseRef: BaseClass<SomeOtherClass> = new MyClass<SomeOtherClass>() ;

[#54615] Tuesday, April 17, 2018, 6 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
eliezerc

Total Points: 286
Total Questions: 102
Total Answers: 102

Location: Federated States of Micronesia
Member since Sun, May 16, 2021
3 Years ago
eliezerc questions
Mon, Jun 20, 22, 00:00, 2 Years ago
Fri, Sep 4, 20, 00:00, 4 Years ago
Fri, Jul 3, 20, 00:00, 4 Years ago
;