0

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.

4
  • Can you fix the syntax errors in your code and provide a definition for areas? Commented Oct 27, 2022 at 2:34
  • Here's the solution, but since your code is incomplete/has errors, I don't know if this works in your actual code. Commented Oct 27, 2022 at 2:36
  • @caTS Sorry, I fixed the errors. Commented Oct 27, 2022 at 2:42
  • 1
    @caTS Please post that as an answer Commented Oct 27, 2022 at 8:51

1 Answer 1

3

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

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

4 Comments

Thank you. And one more question. The filter part could be written like so, right? .filter(([areaType, _]) => areaType === 'toCreate' || zoneType === 'toRemove') I've checked, the areaType is inferred.
@Alex Doesn't seem to work... tsplay.dev/WvG3Mw
Well it's because the code in the playground is a little obsolete, I made some edits after you asked me to, and also extended the AreaType type which is is declared as follows: type AreaType = 'toCreate' | 'toRemove' | 'toUpdate';, with this type it works.
I decided not to ask this question here, cos it would be against the community guidelines. So I made it into a a separate question. Could you please have a look? stackoverflow.com/questions/74221788/…

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.