Typescript how to define message type for broker consumer

0 votes

I want to describe payload type for message which come from broker. Messages can be publish by different events. Messages include eventName and payload. Right now payload defined as any type. I want to improve code and describe real payloads which can be different. But i cannot find right way how to do. I tried use discriminant technic but fail. Looks like I miss something.

My question: how describe Payload which is different for different events?

type EVENTS = "EVENT_1" | "EVENT_2";

interface Message {
  payload: any;
  eventName: EVENTS;
};

interface Consumer{
  (msg: Message): void;
};


const consumers: Record<EVENTS, Consumer> = {
  "EVENT_1": (msg) => {console.log("EVENT 1")},
  "EVENT_2": (msg) => {console.log("EVENT 1")}
};

const consumerHandler = (
  msg: Message
) => {
  const consumer = consumers[msg.eventName];
  consumer(msg);
}
Jun 14, 2022 in TypeSript by Logan
• 2,140 points
683 views

1 answer to this question.

0 votes

Our main goal - is to make illegal states unrepresentable.

Please see next example. This pattern is your friend if you want to make event driven app (sockets, etc...)

const enum Events {
  foo = "foo",
  bar = "bar",
  baz = "baz",
}

/**
 * Single sourse of true
 */
interface EventMap {
  [Events.foo]: { foo: number };
  [Events.bar]: { bar: string };
  [Events.baz]: { baz: string[] };
}

type Values<T> = T[keyof T];

// credits goes to https://stackoverflow.com/a/50375286
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (
  k: infer I
) => void
  ? I
  : never;

type EmitRecord = {
  [P in keyof EventMap]: (name: P, data: EventMap[P]) => void;
};

type ListenRecord = {
  [P in keyof EventMap]: (
    name: P,
    callback: (arg: EventMap[P]) => void
  ) => void;
};

type MakeOverloadings<T> = UnionToIntersection<Values<T>>;

type Emit = MakeOverloadings<EmitRecord>;
type Listen = MakeOverloadings<ListenRecord>;

const emit: Emit = <T>(name: string, data: T) => {};

emit(Events.bar, { bar: "1" });
emit(Events.baz, { baz: ["1"] });
emit("unimplemented", { foo: 2 }); // expected error

const listen: Listen = (name: string, callback: (arg: any) => void) => {};

listen(Events.baz, (arg /* { baz: string[] } */) => {});
listen(Events.bar, (arg /* { bar: string } */) => {});

UnionToIntersection util type is taken fromhere

EventMap - is our single source of true.

We can use it for typing our listeners and emitters

answered Jun 15, 2022 by Nina
• 3,060 points

Related Questions In TypeSript

0 votes
1 answer
0 votes
1 answer

How to create enum type in TypeScript?

TypeScript 0.9+ has a specification for enums: enum ...READ MORE

answered Jun 8, 2022 in TypeSript by Nina
• 3,060 points
610 views
0 votes
1 answer

How to define props in TypeScript where a parent component injects props in its children?

Typescript doesn't remove this special rule "!text" ...READ MORE

answered Jun 16, 2022 in TypeSript by Nina
• 3,060 points
966 views
0 votes
1 answer

How to create ES6 Map in Typescript

Refer this as an example this.configs = new ...READ MORE

answered May 31, 2022 in TypeSript by Nina
• 3,060 points
405 views
0 votes
0 answers

What should the return type of Promise.race be? (Typescript)

For example in the code below, what ...READ MORE

Jul 5, 2022 in TypeSript by Logan
• 2,140 points
314 views
0 votes
0 answers

What is a type in Typescript for the Component class in Angular 2+?

I have a small problem, but big ...READ MORE

Jul 5, 2022 in TypeSript by Logan
• 2,140 points
523 views
0 votes
1 answer

How can I define a type for a CSS color in TypeScript?

There was a proposal for a type of ...READ MORE

answered Jun 15, 2022 in TypeSript by Nina
• 3,060 points
3,305 views
0 votes
1 answer
webinar REGISTER FOR FREE WEBINAR X
REGISTER NOW
webinar_success Thank you for registering Join Edureka Meetup community for 100+ Free Webinars each month JOIN MEETUP GROUP