解决失去对类型约束的支持的问题

Dav*_*ret 7 typescript

这是我在旧版本的TypeScript中所做的事情,我在C#中使用此方法,但它在最新的1.0版本的TypeScript中不起作用.

这是过去的成效:

class Base<T extends Base<T>> {
    public children : Array<T>;

    doAction() {
        this.children[0].promise(); // used to work
    }

    promise() : T {
        return this; // used to work
    }
}

class Child extends Base<Child> {
    public myString: string;
}

new Child().promise().myString; // used to work
Run Code Online (Sandbox Code Playgroud)

一切都过去和谐共处.

现在在TypeScript 1.0中我在Base<T extends Base<T>>定义上得到了这个错误:

类型参数的约束不能引用同一类型参数列表中的任何类型参数.

如何修复此示例类,而不需要在类之外进行任何转换或将任何内容转换为"any"?也许这种模式应该改变?

Fen*_*ton 10

您不再允许在此使用T:

class Base<T extends Base<T>>
--------------------------^
Run Code Online (Sandbox Code Playgroud)

您必须使您的类非泛型或使用:

class Base<T extends Base<any>>
Run Code Online (Sandbox Code Playgroud)

给出的原因是使编译器更简单:

在我们不断努力简化语言的过程中,我们正在简化通用约束所需的内容.

在类型检查,错误报告和设计复杂性方面增加的额外开销没有增加足够的额外表现力,使其值得1.0.我们可能会在未来的TypeScript版本中重新考虑这一点.

- 打破变化维基


Dav*_*ret 6

我接受了史蒂夫的答案,因为他建议使用Base<T extends Base<any>>,但我想保留代码更改的副本,以解决Stack Overflow上的问题:

class Base<T extends Base<any>> { // 1. Set as any
    children: Array<T>;

    doAction() {
        this.children[0].promise();
    }

    promise(): T {
        return <any> this; // 2. cast to any
    }
}

class Child extends Base<Child> {
    public myString: string;
}

new Child().promise().myString;
Run Code Online (Sandbox Code Playgroud)

这需要一个强制转换,但它并不是那么糟糕,因为它只在基类中.此更改不会影响使用Child或Base类的任何内容,因此总体而言,它是一个非常理想的替代方案.


更新:在TS 1.7+中,这可以使用多态来完成:

class Base {
    children: Array<this>;

    doAction() {
        this.children[0].promise();
    }

    promise(): this {
        return this;
    }
}

class Child extends Base {
    public myString: string;
}

new Child().promise().myString;
Run Code Online (Sandbox Code Playgroud)