Issue
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?
Solution
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
Answered By - Karol Majewski
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.