2

I have the below array which can have either be an object or undefined. Even after filtering the results to contain all defined values, typescript still says it could be undefined

interface Bob {
    name: string;
}

type BobDetails = undefined | Bob;

const myArray: BobDetails[] = [{ name:  "Bob"}, undefined];
myArray[0].name; // expected Object is possibly 'undefined'.(2532)

var filter = myArray.filter(arr => arr?.name);
filter[0].name; // still Object is possibly 'undefined'.(2532)

How do make Typescript know that filter[] will have only Bob[] and no undefined. I am aware we might be able to do with ! but I want the normal flow to realise it.

Typescript Playground Example

2 Answers 2

4

To do that, you need to have your filter function be a custom type guard. Right now, arr => arr?.name is just a function that returns a string | undefined. You and i can figure out what implications that will have for the resulting array, but typescript needs a bit more.

If you change the function so that it returns a boolean, and you give it the special return type arr is Bob, then typescript knows that if true is returned, then it can deduce that arr is a Bob. And the filter method knows that this will then result in a Bob[]:

var filter = myArray.filter((arr): arr is Bob => arr?.name !== undefined);

Playground link

Sign up to request clarification or add additional context in comments.

4 Comments

Right now, arr => arr?.name is just a function that returns a string | undefined how can this be possible? We are filtering the results right?
This is a neat solution although I guess its the same as var filter = myArray.filter(arr => arr?.name) as Bob[];. You're simply moving the cast to the type guard after all.
@NidhinJoseph The answer to that is probably : Typescript cannot infer this. This may answer that question also.
The type on arr => arr?.name is the same as the type on arr => Math.random() > 0.5 ? 'foo' : undefined, but only the first one should result in filter being a Bob[]. Using only the implicit type information, there isn't a way for typescript to know whether the array will be narrowed or not. So you need to use a more explicit type to give typescript more information.
1

Imagine the array being: BobDetails[] = [undefined, undefined];

Then filter[0].name; will also be undefined. For simplicity you can check the length of filter as:

if(filter.length>0){ filter[0].name; ... your code}

1 Comment

How does this resolve the error? it still shows Object is possibly undefined

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.