forked from sindresorhus/component-emitter
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
The StrictEventEmitter class that was defined in the socket.io-client repository ([1]) is moved here, so we don't need to create an intermediary class (Socket > StrictEventEmitter > Emitter) to get the proper types. As an additional benefit, the final bundle size should be decreased. BREAKING CHANGE: we now use a named export instead of a default export ```js // before import Emitter from "@socket.io/component-emitter" // after import { Emitter } from "@socket.io/component-emitter" ``` [1]: https://github.com/socketio/socket.io-client/blob/a9e5b85580e8edca0b0fd2850c3741d3d86a96e2/lib/typed-events.ts
- Loading branch information
1 parent
59b4bad
commit 84397cb
Showing
3 changed files
with
182 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,179 @@ | ||
interface Emitter<Event = string> { | ||
on(event: Event, listener: Function): Emitter; | ||
once(event: Event, listener: Function): Emitter; | ||
off(event?: Event, listener?: Function): Emitter; | ||
emit(event: Event, ...args: any[]): Emitter; | ||
listeners(event: Event): Function[]; | ||
hasListeners(event: Event): boolean; | ||
removeListener(event?: Event, listener?: Function): Emitter; | ||
removeEventListener(event?: Event, listener?: Function): Emitter; | ||
removeAllListeners(event?: Event): Emitter; | ||
/** | ||
* An events map is an interface that maps event names to their value, which | ||
* represents the type of the `on` listener. | ||
*/ | ||
export interface EventsMap { | ||
[event: string]: any; | ||
} | ||
|
||
declare const Emitter: { | ||
(obj?: object): Emitter; | ||
new (obj?: object): Emitter; | ||
}; | ||
/** | ||
* The default events map, used if no EventsMap is given. Using this EventsMap | ||
* is equivalent to accepting all event names, and any data. | ||
*/ | ||
export interface DefaultEventsMap { | ||
[event: string]: (...args: any[]) => void; | ||
} | ||
|
||
/** | ||
* Returns a union type containing all the keys of an event map. | ||
*/ | ||
export type EventNames<Map extends EventsMap> = keyof Map & (string | symbol); | ||
|
||
/** The tuple type representing the parameters of an event listener */ | ||
export type EventParams< | ||
Map extends EventsMap, | ||
Ev extends EventNames<Map> | ||
> = Parameters<Map[Ev]>; | ||
|
||
/** | ||
* The event names that are either in ReservedEvents or in UserEvents | ||
*/ | ||
export type ReservedOrUserEventNames< | ||
ReservedEventsMap extends EventsMap, | ||
UserEvents extends EventsMap | ||
> = EventNames<ReservedEventsMap> | EventNames<UserEvents>; | ||
|
||
/** | ||
* Type of a listener of a user event or a reserved event. If `Ev` is in | ||
* `ReservedEvents`, the reserved event listener is returned. | ||
*/ | ||
export type ReservedOrUserListener< | ||
ReservedEvents extends EventsMap, | ||
UserEvents extends EventsMap, | ||
Ev extends ReservedOrUserEventNames<ReservedEvents, UserEvents> | ||
> = FallbackToUntypedListener< | ||
Ev extends EventNames<ReservedEvents> | ||
? ReservedEvents[Ev] | ||
: Ev extends EventNames<UserEvents> | ||
? UserEvents[Ev] | ||
: never | ||
>; | ||
|
||
/** | ||
* Returns an untyped listener type if `T` is `never`; otherwise, returns `T`. | ||
* | ||
* This is a hack to mitigate https://github.com/socketio/socket.io/issues/3833. | ||
* Needed because of https://github.com/microsoft/TypeScript/issues/41778 | ||
*/ | ||
type FallbackToUntypedListener<T> = [T] extends [never] | ||
? (...args: any[]) => void | Promise<void> | ||
: T; | ||
|
||
/** | ||
* Strictly typed version of an `EventEmitter`. A `TypedEventEmitter` takes type | ||
* parameters for mappings of event names to event data types, and strictly | ||
* types method calls to the `EventEmitter` according to these event maps. | ||
* | ||
* @typeParam ListenEvents - `EventsMap` of user-defined events that can be | ||
* listened to with `on` or `once` | ||
* @typeParam EmitEvents - `EventsMap` of user-defined events that can be | ||
* emitted with `emit` | ||
* @typeParam ReservedEvents - `EventsMap` of reserved events, that can be | ||
* emitted by socket.io with `emitReserved`, and can be listened to with | ||
* `listen`. | ||
*/ | ||
export class Emitter< | ||
ListenEvents extends EventsMap, | ||
EmitEvents extends EventsMap, | ||
ReservedEvents extends EventsMap = {} | ||
> { | ||
/** | ||
* Adds the `listener` function as an event listener for `ev`. | ||
* | ||
* @param ev Name of the event | ||
* @param listener Callback function | ||
*/ | ||
on<Ev extends ReservedOrUserEventNames<ReservedEvents, ListenEvents>>( | ||
ev: Ev, | ||
listener: ReservedOrUserListener<ReservedEvents, ListenEvents, Ev> | ||
): this; | ||
|
||
/** | ||
* Adds a one-time `listener` function as an event listener for `ev`. | ||
* | ||
* @param ev Name of the event | ||
* @param listener Callback function | ||
*/ | ||
once<Ev extends ReservedOrUserEventNames<ReservedEvents, ListenEvents>>( | ||
ev: Ev, | ||
listener: ReservedOrUserListener<ReservedEvents, ListenEvents, Ev> | ||
): this; | ||
|
||
export default Emitter; | ||
/** | ||
* Removes the `listener` function as an event listener for `ev`. | ||
* | ||
* @param ev Name of the event | ||
* @param listener Callback function | ||
*/ | ||
off<Ev extends ReservedOrUserEventNames<ReservedEvents, ListenEvents>>( | ||
ev?: Ev, | ||
listener?: ReservedOrUserListener<ReservedEvents, ListenEvents, Ev> | ||
): this; | ||
|
||
/** | ||
* Emits an event. | ||
* | ||
* @param ev Name of the event | ||
* @param args Values to send to listeners of this event | ||
*/ | ||
emit<Ev extends EventNames<EmitEvents>>( | ||
ev: Ev, | ||
...args: EventParams<EmitEvents, Ev> | ||
): this; | ||
|
||
/** | ||
* Emits a reserved event. | ||
* | ||
* This method is `protected`, so that only a class extending | ||
* `StrictEventEmitter` can emit its own reserved events. | ||
* | ||
* @param ev Reserved event name | ||
* @param args Arguments to emit along with the event | ||
*/ | ||
protected emitReserved<Ev extends EventNames<ReservedEvents>>( | ||
ev: Ev, | ||
...args: EventParams<ReservedEvents, Ev> | ||
): this; | ||
|
||
/** | ||
* Returns the listeners listening to an event. | ||
* | ||
* @param event Event name | ||
* @returns Array of listeners subscribed to `event` | ||
*/ | ||
listeners<Ev extends ReservedOrUserEventNames<ReservedEvents, ListenEvents>>( | ||
event: Ev | ||
): ReservedOrUserListener<ReservedEvents, ListenEvents, Ev>[]; | ||
|
||
/** | ||
* Returns true if there is a listener for this event. | ||
* | ||
* @param event Event name | ||
* @returns boolean | ||
*/ | ||
hasListeners< | ||
Ev extends ReservedOrUserEventNames<ReservedEvents, ListenEvents> | ||
>(event: Ev): boolean; | ||
|
||
/** | ||
* Removes the `listener` function as an event listener for `ev`. | ||
* | ||
* @param ev Name of the event | ||
* @param listener Callback function | ||
*/ | ||
removeListener< | ||
Ev extends ReservedOrUserEventNames<ReservedEvents, ListenEvents> | ||
>( | ||
ev?: Ev, | ||
listener?: ReservedOrUserListener<ReservedEvents, ListenEvents, Ev> | ||
): this; | ||
|
||
/** | ||
* Removes all `listener` function as an event listener for `ev`. | ||
* | ||
* @param ev Name of the event | ||
*/ | ||
removeAllListeners< | ||
Ev extends ReservedOrUserEventNames<ReservedEvents, ListenEvents> | ||
>(ev?: Ev): this; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
|
||
var Emitter = require('..'); | ||
var { Emitter } = require('..'); | ||
|
||
function Custom() { | ||
Emitter.call(this) | ||
|