question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Object is possibly null inside a closure defined within a const constraint

See original GitHub issue

Search: Object is possibly null, narrowed type, type constraint, closure

Code

const foo: string | null = 'bar'
if (foo) {
    function baz() {
        console.log(foo.length)  // Object is possibly 'null'
    }
}

Expected behavior:

Compiles

Actual behavior:

const foo: string | null
Object is possibly 'null'

Playground Link:

Playground

Related Issues:

#12113, #33319, #9998

Discussion:

By design, type narrowings are reset inside closures. This makes sense, but there is one case where better assumptions can be made: when the closure is defined inside a type constraint block AND the type narrowing is based on a const value. Even if called from async, the closure is still referencing a const and was created after a suitable type constraint occurred.

Thoughts?

Issue Analytics

  • State:open
  • Created 4 years ago
  • Comments:15

github_iconTop GitHub Comments

1reaction
benallfreecommented, Apr 27, 2021

function has no any assigned.

@johnsoncodehk Can you provide an example please?

variables is const

Yes this does seem to be an issue. Try this playground sample:

const foo: string | null = 'bar'

const baz1 = () => {
  console.log(foo.length) // OK (narrows to string)
}

const baz2 = function () {
  console.log(foo.length) // OK (narrows to string)
}

function baz3() {
  console.log(foo.length) // Error (possibly null)
}

console.log(foo.length) // OK (narrows to string)
0reactions
cefncommented, Feb 26, 2022

I believe typescript could handle this better. I encountered the problem with a real-world example like this, which I have simplified so it can live in a playground

type UrlString = `http${string}`;

interface Item {
  message: string;
}

interface Config {
  endpointUrl?: UrlString;
}

async function doSave(item: Item, endpointUrl: UrlString) {
  const response = await fetch(`${endpointUrl}/item`, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify(item),
  });
  if (response.status !== 200) {
    throw new Error("Save unsuccessful");
  }
  return item;
}

function createHandle(config: Config) {
  const { endpointUrl } = config;
  if (!endpointUrl) {
    throw new Error(`Cannot create handle without endpointUrl config`);
  }

  // FUNCTION BASED APPROACH
  async function save(item: Item) {
    // compilation error Type 'undefined' is not assignable to type '`http${string}`'
    return await doSave(item, endpointUrl);
  }

  return {
    save,
  };
}

I have no choice but for the config object to have endpointUrl initially undefined, simply because of the framework I am using (it has to be populated at runtime before creating the ‘handle’ above). Hence the need for a runtime check during creation.

It is interesting that if I replace the later lines from // FUNCTION BASED APPROACH with the following, then the potential for endpointUrl to be undefined disappears, which could be a workaround for some cases…

// METHOD BASED APPROACH
  return {
      async save(item:Item){
          // no compilation error
          return await doSave(item, endpointUrl); 
      }
  };
}

However, this also suggests to me that typescript type narrowing inference is not doing its job correctly for the case that a function is defined within a closure over a const which is known (by earlier-executed runtime code) to be set. If it can handle the method case, then it should handle the function case.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Typescript, how to pass "Object is possibly null" error?
When you declare const overlayEl = useRef(null); Makes the type it comes out as is null because that's the best possible inference it...
Read more >
Object is possibly 'null' or 'undefined' error in TS | bobbyhadz
The "Object is possibly 'null' or 'undefined'" error occurs when we try to access a property on an object that may have a...
Read more >
Google JavaScript Style Guide
This document serves as the complete definition of Google's coding standards for source code in the JavaScript programming language.
Read more >
Effective Dart: Design
isAfter(b) ? a : b); } } class _Favorites { static const mammal = 'weasel'; }. In idiomatic Dart, classes define kinds of...
Read more >
Object Constraint Language
defined within a UML model represents a distinct OCL type. In addition ... null objects may be compared with non-invalid objects in =...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found