microsoft / microsoft/TypeScript

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

Offen
#63,378 2 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

Domain: check: Type Inference Possible Improvement
Vorherrschende Sprache
Go
Sterne
111k
Forks
14.3k
Ø Merge
2 T. 4 Std.
Gemergte PRs (30 T.)
132

Beschreibung

🔎 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: ...
     });

Beitragsleitfaden

Beitragsleitfaden öffnen

Erste Schritte

  1. Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
  3. Forke das Repository und arbeite in einem Branch.
  4. Öffne einen Pull Request, der die Issue-Nummer nennt.

Rechercherichtung

Beginnen Sie mit dem verlinkten Playground und dem reduzierten fooArgs/foo-Beispiel, variieren Sie die Reihenfolge der Objekteigenschaften und die Annotation des Callback-Parameters. Vergleichen Sie das Verhalten mit dem verwandten Issue #56297 und verfolgen Sie dabei, wie NoInfer-Eigenschaften inferiert werden. Als abgeschlossen gilt die Aufgabe, wenn das Beispiel T konsistent aus T-enthaltenden Eigenschaften vor NoInfer-Eigenschaften inferiert und das gemeldete reihenfolgeabhängige Verhalten behoben ist.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
typescript
Bereich
compilers
Issue-Typ
Bug
Schwierigkeit
4/5
Geschätzter Aufwand
3-5 Tage
Aktivitätsstatus
Ruhig
Klarheit
Größtenteils klar
Anfängerfreundlichkeit
42/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.