Let’s assume we have the HTML events like click, enter, etc. And we want to have a type for strings like ‘onClick’, ‘onEnter’, etc. A first approach could look like this:
type EventHandlerNameUnion = 'onChange' | 'onClick'; // and so on
While this works, it is not the best approach due to the following reasons:
- It’s cumbersome to type all the union values
- As soon as a new HTML event type is added we have to manually extend our type
Generally, we want to have low maintenance types in TypeScript. So, there has to be a better solution.
Template Literal Types to the rescue
Since we want to have a string in the end we can use template literal types to “generate” all the types:
/*
Extract from GlobalEventHandlersEventMap:
interface GlobalEventHandlersEventMap {
...
"change": Event;
"click": MouseEvent;
...
}
*/
type eventTypes = keyof GlobalEventHandlersEventMap;
type EventHandlerName = `on${Capitalize<eventTypes>}`;
If we hover on the type EventHandlerName we see:
We are receiving “on” followed by a capitalised event name, e.g. “Abort”. Finally we are able to detect misspellings and other issue: