microsoft / microsoft/TypeScript

Create flag strictVariableInitialization

Ouverte
#60,064 5 commentaires 2 réactions 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

Awaiting More Feedback Suggestion
Langage dominant
Go
Étoiles
111k
Forks
14.4k
Merge moyen
1 j 19 h
PR mergées (30 j)
117

Description

🔍 Search Terms

uninitialized variable, undefined, closure, strict property initialization,

✅ Viability Checklist
⭐ Suggestion

I would like to see a check that ensures that no variable whose type is not permitted to be undefined may remain uninitialized at the end of its scope.

📃 Motivating Example

TypeScript allows unsafety that can and does catch users by surprise when using variables in a closure. Normally, TS won't let you access an uninitialized variable:

function doSomething() {
   let foo: string;
   foo.toLowerCase(); // TS ERROR: Variable 'foo' is used before being assigned 
}

However, TypeScript optimistically assumes that variables are initialized when used in closures.

let foo: string;

function printFoo() {
    console.log(foo.toLowerCase());
}

printFoo(); // Uncaught TypeError: Cannot read properties of undefined (reading 'toLowerCase')

That's for good reason, but sometimes, as in the above case, this is provably unsafe, since foo is guaranteed not to be initialized.

The new flag "strictVariableInitialization" ensures that a variable must be initialized by the end of all reachable codepaths in its scope.

let foo: string; // (proposed) TS ERROR: `foo` is not initialized in all reachable codepaths 

function printFoo() {
    console.log(foo.toLowerCase());
}

printFoo()

Of course, variables whose type includes undefined are still permitted to be uninitialized.

let foo: string | undefined;

function printFoo() {
    console.log(foo?.toLowerCase());
}

printFoo();

This check is highly analogous to strictPropertyInitialization for classes.

💻 Use Cases

See https://github.com/typescript-eslint/typescript-eslint/issues/9565 for a somewhat-wordier proposal in typescript-eslint, and https://github.com/typescript-eslint/typescript-eslint/issues/4513 and https://github.com/typescript-eslint/typescript-eslint/issues/10055#issuecomment-2374797860 for cases where this has caused confusion in the wild.

In short, people who have written code that does check for initialization of non-nullable variables become confused by the linter informing them that the check is unnecessary according to the types, even though they can see that it is necessary at runtime:

let foo: Something

function useFoo() {
   if (foo != null) { // linter flags this condition as unnecessary since foo cannot be nullish
      foo.bar();
   }
}

The code should be rewritten as

let foo: Something | undefined

function useFoo() {
   if (foo != null) {
      foo.bar();
   }
}

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 examiner le comportement proposé de strictVariableInitialization et les exemples de Closure qui le motivent, puis comparez-le à strictPropertyInitialization. Définissez comment doivent être traités les chemins de code accessibles et les types incluant undefined ; le travail est terminé lorsque la proposition dispose d’une conception arrêtée et d’un comportement correspondant du compilateur sans modifier le JavaScript émis.

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

Évaluation

Stack technique
javascript, typescript
Domaine
compilers
Type d'issue
Fonctionnalité
Difficulté
5/5
Temps estimé
Plus d'une semaine
Activité
À l'abandon
Clarté
Clairement spécifiée
Accessibilité débutants
30/100

Recevez les nouvelles issues par e-mail

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