microsoft / microsoft/TypeScript

Discriminated union containing optional properties and generic types is not narrowed

Offen
#55,036 5 Kommentare 1 Reaktion 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

Domain: check: Control Flow Possible Improvement
Vorherrschende Sprache
Go
Sterne
111k
Forks
14.4k
Ø Merge
1 T. 19 Std.
Gemergte PRs (30 T.)
117

Beschreibung

Bug Report

I would have expected doesNotNarrow (below) to also be able to narrow x.b to NonUndefined<B>.

🔎 Search Terms

generic, narrow, discriminated, union, optional

🕗 Version & Regression Information

This is the behavior in every version I tried, and I reviewed all the FAQ for entries.

⏯ Playground Link

Playground link with relevant code

💻 Code
 type NonUndefined<T> = T extends undefined ? never : T

type X<A, B> = { a: NonUndefined<A>, b?: never } | { a?: never, b: NonUndefined<B> }

function doesNarrow(x: X<number, number>) {
  if (x.a === undefined) {
    const y = x.b
      // ^? number
  } 
}

function doesNotNarrow<A extends number, B extends number>(x: X<A, B>) {
  if (x.a === undefined) {
    const y = x.b
      // ^? NonUndefined<B> | undefined
  } 
}
🙁 Actual behavior

x.b was not narrowed.

🙂 Expected behavior

I expected x.b to be narrowed because if x.a is undefined, then x must be the latter part of the discriminated union because x.a can only be undefined there. TypeScript seems to be able to work that out when the type parameters are constant/non-generic (see doesNarrow), but for some reason it's not able to work it out for the generic case (even though NonUndefined should make it feasible).

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

Beginne mit dem verlinkten TypeScript Playground und vergleiche die Eingrenzung in doesNarrow mit doesNotNarrow. Untersuche den Pfad der Eingrenzung generischer discriminated unions anhand des bereitgestellten Beispiels mit X, NonUndefined und einer optionalen Eigenschaft. Als erledigt gilt, dass x.b im generischen Fall auf NonUndefined eingegrenzt wird, ohne das Verhalten im nicht-generischen Fall zu verschlechtern.

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
Veraltet
Klarheit
Klar beschrieben
Anfängerfreundlichkeit
35/100

Neue Issues direkt in Ihr Postfach

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