Open awerlogus opened 3 years ago
Hi, you already have Event
definition declared and createEventEmitter()
is not receiving any parameters for which you need to set the type of the parameter. So you can directly use Event as your type definition, below is the probable solution:
type Event = { [K in string] : (data: any) => void }
export function createEventEmitter() {
const events: Set<{ [T in keyof Event]: Event[T] }> = new Set()
function on<T extends keyof Event> (event: T, listener: Event[T]) {
events.add({ [event]: listener })
}
return { on }
}
I have naively tested the solution and it works, please test it for your case.
@sswtds
Your solution doesn't check event listeners' parameter types because there's no place where you can put event type declarations to emitter:
type Event = { [K in string] : (data: any) => void }
export function createEventEmitter() {
const events: Set<{ [T in keyof Event]: Event[T] }> = new Set()
function on<T extends keyof Event> (event: T, listener: Event[T]) {
events.add({ [event]: listener })
}
return { on }
}
// SECTION Test
type RoomCreated = { roomCreated: (roomId: string) => void }
const emitter = createEventEmitter()
const logNumber = (x: number) => console.log(x)
// No error, but expected
emitter.on('roomCreated', logNumber)
The code above does the type check as expected:
type Event = { [K in string] : (data: any) => void }
export function createEventEmitter<E extends Event> () {
const events: Set<{ [T in keyof E]: E[T] }> = new Set()
function on<T extends keyof E> (event: T, listener: E[T]) {
events.add({ [event]: listener })
}
return { on }
}
// SECTION Test
type RoomCreated = { roomCreated: (roomId: string) => void }
const emitter = createEventEmitter<RoomCreated>()
const logNumber = (x: number) => console.log(x)
// Error: Type 'string' is not assignable to type 'number'.
emitter.on('roomCreated', logNumber)
You can find full event emitter usage example here: xroom-app/events2
To check event listener parameter type you can do any one of the followings:
number
: type Event = { [K in string] : (data: number) => void }
listener
data type:
function on<T extends keyof Event> (event: T, listener) {
if(listener as number){
events.add({ [event]: listener })
}
}
both solutions are based on top of my previous solution
@sswtds your solutions are not unfortunately related to the aforementioned issue. Events in your case are pretty limited and cannot bear variable payloads depending on the event types. And as for dynamic checking, this breaks the whole advantage of a static typing there. :(
TypeScript Version: 4.2.0-dev.20201222
Search Terms: type information lost
Code
js:
ts:
Expected behavior: No errors
Actual behavior: In function
on
variableevent
has typeT extends keyof E
, butadd
operation shows an errorRelated Issues: https://github.com/microsoft/TypeScript/issues/42060