Skip to content

Commit

Permalink
Optional strong type events for TypeScript (#291)
Browse files Browse the repository at this point in the history
* feat(types): add optional type safety for events

* docs(README): add strong typed events
  • Loading branch information
vader-sama authored Sep 6, 2022
1 parent 3485e7e commit c24b66b
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 4 deletions.
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -807,3 +807,25 @@ emitter.emit('event', 'never handled');
### EventEmitter2.defaultMaxListeners
Sets default max listeners count globally for all instances, including those created before the change is made.
### Strongly typed events
For using strongly type events (_available only in `TypeScript`_) you can create a new `EventEmitter` instance like this:
```ts
import EventEmitter2 from "eventemitter2";

type events = {
error: (err: Error) => void
message: (sender: string, msg: string) => void
}

const emitter = new EventEmitter2<events>()

// Ok
emitter.emit("error", new Error("example"))
emitter.emit("message", "someone", "hello")

// TypeScript catches mistakes
emitter.emit("error", true)
emitter.emit("message", 1, "hello")
```
43 changes: 39 additions & 4 deletions eventemitter2.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
export type event = (symbol|string);
export type eventNS = string|event[];
export type typeSafeEvents = {
[key: event]: (...args: any[]) => void
}

export interface ConstructorOptions {
/**
Expand Down Expand Up @@ -118,32 +121,64 @@ export interface Listener {
off(): this;
}

export declare class EventEmitter2 {
export declare class EventEmitter2<TypeSafeEvents extends typeSafeEvents = { [key: event]: (...args: any[]) => void }> {
constructor(options?: ConstructorOptions)
emit(event: event | eventNS, ...values: any[]): boolean;
emitAsync(event: event | eventNS, ...values: any[]): Promise<any[]>;
emit<Event extends keyof TypeSafeEvents>(event: Event | Event[], ...values: Parameters<TypeSafeEvents[Event]>): boolean;
emitAsync<Event extends keyof TypeSafeEvents>(event: Event | Event[], ...values: Parameters<TypeSafeEvents[Event]>): Promise<any[]>;

addListener<Event extends keyof TypeSafeEvents>(event: Event | Event, listener: TypeSafeEvents[Event]): this|Listener;
addListener(event: event | eventNS, listener: ListenerFn): this|Listener;

on<Event extends keyof TypeSafeEvents>(event: Event | Event, listener: TypeSafeEvents[Event]): this|Listener;
on(event: event | eventNS, listener: ListenerFn, options?: boolean|OnOptions): this|Listener;

prependListener<Event extends keyof TypeSafeEvents>(event: Event | Event, listener: TypeSafeEvents[Event], options?: boolean|OnOptions): this|Listener;
prependListener(event: event | eventNS, listener: ListenerFn, options?: boolean|OnOptions): this|Listener;

once<Event extends keyof TypeSafeEvents>(event: Event | Event, listener: TypeSafeEvents[Event], options?: true|OnOptions): this|Listener;
once(event: event | eventNS, listener: ListenerFn, options?: true|OnOptions): this|Listener;

prependOnceListener<Event extends keyof TypeSafeEvents>(event: Event | Event, listener: TypeSafeEvents[Event], options?: boolean|OnOptions): this|Listener;
prependOnceListener(event: event | eventNS, listener: ListenerFn, options?: boolean|OnOptions): this|Listener;

many<Event extends keyof TypeSafeEvents>(event: Event | Event, timesToListen: number, listener: TypeSafeEvents[Event], options?: boolean|OnOptions): this|Listener;
many(event: event | eventNS, timesToListen: number, listener: ListenerFn, options?: boolean|OnOptions): this|Listener;

prependMany<Event extends keyof TypeSafeEvents>(event: Event | Event, timesToListen: number, listener: TypeSafeEvents[Event], options?: boolean|OnOptions): this|Listener;
prependMany(event: event | eventNS, timesToListen: number, listener: ListenerFn, options?: boolean|OnOptions): this|Listener;

onAny(listener: EventAndListener): this;
prependAny(listener: EventAndListener): this;
offAny(listener: ListenerFn): this;

removeListener<Event extends keyof TypeSafeEvents>(event: Event | Event, listener: TypeSafeEvents[Event]): this;
removeListener(event: event | eventNS, listener: ListenerFn): this;

off<Event extends keyof TypeSafeEvents>(event: Event | Event, listener: TypeSafeEvents[Event]): this;
off(event: event | eventNS, listener: ListenerFn): this;
removeAllListeners(event?: event | eventNS): this;

removeAllListeners<Event extends keyof TypeSafeEvents>(event?: Event | Event[] | eventNS): this;
setMaxListeners(n: number): void;
getMaxListeners(): number;
eventNames(nsAsArray?: boolean): (event|eventNS)[];

listenerCount<Event extends keyof TypeSafeEvents>(event?: Event | Event[]): number
listenerCount(event?: event | eventNS): number

listeners<Event extends keyof TypeSafeEvents>(event?: Event): Array<TypeSafeEvents[Event]>
listeners(event?: event | eventNS): ListenerFn[]

listenersAny(): ListenerFn[]

waitFor<Event extends keyof TypeSafeEvents>(event: Event, timeout?: number): CancelablePromise<any[]>
waitFor(event: event | eventNS, timeout?: number): CancelablePromise<any[]>

waitFor<Event extends keyof TypeSafeEvents>(event: Event, filter?: WaitForFilter): CancelablePromise<any[]>
waitFor(event: event | eventNS, filter?: WaitForFilter): CancelablePromise<any[]>

waitFor<Event extends keyof TypeSafeEvents>(event: Event, options?: WaitForOptions): CancelablePromise<any[]>
waitFor(event: event | eventNS, options?: WaitForOptions): CancelablePromise<any[]>

listenTo(target: GeneralEventEmitter, events: event | eventNS, options?: ListenToOptions): this;
listenTo(target: GeneralEventEmitter, events: event[], options?: ListenToOptions): this;
listenTo(target: GeneralEventEmitter, events: Object, options?: ListenToOptions): this;
Expand Down

0 comments on commit c24b66b

Please sign in to comment.