The solution described in the accepted answer gets the job done but for the cost of losing type safety.
If you want to keep the type-safety going I would suggest the following:
Create dom.d.ts file in @types folder in your sources (or configure typeRoots to make sure that TS compiler will look there) with the following:
interface CustomEventMap {
"customnumberevent": CustomEvent<number>;
"anothercustomevent": CustomEvent<CustomParams>;
}
declare global {
interface Document { //adds definition to Document, but you can do the same with HTMLElement
addEventListener<K extends keyof CustomEventMap>(type: K,
listener: (this: Document, ev: CustomEventMap[K]) => void): void;
dispatchEvent<K extends keyof CustomEventMap>(ev: CustomEventMap[K]): void;
}
}
export { }; //keep that for TS compiler.
This will augment global definition of document‘s addEventListener function to accept your synthetic event and its typed params.
now you can do:
function onCustomEvent(event: CustomEvent<CustomParams>){
this.[...] // this is Document
event.detail ... //is your CustomParams type.
}
document.addEventListener('anothercustomevent', onCustomEvent);
This way you will have everything typed and under control.