undefined
undefined

Reputation: 6844

Typescript refer to the same type as the super method

Let's say I'm using an external library that provides the following class:

Class A {
  ...overloads types
  doSomething(param, params) {

  }
}

I want to override the super method and provide my implementation, but I want to keep the types of the original. (including the overloads)

Class B extends A {
   doSomething(param, params) {
     // ...some logic
     super.doSomething(); 
   }
}

There is a way to do this with Typescript?

Upvotes: 1

Views: 51

Answers (3)

Andrei Tătar
Andrei Tătar

Reputation: 8295

Should work fine exactly how you described it:

class A {
  test() {
    return 'from class A';
  }
}

class B extends A {
  test() {
    return super.test() + ' and from class B';
  }
}

you can play with it here on the typescript playground

To keep the args:

class A {
  test(a: number) {
    return `from class A ${a}`;
  }
}

class B extends A {
  test: A['test'] = (...args) => {
    return super.test(...args) + ' and from class B';
  }
}

and if you want it on the prototype:

class A {
  test(param: number | string): void {
    console.log(param);
  }
}

type ArgumentsType<T> = T extends (...args: infer A) => any ? A : never;

class B extends A {
  test(...args: ArgumentsType<A['test']>): ReturnType<A['test']> {
    return super.test(...args);
  }
}

Upvotes: 2

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

Reputation: 249536

Typescript does not infer parameter types based on the base type. The way things go is that the class is typed independently and then checked for inconsistencies with the base class. This also means there is no way to keep the overloads from the base class.

One way you could reduce the syntax is to assign to the prototype of B

class A {
    doSomething(param: number, params: number)
    doSomething(param: string, params: string)
    doSomething(param: number | string, params: number | string) {
        alert ("A")
    }
}

class B extends A {

}

B.prototype.doSomething = function doSomething(this: B, param, params) {
    alert("B");
    A.prototype.doSomething.call(this, arguments);
} 

new A().doSomething(0, 0)
new B().doSomething(0,0)

This way the types of the parameters are inferred and if you have an explicit annotation for this it will be typed appropriately inside the function. Only drawback is you have to use a rather large syntax to issue the super call

Upvotes: 1

Dmitriy
Dmitriy

Reputation: 2822

The syntax would be super awkward and you are no longer will be leveraging prototype, but rather defining the method in the constructor which might have performance implications but this works:

class A {
    doSomething(param: number): void
    doSomething(param: string): void
    doSomething(param: number | string): void {

    }
}

class B extends A {
    doSomething: A["doSomething"] = () => {
        A.prototype.doSomething.call(this)
    }
}

const b = new B();

b.doSomething(42) // ok
b.doSomething("foo") // ok
b.doSomething(false) // error

Upvotes: 0

Related Questions