typescriptstrictnullchecks

Is there a good way of telling typescript all array elements exist in a Map?


Let's say I'm creating a Map from an array of objects with ids as keys, then accessing the map from a different array that has the same ids:

const arr1 = [
  {id: 'a', firstName: 'Jeff'},
  {id: 'b', firstName: 'John'},
  {id: 'c', firstName: 'Jeremy'}
];

const map1 = new Map(arr1.map(element => [element.id, element]));

const arr2 = [
  {id: 'b', lastName: 'Johnson'},
  {id: 'c', lastName: 'Jackson'},
  {id: 'd', lastName: 'Jenkins'}
];

const arr2InMap1 = arr2.filter(element => map1.has(element.id));
arr2InMap1.forEach(element => console.log(`${map1.get(element.id).firstName} ${element.lastName}`));

If I have "strictNullChecks": true, then the final line would throw an "Object is possibly 'undefined'" error, even though it can never be undefined. Is there a way of telling typescript that the elements in the array exist in the map?

I know I can use the '!' operator, or create a function that only returns T instead of T | undefined to replace Map.get, but is there a better way of achieving this?


Solution

  • No, that is the signature for Map.get. If this is bothersome, a plain object might work better for your case:

    TS Playground

    const obj1 = arr1.reduce(
      (obj, value) => (obj[value.id] = value) && obj,
      {} as Record<string, typeof arr1[number]>,
    );
    
    const arr2InMap1 = arr2.filter(element => element.id in obj1);
    arr2InMap1.forEach(element => console.log(`${obj1[element.id].firstName} ${element.lastName}`));