Reputation: 21932
This compiles just fine:
class Foo<F> {
bar: Array<F> = [];
static create<F, T extends Foo<F>>(this: new () => T): T {
return new this();
}
}
class Foo2 extends Foo<string> {}
const foo = Foo2.create();
But if I convert Array<F>
to Array<(a: F) => void>
, the same code fails:
class Foo<F> {
bar: Array<(a: F) => void> = [];
static create<F, T extends Foo<F>>(this: new () => T): T {
return new this();
}
}
class Foo2 extends Foo<string> {}
const foo = Foo2.create();
^^^
The 'this' context of type 'typeof Foo2' is not assignable to method's 'this' of type 'new () => Foo<unknown>'.
Types of construct signatures are incompatible.
Type 'new () => Foo2' is not assignable to type 'new () => Foo<unknown>'.
Type 'Foo2' is not assignable to type 'Foo<unknown>'.
Type 'unknown' is not assignable to type 'string'. ts(2684)
It works if I type it manually:
const foo = Foo2.create<string, Foo2>();
So for some reason TypeScript can't infer the string
type if it's used in a function argument. Why is this?
Upvotes: 3
Views: 137
Reputation: 36594
I'm not sure why TypeScript is not figuring the type out, but I think you had a few mistakes that you got away with anyway, particularly the F
type in the method declaration overriding the F
in the class itself.
Your code can be simplified as follows:
class Foo<F> {
bar: Array<(a: F) => void> = [];
static create<T>(this: new () => T) {
return new this();
}
}
class Foo2 extends Foo<string> {}
const foo = Foo2.create();
And it'll work fine:
Update: Sorry, I misread the question originally. The answer has since been updated.
Upvotes: 1