microsoft / microsoft/TypeScript

Generic type unnarrowed by `switch...case`

Offen
#43,873 10 Kommentare 5 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

In Discussion Suggestion
Vorherrschende Sprache
Go
Sterne
111k
Forks
14.3k
Ø Merge
2 T. 4 Std.
Gemergte PRs (30 T.)
132

Beschreibung

Bug Report

🔎 Search Terms
  • narrowing of generic types
  • exhaustive switch case
🕗 Version & Regression Information

Theoretically this should be fixed by:

Similar issue:

I'm trying against the latest beta: 4.3.0-pr-43183-11 / 15fae38b39a370f1f597606e552dd40998a1ac49.

⏯ Playground Link

Playground link with relevant code

💻 Code
interface TopLevelElementMap {
	"a": HTMLElement;
	"b": HTMLElement;
}

interface ElementAttributes {}

interface ElementAttributesMap {
	"a": ElementAttributes;
	"b": ElementAttributes;
}

class Element<TagName extends keyof TopLevelElementMap> {
	protected attributes: ElementAttributesMap[TagName] = {};

	public constructor(type: TagName) {}
}

const ElementTagNameMap = {
	"a": function(): Element<"a"> {
		return new Element("a");
	},
	"b": function(): Element<"b"> {
		return new Element("b");
	}
};

function createPrimitive<TagName extends keyof typeof ElementTagNameMap>(tagName: TagName) {
	switch (tagName) {
		case "a":
			return function(): Element<TagName> {
				//
				// [?] Shouldn't `tagName` get narrowed to just "a"?
				//
				return ElementTagNameMap[tagName]();
			};

		case "b":

		default:
			throw new Error("Unrecognized element `" + tagName + "`.");
	}
}

const a = createPrimitive("a");
const b = createPrimitive("b");

As a workaround I can assert as Element<TagName> on the inner-most return statement to silence the error.

🙁 Actual behavior
Type 'Element<"a"> | Element<"b">' is not assignable to type 'Element<TagName>'.
  Type 'Element<"a">' is not assignable to type 'Element<TagName>'.
    Type '"a"' is not assignable to type 'TagName'.
      '"a"' is assignable to the constraint of type 'TagName', but 'TagName' could be instantiated with a different subtype of constraint '"a" | "b"'. (2322)
🙂 Expected behavior

TagName should be narrowed to one of the possible values dictated by the case clause.

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 der verknüpften TypeScript Playground-Reproduktion und bestätige den gemeldeten Fehler bei der generischen Rückgabe innerhalb des switch-Falls. Verfolge die Eingrenzung des generischen Typs des Compilers für switch-Klauseln und füge eine Regressionstestabdeckung hinzu, die zeigt, dass der case TagName eingrenzt und der erwartete Code ohne eine Assertion typgeprüft wird.

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
38/100

Neue Issues direkt in Ihr Postfach

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