Amitabh
Amitabh

Reputation: 61167

Why does typescript allow variable to be used before declaring it?

Typescript does not give a compiler error for the following code:

var b = a + 10; // Why no compilation error here

var a = 10;

alert(b.toString());

I would expect the first line to be an error as I have not declared or initialized var a till this time.

If I remove the second line I get the compiler error.

I know its valid in JavaScript but I would expect TypeScript to give me compilation error or warning.

Upvotes: 8

Views: 2859

Answers (2)

basarat
basarat

Reputation: 276299

Assuming you understand that your code is equivalent to:

var a, b
b = a + 10
a = 10
alert(b.toString())

Which in turn is equivalent to:

var a = undefined, b = undefined
b = a + 10
a = 10
alert(b.toString())

The reason why it should be allowed is because undefined is a valid value for a variable that you can assign and read.

There are various use cases where this functionality is valuable. E.g The module pattern used in typescript:

module x{
    export var foo; 
}

Generates javascript code that exploits this fact:

var x;
(function (x) {
    x.foo;
})(x || (x = {})); //x was never assigned but used in "x ||" part

This is left in TypeScript due to JavaScript backward compatibility (not to mention it is useful).

Here is a purely TypeScript usecase. Perhaps you want to pass undefined into a function call (this is valid typescript):

var a:number = undefined; // same as simply "var a" 
console.log(a);

It is just assumed that the TypeScript developer wants the power of the underlying JavaScript language.

This is not the case for languages where Reading before Assignment is invalid (e.g C#). In C# an unassigned variable has no meaning. In JavaScript it does. So TypeScript has to allow this.

Upvotes: 6

null
null

Reputation: 11849

Because hoisting behavior can be confusing. Your code actually means.

var a, b

b = a + 10
a = 10

alert(b.toString())

There are valid reasons to allow hoisting, but they don't involve var, but function - you can call function declared later.

alert(identity(i))

function identity(i) {
    return i
}

In this case, alert uses result of function declared later. Thanks to hoisting behavior, it works.

While I agree this case should have an warning (not error, TypeScript wants to be compatible with JavaScript), it doesn't appear that TypeScript currently notices that. Every variable in TypeScript has a type that CANNOT change during lifetime of variable, and in your case, a is number type (it isn't aware that you use it before assignment, because var sets type implicitly). TypeScript assumes it's a number, even if it's not, because of its declaration.

You may want to report this as a bug in TypeScript.

Upvotes: 10

Related Questions