microsoft / microsoft/TypeScript
Generic type unnarrowed by `switch...case`
Nadie ha tomado este issue todavía.
- Lenguaje dominante
- Go
- Estrellas
- 111k
- Forks
- 14.3k
- Merge medio
- 2 d 4 h
- PR fusionados (30 d)
- 132
Descripción
Bug Report
🔎 Search Terms
- narrowing of generic types
- exhaustive switch case
🕗 Version & Regression Information
Theoretically this should be fixed by:
- https://github.com/microsoft/TypeScript/issues/13995
- https://github.com/microsoft/TypeScript/pull/43183
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.
Guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Línea de trabajo
Comienza con la reproducción vinculada en TypeScript Playground y confirma el error reportado en el retorno genérico dentro del case del switch. Sigue el estrechamiento del tipo genérico del compilador para las cláusulas switch y añade cobertura de regresión que demuestre que el case estrecha TagName y que el código esperado pasa la comprobación de tipos sin una aserción.
Escrito por el modelo de indexación a partir del texto del issue.
Evaluación
- Stack tecnológico
- typescript
- Área
- compilers
- Tipo de issue
- Error
- Dificultad
- 4/5
- Tiempo estimado
- 3-5 días
- Estado de actividad
- Estancado
- Claridad
- Bien especificado
- Aptitud para principiantes
- 38/100