Strange behaviour of callback function in Typescript

I’m trying to solve problem with filter array function in Typescript, code below:

type Tag = string

type Args = {
  tags?: Tag[]
}

const func = async (args: Args) => {
  if (args.tags) {
    const entities = [
      { tagId: '1' },
      { tagId: '2' }
    ];
    
    const filtered = entities.filter(entity => args.tags.includes(entity.tagId));
    const mapped = args.tags.map(tag => tag + '_test');  
  }
};

This code throws TS2532 error: Object is possibly undefined when I try to filter the entities array. For some reasons TS interpreter thinks that args.tags can be undefined, so include function can’t be called. But as you see, there is a check above, also the map function works fine.

What can be wrong here? Any thoughts are welcome.

Thanks.

Answer

TypeScript doesn’t know that filter‘s callback runs immediately, so if for example filter‘s callback ran later (let’s say on a setTimeout), your code would crash under a call like this:

const a: Args = { tags: [] };
await func(a);
a.tags = undefined;
// Later, the callback runs and accesses 'includes' of the undefined we just set

You can either use !

entity => args.tags!.includes ...

Or stash the value in a const

const tags = args.tags;
if (tags) {
  // ...
  const filtered = entities.filter(entity => tags.includes ...