microsoft / microsoft/TypeScript

Refinement type inference quirk with implicitly typed `let x`

Abierto
#56,097 5 comentarios 0 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

Bug Domain: check: Control Flow Help Wanted
Lenguaje dominante
Go
Estrellas
111k
Forks
14.4k
Merge medio
1 d 19 h
PR fusionados (30 d)
117

Descripción

🔎 Search Terms

refinement narrow let any

🕗 Version & Regression Information
  • This changed between versions 3.9.7 and 4.0.5; the behavior is present in every version from 4.0.5 to 5.3 nightly; I skimmed the whole FAQ document and didn't find anything relevant
⏯ Playground Link

https://www.typescriptlang.org/play?ts=5.3.0-dev.20231013#code/C4TwDgpgBAsiAq5oF4oG8qkgLigcgEE8oBfKAH3UyVzwCFiSBuAKBYDMBXAOwGNgAlgHtuUdgAoAhgCcA5rjiJIASnQsoGqABsIwKAA9Wmg1FQzZRzQPZRx+gHRYUyVITyq06zWQhaAztDWtg5Opi74DB5eGj7+0J7Gxjp6APq43BAAbhDSpgaWMSwkLEA

💻 Code
type MyType = { type: 'A' } | { type: 'B' };

function f(arg: MyType) {
    let x;
    x = arg;
    if (x.type === 'A') {
    } else if (x.type === 'B') {
    } else {
        let _: never = x;
    }
}
🙁 Actual behavior
error TS2322: Type '{ type: "B"; }' is not assignable to type 'never'.

9         let _: never = x;
              ~

This is wrong for two reasons:

  • In the world of perfect type inference, x should be narrowed to never at this point
  • Even acknowledging that there could be some practical limitations, the behavior is not consistent.
    image
    First conditional successfully eliminates the "A" variant:
    image
    But second conditional fails to eliminate the "B" variant:
    image
🙂 Expected behavior

Ideally, this shouldn't be an error at all.

However, given that control-flow-based type inference has its limitations, perhaps some kind of spurious error is inevitable. In that case, it probably should be more like Type 'MyType' is not assignable to type 'never' rather than Type '{ type: "B" }' is not assignable to type 'never'.

Additional information about the issue

Practical impact of this issue is small. There is an easy workaround of adding an explicit type annotation (let x: MyType;).

However, this asymmetry, that the last conditional fails at narrowing when exactly the same conditional before that succeeds, bothers me. I'm reporting this because it could be a symptom of a more general implementation defect.

Guía de contribución

Abrir la guía de contribución

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Línea de trabajo

Comienza reproduciendo el ejemplo de TypeScript Playground y compara el comportamiento entre las versiones reportadas. Investiga la inferencia y el estrechamiento de tipos basados en el flujo de control para un let con tipo implícito asignado desde MyType; se considera terminado cuando la rama else final se estrecha de forma coherente o produce el diagnóstico acordado sin romper el estrechamiento anterior.

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

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.