Taken this structured messages:
type MessageVariant<T extends string, P = {}> = {
type: T;
payload: P;
};
type BoundsChangedMessage = MessageVariant<
"bounds_changed",
{
bounds: number[][];
}
>;
type ChangeLayoutMessage = MessageVariant<
"change_layout",
{
name: string;
}
>;
type Message = BoundsChangedMessage | ChangeLayoutMessage;
I want to be able to express a strong record of:
const handlers: MessageHandler = {
bounds_changed: (message/*: BoundsChangedMessage*/) => {},
change_layout: (message/*: ChangeLayoutMessage*/) => {},
};
So far I have been trying various attempts without luck, including:
type MessageHandler = {
[T in Message["type"]]: (message: MessageVariant<T, /* Payload? */>) => void;
}
Here is a TS Playground for the example.
CodePudding user response:
You need to use Key mapping via "as" and change your MessageHandler
type definition to the following
type Message = BoundsChangedMessage | ChangeLayoutMessage;
type MessageHandler = {
[M in Message as M["type"]]: (message: M) => void;
}
Here is the link to TS Playground with the full example
CodePudding user response:
You can achieve that record type by defining the message handler type like below.
type Message = BoundsChangedMessage | ChangeLayoutMessage;
type MessageHandler = {
[K in Message as K['type']]: (message: K) => void;
}
const handlers: MessageHandler = {
bounds_changed: m => {
console.log(m);
},
change_layout: m => {
console.log(m)
}
}