microsoft / microsoft/TypeScript

Refinement type inference quirk with implicitly typed `let x`

Ouverte
#56,097 5 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

Bug Domain: check: Control Flow Help Wanted
Langage dominant
Go
Étoiles
111k
Forks
14.4k
Merge moyen
1 j 19 h
PR mergées (30 j)
117

Description

🔎 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.

Guide de contribution

Ouvrir le guide de contribution

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Piste de recherche

Commencez par reproduire l’exemple de TypeScript Playground et comparez le comportement entre les versions signalées. Étudiez l’inférence et le rétrécissement des types fondés sur le flux de contrôle pour un let typé implicitement et assigné depuis MyType ; le travail est considéré comme terminé lorsque la branche else finale est rétrécie de manière cohérente ou produit le diagnostic convenu sans perturber le rétrécissement précédent.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
typescript
Domaine
compilers
Type d'issue
Bug
Difficulté
4/5
Temps estimé
3-5 jours
Activité
À l'abandon
Clarté
Clairement spécifiée
Accessibilité débutants
35/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.