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

Object is incorrectly typed as 'possibly null' inside closure #12113

Closed
tjhance opened this issue Nov 9, 2016 · 1 comment
Closed

Object is incorrectly typed as 'possibly null' inside closure #12113

tjhance opened this issue Nov 9, 2016 · 1 comment
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@tjhance
Copy link

tjhance commented Nov 9, 2016

TypeScript Version: 2.0.3 (also the 2.1 RC)

Code

With --strictNullChecks,

class A {
  constructor() { }
  method() { }
}

function f(a: A | null) {
  a = a || new A();
  if (!a) {
    return;
  } 
  
  [1,2,3].forEach((item) => {
    a.method();
  });
} 

Expected behavior:

I expect this to compile

Actual behavior:

I get an error,

closure.ts(13,5): error TS2531: Object is possibly 'null'.

If I remove the forEach loop and just write a.method(), it compiles. Also, if I remove the line a = a || new A(), it compiles. Both things together seem to confuse TypeScript.

If I remove the if (!a) { return; } it fails with the same error, which seems like a bug as well.

I understand how this closures in general could be difficult to reason about, but in this case, I think TypeScript should be able to figure it out, since the closure function cannot be called until after the if (!a) { return; }, after which point a is never assigned.

@gcnew
Copy link
Contributor

gcnew commented Nov 9, 2016

TypeScript resets the narrowed type when a reference is used inside a closure. This is done because the reference may be of different type if the closure is asynchronously executed (i.e. subsequent code may change the type). As TypeScript does not have a mechanism to tell whether a function is immediately invoked or not, it applies the following two rules:

  • if the variable is declared as const, it preserves its narrowed type (as const variables cannot be reassigned)
  • if a variable or parameter is not reassigned in function's body it's treated as if it was const

So to fix your issue either assign the new value to const a2 or omit the assignment as it seems redundant.

See #10357

@ahejlsberg ahejlsberg added the Working as Intended The behavior described is the intended behavior; this is not a bug label Nov 11, 2016
@mhegazy mhegazy closed this as completed Dec 29, 2016
@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