打字稿自参考作为类构造函数

时间:2018-09-11 00:18:43

标签: typescript

class Foo<T> {
    remake(){
        return new Foo<T>;
    }
    recast(){
        return this as any as Foo<Array<T>>
    }
}

我要设置Foo类的Child类。 子类应该在remakerecast上引用自己

另外,如果还有其他语法可以更改实例的泛型,对我也将很好。

1 个答案:

答案 0 :(得分:2)

您可以使用remake实现this.constructor并使用this类型键入它。 recast需要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[]>