Typescript: Object is possibly 'undefined'

Typescript doesn't keep type information about values at specific array indices. For example, this is an error:

function test(a: (number | string)[]) {
    if (typeof a[3] === "number") {
        const num: number = a[3];
    }
}

To get something that can have type information, you could put a[k] into some other variable like this:

const checkText = (k: string, a: IAsset | null) => {
if (a) {
  const atK = a[k];
  if (atK) {
    return (textMatch(txt.toLowerCase(), atK.toString().toLowerCase()) ? a : null);
  }
}

or you could cast it, because you know more about the types than the type system:

const checkText = (k: string, a: IAsset | null) => {
  if (a && a[k]) {
    return (textMatch(txt.toLowerCase(), (a[k] as string | number | true).toString().toLowerCase()) ? a : null);
  }
}

or you could avoid having to worry about undefineds by using string interpolation:

const checkText = (k: string, a: IAsset | null) => {
  if (a && a[k]) {
    return (textMatch(txt.toLowerCase(), `${a[k]}`.toLowerCase()) ? a : null);
  }
}

Ideally the type system would take care of these things, but I'm sure there's some reason why this kind of type information isn't available in general.


There are two ways to that I can think of to get rid of the error.

The first way I can think of is to use a fallback with the || operator, which would turn this:

a[k].toString().toLowerCase()

Into this, so if the value is falsy, then use an empty string.

(a[k] || '').toString().toLowerCase()
// Or with optional chaining
a[k]?.toString().toLowerCase() || ''

Note: Use ?? to catch only undefined and null values instead of falsy values.

The other way is to save the value to a variable and check the new variable. Which then makes this

if (a && a[k]) {
  return textMatch(txt.toLowerCase(), a[k].toString().toLowerCase()) ? a : null;
}

Become this:

let v = a ? a[k] : null
if (v) {
  return textMatch(txt.toLowerCase(), v.toString().toLowerCase()) ? a : null;
}