Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript array find possibly undefind

Tags:

typescript

I have a collection of data that looks like this:

interface Item {   name: "one" | "two";   data: string; }  const namedItems: Item[] = [   {     name: "one",     data: "some data one",   },   {     name: "two",     data: "some data two",   }, ]; 

Each item has a name and the value can either be "one" or "two".

Then running an array find on this:

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

Throws a typescript error "Object is possibly 'undefined'". Which seems to be because of the fact that finds can possibly not find something but in my example you're only allowed to look for "one" or "two" which would always return a result.

How do I get typescript to know it will always return a result in the find?

like image 943
Matt Coady Avatar asked Feb 17 '19 22:02

Matt Coady


People also ask

How do I fix object is possibly undefined in TypeScript?

The "Object is possibly 'undefined'" error occurs when we try to access a property on an object that may have a value of undefined . To solve the error, use the optional chaining operator or a type guard to make sure the reference is not undefined before accessing properties.

How do I check if an object is undefined in TypeScript?

We can use typeof or '==' or '===' to check if a variable is null or undefined in typescript.

How do you prevent undefined in TypeScript?

To avoid undefined values when using or accessing the optional object properties, the basic idea is to check the property value using an if conditional statement or the optional chaining operator before accessing the object property in TypeScript.

What type is undefined TypeScript?

TypeScript has two special types, null and undefined , that have the values null and undefined respectively. We mentioned these briefly in the Basic Types section. By default, the type checker considers null and undefined assignable to anything. Effectively, null and undefined are valid values of every type.


2 Answers

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 
like image 152
Karol Majewski Avatar answered Sep 30 '22 21:09

Karol Majewski


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;

like image 45
Tomek Avatar answered Sep 30 '22 19:09

Tomek