#"variable used before being assigned" not caught

26 messages · Page 1 of 1 (latest)

charred needle
#

hello! i'm expecting an undefined variable to be caught by the compiler, but it isn't. here's the example:

rustic cobaltBOT
#
raincomplex#0

Preview:```ts
// we're not allowed to do this
/*
function badf() {
var x : number;
return x; // error: "x" used before being assigned
}
console.log(badf() + 42);
//*/

// but we're allowed to do this...
function f(): () => number { // add "| undefined" to "number" and it errors...

...```

charred needle
#

is this a bug, or am i missing something? very new to typescript

teal stone
#

!:9998 this is because of the limitation of narrowing not being tracked across function boundaries

rustic cobaltBOT
charred needle
#

i guess i'm confused about the strictNullChecks option -- it seems like that should imply that the type of "var x : number" is actually "number | undefined" unless it can be narrowed later in the function (for example, by assigning a number to x)

#

in the page on narrowing in the docs it talks about "observed type" versus "declared type". the behavior i'm seeing seems to imply that a variable's observed type (in this case, undefined) isn't always guaranteed to fit inside its declared type (here, number)

main scroll
#

You're allowed to do this:

function f() {
  var x: number;
  return () => x;
}
``` but not ```ts
function f() {
  var x: number;
  return x;
}
``` because in the first case you are not returning a value, but a function that returns that value
#

Hence why it doesn't complain about not being defined. Still it returns undefined, so undefined + 42 = NaN

hasty mason
#

Why not use something like this?

function badf(x :number){
    return x
}
console.log(badf(7) + 8)
charred needle
#

sometimes something like this pattern is used:

function makeThing() {
    const T = {};
    var stored;
    T.get = function() {
        return stored;
    };
    T.set = function(newvalue) {
        stored = newvalue;
    };
    return T;
}
#

i realize that a class might be an option here, and then strictPropertyInitialization would catch this problem

#

but that doesn't help me with an existing codebase

rigid raptor
#

What do you want?

charred needle
#

how is this narrowing? there's no conditional

#

i want to understand (:

#

(referring to the f() in my original example)

long tapir
#

I think this is just a case where the compiler can't really analyze to check if this pattern is being used safely.

#

It's the sort of pattern that's not safe, but occasionally useful so the compiler allows it.

#

👆 It doesn't look like @typescript-eslint even has a rule for this because a fairly niche issue

#

Best case we could create a rule that says "don't create let variables without an initialiser unless they have undefined in their type". But IDK if there's huge amounts of value in that.

#

Also relevant, it looks like the suggestion is to just turn on init-declarations which will force you to add = /* something */ to all your declarations which makes this a moot point.

charred needle
#

ah great, thank you!