question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Uninitialized variables work around strictNullChecks (follow-up to #13884)

See original GitHub issue

This is a follow-up to #13884, where @RyanCavanaugh asked me to open a new issue.

tl;dr: Now that there is strictPropertyInitialization, it seems that there should also be an analogous strictLocalInitialization.

TypeScript Version: 2.8

Search Terms: uninitialized local variables, strict local variables, strictLocalInitialization, strictPropertyInitialization, strictNullChecks

Code

let x: number[];  // No definite assignment assertion.
// x.toString();  // Compile-time error. Yay!
function foo() {
  x.toString();  // No compile-time error, but throws an exception. :(
}
foo();

Slightly more interesting:

function fooFactory() {
  let x: number;  // Inaccessible from anywhere but `foo()` below.
  return {
    foo() {
      // Guaranteed to throw an exception since `x` can't change.
      return x.toString();
    }
  };
}

Expected behavior:

If an imaginary --strictLocalInitialization flag is enabled, these snippets should each result in a compile-time error.

To resolve such an error, one would need to:

A) Initialize the variable in a way that the TypeScript compiler understands (e.g. immediately, or before referencing it in a closure).

-OR-

B) Use a definite assignment assertion. It seems that this issue would come up naturally when discussing definite assignment assertions for local variables. Instead, the example provided in the blog feels contrived and wouldn’t be a problem if it weren’t for control flow analysis limitations.

-OR-

C) Explicitly mark the variable as potentially undefined, forcing callers to acknowledge that it may not be set.

Actual behavior:

No compile-time errors, but obvious run-time errors.

Playground Link:

Link (enable strictNullChecks)

Related Issues:

#13884, #9998


Understandably, this may not be as simple as strictPropertyInitialization, but I feel it needs a discussion none the less. The fooFactory() example above is analogous to this Foo class, which correctly emits a compile-time error under strictPropertyInitialization:

class Foo {
  private x: number; // Compile-time error!
  foo() {
    // `x` isn't initialized! But it's OK, compile-time error above.
    return this.x.toString();
  }
}

Issue Analytics

  • State:open
  • Created 5 years ago
  • Reactions:15
  • Comments:18 (6 by maintainers)

github_iconTop GitHub Comments

9reactions
RyanCavanaughcommented, Apr 17, 2018

Accepting PRs. The rule here is that any variable that is read but never written to is an error if the variable doesn’t have undefined in its type.

Implementation note - this needs to be done not as a separate pass. Re-use the existing logic that finds unused locals and refactor it to provide read/write information instead of just read.

No new flag since this should only ever catch true errors – this will be the default behavior for all strictNullChecks compilations.

2reactions
jfirebaughcommented, Jan 27, 2022

I would actually rather have the simpler --strictLocalInitialization option that flags any uninitialized declaration which does not have undefined as an allowable type, than a control-flow based feature that allows a subset of such constructs where assignment before use can be proven. And even more so if the control-flow based feature is going to permit some constructs where there is an assignment but it can’t be proven to occur before use – I think the majority of bugs people hope to catch with strictness like this would fall in this category.

Read more comments on GitHub >

github_iconTop Results From Across the Web

strictNullChecks - TSConfig Option - TypeScript
When strictNullChecks is true , null and undefined have their own distinct types and you'll get a type error if you try to...
Read more >
TypeScript "strictNullChecks" - a migration guide
This works because any code that is correct with strictNullChecks ... You can get around this by saving the value in a local...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found