microsoft / microsoft/TypeScript

Need a dummy overload to improve inference

Aperta
#39,850 1 commento 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

Bug Domain: check: Type Inference
Lingua principale
Go
Stelle
111k
Fork
14.3k
Merge medio
2g 4h
PR unite (30g)
132

Descrizione

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.

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 l’esempio nel TypeScript Playground collegato, confrontando l’inferenza con e senza i due overload. Traccia il comportamento dell’inferenza generica e della risoluzione degli overload del compilatore per le chiamate a listen; il lavoro è completo quando i callback inferiscono FieldEvent, BeforeSetEvent e AfterSetEvent con i tipi concreti pertinenti, senza gli overload fittizi.

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

Valutazione

Stack tecnologico
typescript
Ambito
compilers
Tipo di issue
Bug
Difficoltà
5/5
Tempo stimato
Più di una settimana
Stato di attività
Ferma
Chiarezza
Abbastanza chiara
Idoneità per principianti
25/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.