I can't get the code following to type-check:
type MyFunctionConstructor<T, F extends MyFunction<T>> = new (
f: (n: number) => T
) => F;
class MyFunction<T> {
constructor(f: (n: number) => T) {
this.f = f;
}
f: (n: number) => T;
composeT(g: (t: T) => T) {
return new (this.constructor as MyFunctionConstructor<T, this>)(n =>
g(this.f(n))
);
}
composeU<U>(g: (t: T) => U) {
return new (this.constructor as MyFunctionConstructor<U, this>)(n =>
g(this.f(n)) // tsc error here, see below
);
}
}
class MyFancyFunction<T> extends MyFunction<T> {}
I get the following error:
Type 'this' does not satisfy the constraint 'MyFunction<U>'.
Type 'MyFunction<T>' is not assignable to type 'MyFunction<U>'.
Type 'T' is not assignable to type 'U'.
I don't want to call the constructor by name (i.e., new MyFunction(...)
) so that if f
is an instance of a subclass of MyFunction
(e.g., of FancyFunction
) then so are f.composeT(g)
and f.composeU(g)
. The as
casting used for the constructor call in composeT
isn't working for the more general composeU
method that has a generic parameter. How can I deal with the extra generic, U
?
(The method for making composeT
type-check is comes from this answer. This question is essentially a follow-up that I couldn't fit in a comment.)