microsoft / microsoft/TypeScript
Need a dummy overload to improve inference
Chưa có ai nhận issue này.
- Ngôn ngữ chính
- Go
- Star
- 111k
- Fork
- 14.3k
- Merge trung bình
- 2 ngày 4 giờ
- Pull request đã merge (30 ngày)
- 132
Mô tả
TypeScript Version: 3.x, 4.0.0-beta, nightly
Search Terms: dummy fake overload infer
Code
class FieldEvent<T extends Field> {
constructor(readonly field: T, readonly message: string) { }
}
class Field {
listen<T extends FieldEvent<Field>>(type: new (...args: any[]) => T, listener: (event: T) => void): void { }
}
class BeforeSetEvent<T extends number | string> extends FieldEvent<ValueField<T>> {
constructor(field: ValueField<T>, public newValue: T) { super(field, ""); }
}
class AfterSetEvent<T extends number | string> extends FieldEvent<ValueField<T>> {
constructor(field: ValueField<T>, readonly oldValue: T) { super(field, ""); }
}
class ValueField<T extends number | string> extends Field {
constructor(public value: T) { super(); }
// listen<U extends FieldEvent<Field>>(type: new (arg: this) => U, listener: (event: U) => void): void;
// listen<U extends FieldEvent<Field>>(type: new (...args: any[]) => U, listener: (event: U) => void): void;
listen<U extends FieldEvent<Field>>(type: new (...args: any[]) => U, listener: (event: U) => void): void {
super.listen(type, listener);
}
}
let field = new ValueField(0);
field.listen(FieldEvent, (event) => event.field); // event: FieldEvent<any>
field.listen(BeforeSetEvent, (event) => { event.field; event.newValue; }); // event: BeforeSetEvent<any>
field.listen(AfterSetEvent, (event) => { event.field; event.oldValue; }); // event: AfterSetEvent<any>
Expected behavior:
event to be better inferred than any.
Actual behavior:
event inferred as any.
But if we uncomment the 2 overloads, then event is correctly inferred:
field.listen(FieldEvent, (event) => event.field); // event: FieldEvent<ValueField<0>>
field.listen(BeforeSetEvent, (event) => { event.field; event.newValue; }); // event: BeforeSetEvent<0>
field.listen(AfterSetEvent, (event) => { event.field; event.oldValue; }); // event: AfterSetEvent<0>
What's surprising (so the reason I consider it as a bug):
- The 1st overload doesn't match any signature.
- But it influences the way the other overload is inferred.
Note that if we replace (arg: this) by () or another type, then:
field.listen(FieldEvent, (event) => event.field); // event: FieldEvent<Field>
field.listen(BeforeSetEvent, (event) => { event.field; event.newValue; }); // event: BeforeSetEvent<string | number>
field.listen(AfterSetEvent, (event) => { event.field; event.oldValue; }); // event: AfterSetEvent<string | number>
Playground Link: Playground Link
Related Issues: I first posted #36226 but was not able to solve my issue, until I found the (arg: this) trick.
Hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Hướng nghiên cứu
Bắt đầu bằng cách tái hiện ví dụ trong TypeScript Playground được liên kết, so sánh việc suy luận khi có và không có hai overload. Theo dõi hành vi suy luận generic và phân giải overload của compiler đối với các lệnh gọi listen; hoàn thành khi các callback suy luận ra FieldEvent, BeforeSetEvent và AfterSetEvent cùng các kiểu cụ thể tương ứng mà không cần các overload giả.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Đánh giá
- Công nghệ
- typescript
- Lĩnh vực
- compilers
- Loại issue
- Lỗi
- Độ khó
- 5/5
- Thời gian dự kiến
- Hơn một tuần
- Mức độ hoạt động
- Đình trệ
- Độ rõ ràng
- Khá rõ ràng
- Mức phù hợp với người mới
- 25/100