2014-04-11 14 views
7

Đây là điều tôi đã làm trong các phiên bản cũ của TypeScript và tôi sử dụng phương pháp này trong C#, nhưng nó không hoạt động trong phiên bản 1.0 mới nhất của TypeScript.Làm việc xung quanh mất hỗ trợ cho ràng buộc loại là tự

Đây là những gì làm việc trong quá khứ:

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 

Tất cả mọi thứ đã từng làm việc trong sự hòa hợp.

Bây giờ trong nguyên cảo 1.0 Tôi nhận được lỗi này vào định nghĩa Base<T extends Base<T>>:

Hạn chế của một số loại không có thể tham khảo bất kỳ tham số kiểu so với cùng danh sách tham số kiểu.

Làm cách nào để sửa lớp mẫu này hoạt động mà không yêu cầu bất kỳ phôi nào ngoài lớp học hoặc truyền bất kỳ thứ gì vào "bất kỳ" nào? Có lẽ mô hình này nên được thay đổi?

+0

Lưu ý rằng mô hình này sẽ không còn cần thiết khi đánh máy hỗ trợ một [đa hình này] (https: // github. com/Microsoft/TypeScript/pull/4910) trong TS1.7. –

Trả lời

10

Bạn đang không còn được phép sử dụng T đây:

class Base<T extends Base<T>> 
--------------------------^ 

Bạn có thể cần phải thực hiện lớp học của bạn không chung chung hoặc sử dụng:

class Base<T extends Base<any>> 

Lý do đưa ra cho việc này đã làm cho các trình biên dịch đơn giản hơn:

Trong nỗ lực liên tục của chúng tôi để đơn giản hóa ngôn ngữ, chúng tôi đang đơn giản hóa những gì chung c onstraints có thể đòi hỏi.

Chi phí bổ sung về kiểm tra loại, báo cáo lỗi và độ phức tạp của thiết kế không thêm đủ tính biểu cảm bổ sung để làm cho nó đáng giá cho 1.0. Chúng tôi có thể xem lại điều này trong các phiên bản tương lai của TypeScript.

- Breaking Changes Wiki

+0

Cảm ơn. Nó không phải là tốt đẹp, nhưng tôi đã có thể làm cho mọi thứ hoạt động bằng cách làm 'Base >'. Tôi đã phải làm một dàn diễn viên cho bất kỳ, nhưng đó không phải là một việc lớn trong lớp cơ sở: http://goo.gl/8JSLxq –

6

tôi chấp nhận câu trả lời của Steve vì ông đề nghị sử dụng Base<T extends Base<any>>, nhưng tôi muốn giữ một bản sao của sự thay đổi mã mà khắc phục vấn đề trên 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; 

Điều này đòi hỏi một diễn viên cho bất kỳ, nhưng nó không phải là xấu vì nó chỉ trong lớp cơ sở. Thay đổi này không ảnh hưởng đến bất cứ điều gì bằng cách sử dụng các lớp học Trẻ em hoặc Cơ sở, vì vậy tổng thể nó là một lựa chọn rất lý tưởng.


Cập nhật: Trong TS 1.7+ này có thể được thực hiện bằng một polymorphic this:

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; 
+0

dude tuyệt vời, cảm ơn –

0

promise() : T { return this; } nó là giả định rất yếu có thể dễ dàng bị phá vỡ, vì downcasting định nghĩa trong một lớp cơ sở chỉ không thể làm việc cho bất kỳ tiểu nhóm nào

Ví dụ trong trường hợp của bạn, nếu bất kỳ ai xác định class SuperChild extends Child {} thì promise() của SuperChild sẽ cung cấp cho bạn Child thay vì SuperChild.

Bên cạnh đó đây là cách bạn có thể làm cho nó làm việc theo cách nó được sử dụng để:

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

    constructor(
     private toSelf:() => T, 
     private toBase: (something: T) => Base<T> 
    ) { 
    } 


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

    promise() : T { 
     return this.toSelf(); // 
    } 
} 

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

function toThis() { return this; } 

new Child(toThis, x => x).promise().myString; // used to work 
Các vấn đề liên quan