microsoft / microsoft/TypeScript

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

Aperta
#35,154 3 commenti 1 reazione 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

Needs Investigation
Lingua principale
Go
Stelle
111k
Fork
14.3k
Merge medio
2g 4h
PR unite (30g)
132

Descrizione

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

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Direzione di ricerca

Inizia riproducendo gli errori alle righe 29 e 33 di test.ts nell’esempio minimo riproducibile collegato, quindi esamina le definizioni correlate in index.ts. Conferma il comportamento previsto verificando che un listener con un parametro venga accettato per una tupla con due parametri, mantenendo al contempo la sicurezza dei tipi.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
typescript
Ambito
compilers
Tipo di issue
Bug
Difficoltà
4/5
Tempo stimato
3-5 giorni
Stato di attività
Ferma
Chiarezza
Abbastanza chiara
Idoneità per principianti
35/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.