With reference to my code below, I am trying to create a Map<string, Function> (eventHandlerMap
in the code below) such that each of its keys is a string from (PortalEvent
in the code below) Union type. The value of each property should be a function that must return an object of specific type (in this example one of UserComment
or Author
).
Objectives:
-
Anytime a new key is added to
PortalEvent
, a handler function must be defined andeventHandlerMap
should be updated. -
Anytime
Author
orUserComment
type is changed the above, the respective handler should be changed for new/removed properties.
If it helps the types PortalEvent
, UserComment
and Author
are 3rd-party library maintained types and I want to be able to update my code whenever a new version of 3rd-party library is used in the project.
Here is the code I have come up: Playground Link
// Typescript Version 5.1.6
// Code for which I have no control over
// -------------------------------------
type PortalEvent = 'comment_created' | 'author_updated';
type UserComment = {
id: string;
content: string;
}
type Author = {
id: string;
name: string;
country: string
}
// Code that I can change
// ----------------------
// Define the types necessary for defining object eventHandlerMap
type HandlerReturnType = {
'comment_created': UserComment,
'author_updated': Author,
}
type HandlerArgType = {
'comment_created': { arg1: number, arg2: string; },
'author_updated': { arg1: string },
}
type THandlerMap<A extends {[j in PortalEvent]: unknown}, R extends {[j in PortalEvent]: unknown}> = {
[key in PortalEvent]: (arg: A[key]) => R[key] ;
};
// Define the Event handler map
const eventHandlerMap: THandlerMap<HandlerArgType, HandlerReturnType> = {
'comment_created': commentCreatedHandler,
'author_updated': authorUpdatedHandler,
}
function commentCreatedHandler(args: HandlerArgType['comment_created']): UserComment {
let id: string = '', content: string = '';
// ... code to initialize id and content properties
return {
id,
content,
};
}
function authorUpdatedHandler(args: HandlerArgType['author_updated']): Author {
let id: string = '', name: string = '', country : string = '';
// ... code to initialize id, name and country properties
return {
id,
name,
country
};
}
The code above achieves the listed objectives. Is there a better way of doing this?
Dev Khan is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.