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

StrictNullChecks and throw/return with incorrect when used with closure scope #13572

Closed
xealot opened this issue Jan 19, 2017 · 3 comments · Fixed by #56908
Closed

StrictNullChecks and throw/return with incorrect when used with closure scope #13572

xealot opened this issue Jan 19, 2017 · 3 comments · Fixed by #56908
Labels
Duplicate An existing issue was already created

Comments

@xealot
Copy link

xealot commented Jan 19, 2017

TypeScript Version: 2.1.5

Code

function other() {
  return new Promise((resolve, reject) => {
    resolve("OK!");
  });
}

function test(hosts: {whatever: boolean}[]) {
  let host = hosts.filter((f) => f.whatever).shift();

  if (!host) {
    throw new Error("Crap!");
  }

  return other().then(() => {
    console.log(`${host.whatever} selected`);
  });
}

Playground

Expected behavior:

Do not emit an error about host possibly being null, since the method exits early if that's the case.

Actual behavior:

Typically when using strictnullchecks Typescript is intelligent enough to understand that when you throw an error from a method based on a type check/guard it narrows the type after the statement. As indicated in this short example:

function test(hosts: {whatever: boolean}[]) {
  let host = hosts.filter((f) => f.whatever).shift();

  // Correctly calls out hose as possibly being null
  console.log(`${host.whatever} selected`);
  
  if (!host) {
    throw new Error("Crap!");
  }

  // Does not complain here because of the above check/throw
  console.log(`${host.whatever} selected`);
}

For some reason when you add the return of the function and use host through a closure it starts complaining.

I'm sure it's the closure, but I don't see how this could error.

@xealot
Copy link
Author

xealot commented Jan 19, 2017

Note: re-assigning the variable to a new variable after the throw seems to re-bind the type information and solves the issue... Seems like a bug.

function other() {
  return new Promise((resolve, reject) => {
    resolve("OK!");
  });
}

function test(hosts: {whatever: boolean}[]) {
  let host = hosts.filter((f) => f.whatever).shift();

  if (!host) {
    throw new Error("Crap!");
  }

  let ho = host;  // WAVES MAGIC WAND

  return other().then(() => {
    console.log(`${ho.whatever} selected`);
  });
}

@HerringtonDarkholme
Copy link
Contributor

#9998 / #11498

Changing let host to const host also solves this.

@xealot
Copy link
Author

xealot commented Jan 19, 2017

Wow, the perfect comment!

Found the threads I knew existed by couldn't locate in search, and offered clean workaround!

Thanks. Closing in favor of #9998 and #11498

@xealot xealot closed this as completed Jan 19, 2017
@RyanCavanaugh RyanCavanaugh added the Duplicate An existing issue was already created label Jan 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
Duplicate An existing issue was already created
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants