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
.