Reputation: 269
class Foo<T> {
remake(){
return new Foo<T>;
}
recast(){
return this as any as Foo<Array<T>>
}
}
I want to make Child class of Foo
Class.
Child class should be referencing itself on remake
and recast
also, If there has other syntax for change to generics of instance, it will be good to me.
Upvotes: 0
Views: 1125
Reputation: 30929
You can implement remake
using this.constructor
and type it using the this
type. recast
needs higher-kinded types or a way of faking them, as below, and needs you to explicitly specify the type constructor for each subclass (it might be possible to infer this automatically with a native implementation of higher-kinded types).
// Matt's mini "type functions" library
const INVARIANT_MARKER = Symbol();
type Invariant<T> = { [INVARIANT_MARKER](t: T): T };
interface TypeFuncs<C, X> {}
const FUN_MARKER = Symbol();
type Fun<K extends keyof TypeFuncs<{}, {}>, C> = Invariant<[typeof FUN_MARKER, K, C]>;
const BAD_APP_MARKER = Symbol();
type BadApp<F, X> = Invariant<[typeof BAD_APP_MARKER, F, X]>;
type App<F, X> = [F] extends [Fun<infer K, infer C>] ? TypeFuncs<C, X>[K] : BadApp<F, X>;
// Example
const F_Foo = Symbol();
type F_Foo = Fun<typeof F_Foo, never>;
const F_Bar = Symbol();
type F_Bar = Fun<typeof F_Bar, never>;
interface TypeFuncs<C, X> {
[F_Foo]: Foo<X>;
[F_Bar]: Bar<X>;
}
class Foo<T, F = F_Foo> {
remake(): this {
return new (<any>this.constructor)();
}
recast(): App<F, T[]> {
return this as any as App<F, T[]>;
}
}
class Bar<T, F = F_Bar> extends Foo<T, F> { }
let b = new Bar<number>();
let b2 = b.remake();
console.log(b2.constructor.name); // Bar
let b3 = b.recast(); // Bar<number[]>
Upvotes: 2