Home > Back-end >  "Where clause" in mapped type
"Where clause" in mapped type

Time:06-19

Working purely on a type level. Given the following scenario:

type Command<Type extends string> = { type: Type };
type Handler<Type extends string, Dependencies> = (cmd: Command<Type>, deps: Dependencies) => void;

type CommandA = Command<"A">;
type CommandB = Command<"B">;

type MockServiceA = { foo: () => boolean };
type MockServiceB = { bar: () => boolean };

type HandlerA = Handler<"A", { someService: MockServiceA }>;
type HandlerB = Handler<"B", { someService: MockServiceA; anotherService: MockServiceB }>;


type HandlerSum = HandlerA | HandlerB; // there might be n handlers in the sum type

I would like to create a mapped type that gives me a dictionary of command types and their dependencies.

type OnlyHalfwayThere = {
  [K in Parameters<HandlerSum>[0]["type"]]: Parameters<HandlerSum>[1]; // <--- this gives me a union of all dependencies
};

// basically what I want is a where clause...
// get the second function argument of the handler where the first function argument matches the key selector [K in Parameters<HandlerSum>[0]["type"]]
// desired outcome
type Outcome = {
  A: { someService: MockServiceA };
  B: { someService: MockServiceA; anotherService: MockServiceB };
};


CodePudding user response:

You can rewrite the mapped type like this:

type OnlyHalfwayThere = {
  [K in Parameters<HandlerSum> as K[0]["type"]]: K[1];
};

Instead of assigning the "type" value to K, we assign Parameters<HandlerSum> to it. We can now use K to get both K[0]["type"] and K[1].

Playground

  • Related