Hi, I’m trying to create a generic React hook that listens to an EventEmitter3 instance and updates state based on a selected transformation of the event arguments.
Here’s a simplified example:
function useEventEmitterState<
TState,
TEmitter extends EventEmitter,
TEvent extends ReturnType<TEmitter["eventNames"]>[number]
>(
emitter: TEmitter,
event: TEvent,
select: (...args: any[]) => TState,
init: (() => TState) | TState
) {
const [state, setState] = useState<TState>(init);
useEffect(() => {
if (!emitter) return;
const listener = (...args: any[]) => {
setState(select(...args));
};
emitter.on(event, listener);
return () => emitter.off(event, listener);
}, [emitter, event]);
return state;
}
Problem:
TypeScript cannot infer the argument types for select based on the event name TEvent and the emitter instance TEmitter.
Currently I have to use any[] for ...args in select and the internal listener.
I would like a way to type select so that:
const state = useEventEmitterState(emitter, "smthChanged", (arg1, arg2) => { ... }, ...);
TypeScript automatically infers arguments for event name.
Request:
Could the EventEmitter3 typings support inferring event argument types from the generic EventMap of the emitter instance? Something similar to:
interface MyEvents {
fileSelected: [File];
otherEvent: [string, number];
}
class Example extends EventEmitter<MyEvents> {
selectedFile: File | null = null;
}
const emitter = new Example();
function MyComponent() {
// select callback should infer args based on "fileSelected"
const selectedFile = useEventEmitterState<File | null>(emitter, "fileSelected", (file) => file, emitter.selectedFile);
const someOtherState = useEventEmitterState<string>(emitter, "otherEvent", (arg1,arg2) => `${arg1}${arg2}`, "");
return <div>hi</div>
}
Right now, using only ReturnType<TEmitter["eventNames"]>[number] is insufficient, because TS loses the argument types.
Thanks!
Hi, I’m trying to create a generic React hook that listens to an EventEmitter3 instance and updates state based on a selected transformation of the event arguments.
Here’s a simplified example:
Problem:
TypeScript cannot infer the argument types for
selectbased on the event nameTEventand the emitter instanceTEmitter.Currently I have to use any[] for ...args in select and the internal listener.
I would like a way to type select so that:
TypeScript automatically infers arguments for event name.
Request:
Could the EventEmitter3 typings support inferring event argument types from the generic EventMap of the emitter instance? Something similar to:
Right now, using only ReturnType<TEmitter["eventNames"]>[number] is insufficient, because TS loses the argument types.
Thanks!