Home > Back-end >  set type for the key values of Object.entries in typescript
set type for the key values of Object.entries in typescript

Time:10-28

Quick task description:

I have an object of areas and I need to do some processing of those areas depending on their type using the areaProcessor function. Also, only 'toCreate' and 'toRemove' types of areas should be processed.

type AreaType = 'toCreate' | 'toRemove' | 'toUpdate';

const areas: AreaType = { toCreate: [], toUpdate: [], toRemove: [] };

const areaProcessor = (areaType: AreaType, gf: any): any => {};

Object.entries(areas)
      .filter(([areaType, _]) => areaType === 'toCreate' || areaType === 'toRemove')
      .flatMap(([areaType, gf]) => areaProcessor(areaType, gf));

Problem:

The problem here is that typescript throws a type error for areaProcessor:

Argument of type 'string' is not assignable to parameter of type '"toCreate" | "toRemove"'.

Obviously, it's because in the flatMap function areaType is of type string, but I'd like it to be of type

type AreaType = 'toCreate' | 'toRemove' | 'toUpdate';

Question:

How do I do the conversion then?

P.S.

I used any just to avoid introducing new, irrelevant types.

CodePudding user response:

Object.entries will give you "wider" types than what you would expect (because it could return keys that don't exist in the type), but you can ignore this by making your own type:

type Entries<T> = {
    [K in keyof T]: [key: K, value: T[K]];
}[keyof T][];

Then we have to cast to this and use a type predicate to narrow the entries:


(Object.entries(obj) as Entries<typeof obj>)
    .filter((pair): pair is [AreaType, typeof pair[1]] => pair[0] === "toCreate" || pair[0] === "toRemove")
    .flatMap(([areaType, gf]) => areaProcessor(areaType, gf)); // OK

After we narrow the entries, it is now OK to pass areaType to areaProcessor.

Playground

  • Related