0

I am trying to wrap my head around this. I have been working with generics in Java and C#, but only recently in TypeScript. So, can someone please explain to me this madness?

constructor FooAdapter(): FooAdapter

Type 'FooAdapter' is not assignable to type 'A'.

'FooAdapter' is assignable to the constraint of type 'A', but 'A' could be instantiated with a different subtype of constraint 'FooAdapter'.

ts(2322)

From the following snippet:

interface IFoo {}

interface IAdapter<F extends IFoo> {
   getFoo():F
}

abstract class AbstractFoo<F extends IFoo> {
   abstract something<A extends IAdapter<F>>():A;
}


class Foo implements IFoo {}
class FooAdapter implements IAdapter<Foo> {
   getFoo() { return new Foo(); }
}

class FooFactory extends AbstractFoo<Foo> {
   something<A extends FooAdapter>():A {
      return new FooAdapter();  // <--- ts(2322) here
   }   
}

How to fix this error?

Yanick Rochon
  • 51,409
  • 25
  • 133
  • 214
  • Does this answer your question? [How to fix TS2322: "could be instantiated with a different subtype of constraint 'object'"?](https://stackoverflow.com/questions/56505560/how-to-fix-ts2322-could-be-instantiated-with-a-different-subtype-of-constraint) – zerkms Sep 28 '22 at 01:40
  • I also changed your code to show why it's a problem (line 28): https://www.typescriptlang.org/play?#code/JYOwLgpgTgZghgYwgAgJIDED2nkG8C+AUIaJLIiqgIIAmcADmQDzrIQAekINAzmlpgB8eQsjEBzCGAEAKAJQAudISKE4AIx5goiMMgQAbODz5VN23QJZtOEbnwzZhuUWI1adCPT0wBbKQAWoOJMVDZcvGi0DMzogoLyClQA3CrEhIbGfALIwL70BhD+4A45BBlGJsgC0YzQufmFxWAOtbFOImLIktLY8njIUFIArlAgyCAQAO7VfXLJyESqmVUAQlJkNXR1UOF2kVsx9S5iCHAGBgCyEInIAG6YwDR4S8Qr2djouphQAJ579mQZg8lmwLA6JzEPn8YCCIBCYQ4EQ+mDa0ASijCkK6gxGYwm01mqO2ZHkC2QAHoKcgmABaenIFoyABMAGZmcy5MgAtAIK5Fl00hlMCAtMgYMgALwEmYCL5eH6-MnC0V6YYBADyASl4oAdNDAsEmOswJtsGioBjkkA – zerkms Sep 28 '22 at 01:45

1 Answers1

2

The issue is that FooAdapter is not A, FooAdapter may only be the parent class of A.

Your options here are:

A) Make something's return more generic so that it is happy with new FooAdapter():

interface IFoo {}

interface IAdapter<F extends IFoo> {
   getFoo():F
}

abstract class AbstractFoo<F extends IFoo> {
   abstract something(): IAdapter<F>;
}


class Foo implements IFoo {}

class FooAdapter implements IAdapter<Foo> {
   getFoo() { return new Foo(); }
}

interface IHasEmptyConstructor<T> {
    new(): T
}

class FooFactory extends AbstractFoo<Foo> {
   something(): IAdapter<Foo> {
      return new FooAdapter();
   }   
}

const fooFactory = new FooFactory();

fooFactory.something();

B) Make something return A instead of FooAdapter:

interface IFoo {}

interface IAdapter<F extends IFoo> {
   getFoo():F
}

abstract class AbstractFoo<F extends IFoo> {
   abstract something<A extends IAdapter<F>>(adapter: IHasEmptyConstructor<A>):A;
}


class Foo implements IFoo {}

class FooAdapter implements IAdapter<Foo> {
   getFoo() { return new Foo(); }
}

interface IHasEmptyConstructor<T> {
    new(): T
}

class FooFactory extends AbstractFoo<Foo> {
   something<A extends FooAdapter>(adapter: IHasEmptyConstructor<A>): A {
      return new adapter();
   }   
}

const fooFactory = new FooFactory();

fooFactory.something(FooAdapter);
Jacob Smit
  • 2,206
  • 1
  • 9
  • 19