Typescript array find possibly undefind

If you're absolutely sure that you'll always get a match then you can tell TS so:

const getData = (query: "one" | "two") => (namedItems.find((item) => query === item.name) as Item).data;


Explanation

The reason you are experiencing this is the type signature for Array.prototype.find:

find(predicate: (value: T, index: number, obj: T[]) => boolean, thisArg?: any): T | undefined;

As you can see, it always returns T | undefined. This makes a lot of sense because a collection defined as Item[] can contain an arbitrary number of items — including 0. In your case, the collection is complete, but on the type level it's no different than [{ name: "one", data: "some data one" }] or even [].

In order to access item.data in a type-safe manner, TypeScript will require you to double check whether the result is indeed found.

const lookup = namedItems.find(item => item.name === 'one');

if (lookup === undefined) {
  throw new TypeError('The value was promised to always be there!');
}

console.log(lookup.data);

Solution

Since this can become cumbersome in the long run, you may find it useful to create a helper function for this kind of scenarios.

function ensure<T>(argument: T | undefined | null, message: string = 'This value was promised to be there.'): T {
  if (argument === undefined || argument === null) {
    throw new TypeError(message);
  }

  return argument;
}

Usage:

const getData = (query: "one" | "two") =>
  ensure(namedItems.find(item => query === item.name)).data

Tags:

Typescript