To avoid nonexistent events appear in the service methods let's create an enum with all our event names.
Each event has its own specific data interface. To bound event name to data let's create an interface that will have an event name as a key and data type as its key value.
After we linked event names to its data appears the question "How we actually get event data type?"
Typescript allows you to get the type of property in the interface by its key.
The best example for a generic key loop is already built in TS - "Pick" utility type.
The best example for a generic key loop is already built in TS - "Pick" utility type.
If you create a function with generic parameters it's not always required to open angle brackets for type, because usually type can be inferred from parameters itself. Similar to variable assign where type can be inferred from the value itself.
There are cases when you need a filter for generic type. For example, your function accepts any object but requires specific params.
So after all information and actions what we did it's time to write our typed emitter method