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?
CodePudding user response:
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);