microsoft / microsoft/TypeScript

Object properties are inferred in the wrong order: should infer properties with `NoInfer<T>` AFTER properties with `T`

Aperta
#63,378 2 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

Domain: check: Type Inference Possible Improvement
Lingua principale
Go
Stelle
111k
Fork
14.3k
Merge medio
1g 19h
PR unite (30g)
117

Descrizione

🔎 Search Terms

NoInfer
brittle inference
object properties

Related issues:

🕗 Version & Regression Information

Tested in 6.0.2 and nightly.

⏯ Playground Link

Playground Link

💻 Code

See playground for the full example.

type fooArgs<T> = {
     a: (_: A) => X<T>,
     // note: NoInfer<Y<T>> better than Y<NoInfer<T>>, doesn't change this issue though
     b: NoInfer<Y<T>>
}

function foo<T>(args: fooArgs<T>) {}

foo({
     a: (_) => ...,
     b: ... // inference of the value given to b is VERY brittle.
});
🙁 Actual behavior

Sometimes, b is inferred before a.

Then, as a is the one used to infer the generic parameter T, the value given to b doesn't have the correct type (because inferred before a).
This is likely due to the fact that the value given to a is a callback with a parameter we didn't specify the type ((_) => ...). Therefore, TS has first to look at fooArgs<T> to infer the callback's parameter type (i.e. the type of _).

Due to that, b is sometime inferred before a has been properly inferred. This behavior depends on the order of the object properties (cf related issue). It is also influenced by other defined properties, and how they are defined. Making the inference quite chaotic.

🙂 Expected behavior

TS should infer NoInfer<T> properties AFTER T properties, in order to prevent such issues.

Additional information about the issue

The fact that the order of the inference changes is quite troublesome, hiding the issue in some cases.

Could be nice to have a kind of tool/flag to detect such kind of potential issues, and to help debugging.

EDIT: A possible workaround:

type fooArgs<T> = {
     b: Y<T>
}

function foo<T>(a: (_: A) => X<T>, args: NoInfer<fooArgs<T>>) {}

foo(
     a: (_) => ..., {
         b: ...
     });

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 con il Playground collegato e l’esempio ridotto fooArgs/foo, variando l’ordine delle proprietà dell’oggetto e l’annotazione del parametro del callback. Confronta il comportamento con l’issue correlata #56297 mentre tracci come vengono inferite le proprietà NoInfer. Il lavoro è completato quando l’esempio inferisce coerentemente T dalle proprietà che contengono T prima delle proprietà NoInfer e il comportamento dipendente dall’ordine segnalato è stato risolto.

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à
Tranquilla
Chiarezza
Abbastanza chiara
Idoneità per principianti
42/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.