1

I am struggling with defining a method to take subclasses of a base class correctly.

handle(content: AbstractClass)

Calling it directly with an inherited class leads to Argument of type 'ConcreteClass' is not assignable to parameter of type 'AbstractClass'.

I have tried it with an interface, similar result Argument of type 'typeof ConcreteClass' is not assignable to parameter of type 'Interface'

class AbstractClass implements Interface

handle(content: Interface)

I have found a question to a similar topic but the solution also don't helps me.

interface ClassConstructor<T extends AbstractClass> {
  new(): T;
}

abstract class AbstractClass {
  private test: string;

  constructor(value: string) {}
}

class B extends AbstractClass {
  private test2: string;

  constructor(value: string, value2: number) {
    super(modal);
  }
}

class S1 {
  show(content: ClassConstructor<AbstractClass>) {}

  b() {
    this.a(B);
  }
}

On playground

I want to achieve that the method show can take every implementation of the AbstractClass regardless how it is defined f.e. different constructors and similar.
I am using it in combination with Angular and Angular resolves dependencies via the constructor.

How can I do this with TypeScript?

CSchulz
  • 10,882
  • 11
  • 60
  • 114

1 Answers1

0

That's because the signatures of the constructors don't match.

This works:

interface ClassConstructor<T extends A> {
    new(value: string): T;
}

class B extends A {
    private test2: string;

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

class S1 {
    a(content: ClassConstructor<B>) {}
    b() {
        this.a(B);
    }
}

Now the different constructors share the same signature.

Nitzan Tomer
  • 155,636
  • 47
  • 315
  • 299
  • So it is not possible to use if the constructors are different? – CSchulz Jul 27 '17 at 11:17
  • If the constructors are different then you probably need a different solution. What is your exact use case? In the code you provided so far you can just change it to `a(content: { new (value: string, value2: number): B }) {}` and everything works out well. There's no real need for the `ClassConstructor`. So please update your question with your real scenario, then you might get an answer that helps you – Nitzan Tomer Jul 27 '17 at 11:20
  • I have updated my question. I hope it is more clear now. I have a base class which will be extended on different ways and with different constructors caused by different dependencies. I want to achieve that the given method can take every implementation. – CSchulz Jul 27 '17 at 11:28
  • 2
    You can change the `ClassConstructor` to have this: `new(...args: any[]): T;`. That should match all of the different signatures – Nitzan Tomer Jul 27 '17 at 11:50