Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect error of use of unassigned variable #13811

Closed
NN--- opened this issue Feb 1, 2017 · 9 comments
Closed

Incorrect error of use of unassigned variable #13811

NN--- opened this issue Feb 1, 2017 · 9 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@NN---
Copy link

NN--- commented Feb 1, 2017

TypeScript Version: 2.1.5
strictNullChecks: true

Code

let a: {};

if (!a) { // <!-- Error
   ....
}

Expected behavior:
Code compiles fine.

Actual behavior:
Use of unassigned variable.

@devdoomari
Copy link

devdoomari commented Feb 1, 2017

a has the type of {}, and has no value assigned.
i.e. your code is equivalent to:

let a: {} = undefined;

so what you wanted:

let a = {}; // not let a: {}

@NN---
Copy link
Author

NN--- commented Feb 1, 2017

@devdoomari It is not what I want.
I want to have it undefined and assign it only if it is undefined.

Full code:

let a: {};

for (const x of y) {
  if(x.q) {
    a =x.q;
    break;
  }
}

// Assign default value if couldn't assign before
if (!a) {
  a = {};
}

@ahejlsberg
Copy link
Member

The control flow checker (in strict null checks mode) assures that you'll never accidentally observe undefined in a variable unless the type of the variable allows it. Your program logic is constructed such that undefined is actually a permitted value (at least in parts of the logic), so I'd recommend including undefined in the type of a:

let a: {} | undefined;

The problem with your suggestion is that we'd no longer catch this:

let a: string;
// Intended to have assignment here, but forgot
if (!a) {
    // Think I have an empty string, but I have undefined
}

@ahejlsberg ahejlsberg added the Working as Intended The behavior described is the intended behavior; this is not a bug label Feb 1, 2017
@NN---
Copy link
Author

NN--- commented Feb 1, 2017

@ahejlsberg What about this case ?

I would expect it compiling fine since I am checking against undefined.

let a: number;
if (typeof a !== "undefined") {
	a = 1;
}

@ahejlsberg
Copy link
Member

ahejlsberg commented Feb 1, 2017

I think the same argument holds. If the declared type of a variable does not include undefined, the control flow analyzer takes it to mean you never want to observe the variable in an uninitialized state (in any way). I think the consistency of that is important, particularly since you can just add undefined to the type in cases where you want to do those types of checks.

@NN---
Copy link
Author

NN--- commented Feb 2, 2017

That's what I ended with.
Thanks.

@NN---
Copy link
Author

NN--- commented Feb 6, 2017

@ahejlsberg
I feel that there is a need for language construct or helper which tests for null or undefined.
Currently I use "if(a) {..}" but if type of 'a' changes to string or number, this test will not be correct.

I feel more safe using this helper now.

function isNullOrUndefined<T>(obj: T | null | undefined): obj is null | undefined {
	return typeof obj === "undefined" || obj === null;
}

if (!isNullOrUndefined(a)) { ... }

But prefer to have something in the language like:

iff (a) { ... }

@ahejlsberg
Copy link
Member

Adding entirely new statements beyond what JavaScript has is definitely out of scope for TypeScript. To check if a value is null or undefined in JavaScript, just use x == null. See more discussion here.

@NN---
Copy link
Author

NN--- commented Feb 6, 2017

Thanks.
Didn't think about this pattern

@mhegazy mhegazy closed this as completed Apr 19, 2017
@microsoft microsoft locked and limited conversation to collaborators Jun 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

4 participants