microsoft / microsoft/TypeScript
TS Proposal : "Interface incorrectly extends interface" - sub-interface method overload OR override ?
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 : 2.6.2
The problem
Initial scenario
I encountered the issue yesterday days as I was trying to add some features to one of my interface inheritance chain. The context of this example is just imagined : It is longer than needed to demonstrate the issue, but I wanted a full example to clearly show it needs to be addressed.
So, let's imagine a testing app that should instrument devices : the following is a potential model of the situation :
interface Stream
{
}
interface InputStream
{
}
interface OutputStream
{
}
// interface inheraitance is a great feature
interface IOStream extends InputStream, OutputStream
{
}
interface InterfaceLike
{
}
interface DeviceInterfaceLike extends InterfaceLike
{
init();
}
interface InputDeviceInterfaceLike extends DeviceInterfaceLike
{
input(); // this should word just like the `touch` command
// like if there's and error with the device, it will trigger exception
input(stream: InputStream);
}
interface ScreenDeviceInterfaceLike extends InputDeviceInterfaceLike
{
input(stream: InputStream, coordinates: {x: number, y: number});
}
interface TouchScreenDeviceInterfaceLike extends InputDeviceInterfaceLike
{
input(stream: IOStream, coordinates: {x: number, y: number});
}
Expected behavior :
It should just overload that method in the sub-interfaces.
Actual behavior :
error TS2430: Interface 'ScreenDeviceInterfaceLike' incorrectly extends interface 'InputDeviceInterfaceLike'.
Types of property 'input' are incompatible.
Type '(stream: InputStream, coordinates: { x: number; y: number; }) => any' is not assignable to type '{ (): any; (stream: InputStream): any; }'.
core.ts(73,11): error TS2430: Interface 'TouchScreenDeviceInterfaceLike' incorrectly extends interface 'InputDeviceInterfaceLike'.
Types of property 'input' are incompatible.
Type '(stream: IOStream, coordinates: { x: number; y: number; }) => any' is not assignable to type '{ (): any; (stream: InputStream): any; }'.
18:38:26 - Compilation complete. Watching for file changes.
It requires me to fully copy paste all method signatures in each interface.
interface ScreenDeviceInterfaceLike extends InputDeviceInterfaceLike
{
input(); // this should word just like the `touch` command
// like if there's and error with the device, it will trigger exception
input(stream: InputStream);
input(stream: InputStream, coordinates: {x: number, y: number});
}
interface TouchScreenDeviceInterfaceLike extends InputDeviceInterfaceLike
{
input(); // this should word just like the `touch` command
// like if there's and error with the device, it will trigger exception
input(stream: InputStream);
input(stream: IOStream, coordinates: {x: number, y: number});
}
When you're can have up to (why not) 15 overloads distributed through inheritance chain... It becomes, (yes, you said it) bulky.
Now it is, that the compiler cannot yet figure out when to override the method signatures inherited from parents and when to overload them.
The Proposal
My first thought was to introduce a new keyword just like @ts-nocheck and like.
@override
interface InputDeviceInterfaceLike extends DeviceInterfaceLike
{
@override // to override all definitions from parents
init(istream: InputStream);
}
OR
interface InputDeviceInterfaceLike extends DeviceInterfaceLike
{
@override
{
init(); // to override only this (these) definitions : forget all previous definition but this (these)
}
init(istream: InputStream);
}
Then, the TouchScreenDeviceInterfaceLike interface would become :
interface TouchScreenDeviceInterfaceLike extends InputDeviceInterfaceLike
{
@override // it is now clear that the only way to instrument a touchscreen is to provide a `IOStream` and coordinates (`{x: number, y: number}`)
input(stream: IOStream, coordinates: {x: number, y: number});
}
Furthermore, @overload
While the previous @override is useful when the default behavior is oveloading, we can still define the default behavior to suppress all parent definition WHEN A METHOD IS REDEFINED in subinterface, except when @overload is used. i.e
interface InputDeviceInterfaceLike extends DeviceInterfaceLike
{
// to override all definitions from parents
init(istream: InputStream);
}
OR
interface InputDeviceInterfaceLike extends DeviceInterfaceLike
{
@overload // to overload signatures from parents
init(istream: InputStream);
}
And TouchScreenDeviceInterfaceLike interface can become :
interface TouchScreenDeviceInterfaceLike extends InputDeviceInterfaceLike
{
@overload // to overload signatures from parents
{
init(istream: InputStream); // except this signature... So that it remains only the empty parameter and the below
}
input(stream: IOStream, coordinates: {x: number, y: number});
}
By thinking rigorously, I think the first step would be allow inheriting type to overload methods by default.
= = = = = = UPDATE = = = = = =
I now think it worth to add that by no mean, all through an interface inheritance chain should a method be completely wiped off (deleted, removed)... Not even by @Override! As this may (will) break the core concept of OOP inheritance.
The mechanism is to ensure that only some methods mood (signatures) are handled (accepted) at a given inheritance node.
In other words, if @Override suppresses all signatures, at least one method signature MUST be required.
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
Không có tệp mã nguồn, bài kiểm thử hoặc điểm vào của trình biên dịch nào được nêu. Hãy bắt đầu bằng việc xem xét ngữ nghĩa được đề xuất cho tính kế thừa interface, overload và override; công việc được hoàn tất khi hành vi dự kiến đã được thống nhất và các thay đổi tương ứng của compiler cùng các bài kiểm thử đã được xác định.
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
- Tính năng
- Độ 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
- Cần làm rõ
- Mức phù hợp với người mới
- 25/100