How to tag a "TS2531: Object is possibly 'null'" when the object is never null" error as a false positive?

Viewed 168

The following code

const infinoteUrl =
  $q.localStorage.getItem("infinote-dev-api") === null
    ? `${window.location.protocol}//${window.location.host}`
    : $q.localStorage.getItem("infinote-dev-api")
console.log(`infinote URL: ${infinoteUrl}`)

let infinoteToken = $q.localStorage.getItem("infinote-token")
if (infinoteToken === null && !infinoteUrl.toString().includes("localhost")) {
   ...
}

compiles with the TS2531: Object is possibly 'null' error:

TS2531: Object is possibly 'null'.
    106 |
    107 |     let infinoteToken = $q.localStorage.getItem("infinote-token")
  > 108 |     if (infinoteToken === null && !infinoteUrl.toString().includes("localhost")) {
        |                                    ^^^^^^^^^^^
    109 |       infinoteToken = "empty"
    110 |       $q.notify({
    111 |         message: 'no infinote-token in local storage',

I do not belive that infinoteUrl can ever be null so I would like to tell the compiler that this case is fine. Is there a way to do so?

As for the issue itself, I solved it thanks to Optional Chaining (if (infinoteToken === null && !infinoteUrl?.toString().includes("localhost"))), but I am interested how to more generally tell the TS compiler that a case it detected is a false alert.

3 Answers

You are assuming that infinoteUrl cannot be null, because you assume that $q.localStorage.getItem("infinote-dev-api") will return twice the same value. But there's no syntactical guarantee for that. Therefore TypeScript is warning you. You can use !. as suggested, but in my eyes, that defeats the point of using a strict type system in the first place. Try to leverage the features typescript has. You can rewrite it to

const maybeInfinoteUrl = $q.localStorage.getItem("infinote-dev-api");
const infinoteUrl =
   maybeInfinoteUrl === null
    ? `${window.location.protocol}//${window.location.host}`
    : maybeInfinoteUrl
console.log(`infinote URL: ${infinoteUrl}`)

or a much simpler form (which basically compiles to something similar) would be

const infinoteUrl =
  $q.localStorage.getItem("infinote-dev-api")
    ?? `${window.location.protocol}//${window.location.host}`

console.log(`infinote URL: ${infinoteUrl}`)

here you have a TypeScript Plaground example: https://www.typescriptlang.org/play?#code/GYVwdgxgLglg9mABAcwKZQGoEMA2JUAUAlAFyJgg46IA+iAzlAE4xjKIDeAUIr4k+hBMkAciz0AJsBEBuLgF8uXCAkaIAHogC8KdNjyEi2rTopVEAfkQiAjgHdUTEYjJpMufMTkqwagJ7auu4GxJZWtg5OcsqqcDioAHQ4cMgE6glQcAAycJEAwuKGRN6x8UkpBH4Z2bmOBfRFMkA

Use @ts-ignore

// @ts-ignore TS2531: Object is possibly 'null'
if (infinoteToken === null && !infinoteUrl.toString().includes("localhost"))

This will ignore all errors on the line below the comment (so using optional chaining even though the value is never null will be safer)

Related