microsoft / microsoft/TypeScript

Rest parameter in callback function using generic tuple types: Forces definition of all parameters

Đang mở
#35,154 3 bình luận 1 reaction 0 người được giao Xem trên GitHub

Chưa có ai nhận issue này.

Needs Investigation
Ngôn ngữ chính
Go
Star
111k
Fork
14.4k
Merge trung bình
1 ngày 19 giờ
Pull request đã merge (30 ngày)
117

Mô tả

TypeScript Version: 3.8.0-dev.20191116

Search Terms:
rest parameter, spread, tuple type, generics, conditional types

Code
https://github.com/BTOdell/typescript-tuple-rest-spread-bug

This issue was discovered when implementing a type-safe event emitter class. I've produced a minimum reproducible example at the GitHub link above as well as in a Playground link below.

  • index.ts defines an unimplemented EventEmitter that includes 4 functions which should be equivalent (except for the eventName parameter).
  • test.ts consumes the EventEmitter class and calls the various functions to test type-safety.

An Events interface is used to define the supported events by mapping the event name to a tuple type for the parameters of the event listener.
This interface is passed through a generic parameter E in the Test class and then passed through a generic parameter E in the EventEmitter class.

Expected behavior:
A listener function should be able to define 1 parameter even if the caller might pass 2 parameters. The listener will then only have access to the first parameter passed. This is how JavaScript normally behaves.

Actual behavior:
The unexpected behavior occurs on lines 29 and 33 (in test.ts) and only occurs when the Events interface type has to pass through 2 generic class parameters.
If line 14 is uncommented, and line 13 is commented then all unexpected behavior is resolved.

Error:(29, 47) TS2345: Argument of type '(b: boolean) => void' is not assignable to parameter of type '(...args: Args<E["multiArray"]>) => any'.
  Types of parameters 'b' and 'args' are incompatible.
    Type 'Args<E["multiArray"]>' is not assignable to type '[boolean]'.
      Type 'E["multiArray"] | [E["multiArray"]]' is not assignable to type '[boolean]'.
        Type 'any[] & E["multiArray"]' is not assignable to type '[boolean]'.
          Types of property 'length' are incompatible.
            Type '2' is not assignable to type '1'.
              Type '[boolean, boolean]' is not assignable to type '[boolean]'.
                Types of property 'length' are incompatible.
                  Type '2' is not assignable to type '1'.

It seems like the tuple types [boolean, boolean] and [boolean] are not being treated like they're being spread as a rest parameter in a function. Could the context information be getting lost due to jumping through multiple generic parameters?

Playground Link:
Playground link

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. 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.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. 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 các lỗi ở dòng 29 và 33 của test.ts trong ví dụ tối thiểu có thể tái hiện được được liên kết, sau đó kiểm tra các định nghĩa liên quan trong index.ts. Xác nhận hành vi mong đợi bằng cách kiểm tra rằng một listener có một tham số được chấp nhận cho một tuple có hai tham số, đồng thời tính an toàn kiểu vẫn được duy trì.

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ó
4/5
Thời gian dự kiến
3-5 ngày
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
35/100

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.