Commit ae5f5cb13c63aec801f9d900a0f3b85bf86b675e

Authored by Kirk Lin
Committed by GitHub
1 parent ccaa84c3

feat: sync mitt (#2677)

Showing 1 changed file with 56 additions and 35 deletions
src/utils/mitt.ts
@@ -2,32 +2,37 @@ @@ -2,32 +2,37 @@
2 * copy to https://github.com/developit/mitt 2 * copy to https://github.com/developit/mitt
3 * Expand clear method 3 * Expand clear method
4 */ 4 */
5 -  
6 export type EventType = string | symbol; 5 export type EventType = string | symbol;
7 6
8 // An event handler can take an optional event argument 7 // An event handler can take an optional event argument
9 // and should not return a value 8 // and should not return a value
10 -export type Handler<T = any> = (event?: T) => void;  
11 -export type WildcardHandler = (type: EventType, event?: any) => void; 9 +export type Handler<T = unknown> = (event: T) => void;
  10 +export type WildcardHandler<T = Record<string, unknown>> = (
  11 + type: keyof T,
  12 + event: T[keyof T],
  13 +) => void;
12 14
13 // An array of all currently registered event handlers for a type 15 // An array of all currently registered event handlers for a type
14 -export type EventHandlerList = Array<Handler>;  
15 -export type WildCardEventHandlerList = Array<WildcardHandler>; 16 +export type EventHandlerList<T = unknown> = Array<Handler<T>>;
  17 +export type WildCardEventHandlerList<T = Record<string, unknown>> = Array<WildcardHandler<T>>;
16 18
17 // A map of event types and their corresponding event handlers. 19 // A map of event types and their corresponding event handlers.
18 -export type EventHandlerMap = Map<EventType, EventHandlerList | WildCardEventHandlerList>; 20 +export type EventHandlerMap<Events extends Record<EventType, unknown>> = Map<
  21 + keyof Events | '*',
  22 + EventHandlerList<Events[keyof Events]> | WildCardEventHandlerList<Events>
  23 +>;
19 24
20 -export interface Emitter {  
21 - all: EventHandlerMap; 25 +export interface Emitter<Events extends Record<EventType, unknown>> {
  26 + all: EventHandlerMap<Events>;
22 27
23 - on<T = any>(type: EventType, handler: Handler<T>): void;  
24 - on(type: '*', handler: WildcardHandler): void; 28 + on<Key extends keyof Events>(type: Key, handler: Handler<Events[Key]>): void;
  29 + on(type: '*', handler: WildcardHandler<Events>): void;
25 30
26 - off<T = any>(type: EventType, handler: Handler<T>): void;  
27 - off(type: '*', handler: WildcardHandler): void; 31 + off<Key extends keyof Events>(type: Key, handler?: Handler<Events[Key]>): void;
  32 + off(type: '*', handler: WildcardHandler<Events>): void;
28 33
29 - emit<T = any>(type: EventType, event?: T): void;  
30 - emit(type: '*', event?: any): void; 34 + emit<Key extends keyof Events>(type: Key, event: Events[Key]): void;
  35 + emit<Key extends keyof Events>(type: undefined extends Events[Key] ? Key : never): void;
31 clear(): void; 36 clear(): void;
32 } 37 }
33 38
@@ -36,7 +41,10 @@ export interface Emitter { @@ -36,7 +41,10 @@ export interface Emitter {
36 * @name mitt 41 * @name mitt
37 * @returns {Mitt} 42 * @returns {Mitt}
38 */ 43 */
39 -export default function mitt(all?: EventHandlerMap): Emitter { 44 +export function mitt<Events extends Record<EventType, unknown>>(
  45 + all?: EventHandlerMap<Events>,
  46 +): Emitter<Events> {
  47 + type GenericEventHandler = Handler<Events[keyof Events]> | WildcardHandler<Events>;
40 all = all || new Map(); 48 all = all || new Map();
41 49
42 return { 50 return {
@@ -47,48 +55,61 @@ export default function mitt(all?: EventHandlerMap): Emitter { @@ -47,48 +55,61 @@ export default function mitt(all?: EventHandlerMap): Emitter {
47 55
48 /** 56 /**
49 * Register an event handler for the given type. 57 * Register an event handler for the given type.
50 - * @param {string|symbol} type Type of event to listen for, or `"*"` for all events 58 + * @param {string|symbol} type Type of event to listen for, or `'*'` for all events
51 * @param {Function} handler Function to call in response to given event 59 * @param {Function} handler Function to call in response to given event
52 * @memberOf mitt 60 * @memberOf mitt
53 */ 61 */
54 - on<T = any>(type: EventType, handler: Handler<T>) {  
55 - const handlers = all?.get(type);  
56 - const added = handlers && handlers.push(handler);  
57 - if (!added) {  
58 - all?.set(type, [handler]); 62 + on<Key extends keyof Events>(type: Key, handler: GenericEventHandler) {
  63 + const handlers: Array<GenericEventHandler> | undefined = all!.get(type);
  64 + if (handlers) {
  65 + handlers.push(handler);
  66 + } else {
  67 + all!.set(type, [handler] as EventHandlerList<Events[keyof Events]>);
59 } 68 }
60 }, 69 },
61 70
62 /** 71 /**
63 * Remove an event handler for the given type. 72 * Remove an event handler for the given type.
64 - * @param {string|symbol} type Type of event to unregister `handler` from, or `"*"`  
65 - * @param {Function} handler Handler function to remove 73 + * If `handler` is omitted, all handlers of the given type are removed.
  74 + * @param {string|symbol} type Type of event to unregister `handler` from (`'*'` to remove a wildcard handler)
  75 + * @param {Function} [handler] Handler function to remove
66 * @memberOf mitt 76 * @memberOf mitt
67 */ 77 */
68 - off<T = any>(type: EventType, handler: Handler<T>) {  
69 - const handlers = all?.get(type); 78 + off<Key extends keyof Events>(type: Key, handler?: GenericEventHandler) {
  79 + const handlers: Array<GenericEventHandler> | undefined = all!.get(type);
70 if (handlers) { 80 if (handlers) {
71 - handlers.splice(handlers.indexOf(handler) >>> 0, 1); 81 + if (handler) {
  82 + handlers.splice(handlers.indexOf(handler) >>> 0, 1);
  83 + } else {
  84 + all!.set(type, []);
  85 + }
72 } 86 }
73 }, 87 },
74 88
75 /** 89 /**
76 * Invoke all handlers for the given type. 90 * Invoke all handlers for the given type.
77 - * If present, `"*"` handlers are invoked after type-matched handlers. 91 + * If present, `'*'` handlers are invoked after type-matched handlers.
78 * 92 *
79 - * Note: Manually firing "*" handlers is not supported. 93 + * Note: Manually firing '*' handlers is not supported.
80 * 94 *
81 * @param {string|symbol} type The event type to invoke 95 * @param {string|symbol} type The event type to invoke
82 * @param {Any} [evt] Any value (object is recommended and powerful), passed to each handler 96 * @param {Any} [evt] Any value (object is recommended and powerful), passed to each handler
83 * @memberOf mitt 97 * @memberOf mitt
84 */ 98 */
85 - emit<T = any>(type: EventType, evt: T) {  
86 - ((all?.get(type) || []) as EventHandlerList).slice().map((handler) => {  
87 - handler(evt);  
88 - });  
89 - ((all?.get('*') || []) as WildCardEventHandlerList).slice().map((handler) => {  
90 - handler(type, evt);  
91 - }); 99 + emit<Key extends keyof Events>(type: Key, evt?: Events[Key]) {
  100 + let handlers = all!.get(type);
  101 + if (handlers) {
  102 + (handlers as EventHandlerList<Events[keyof Events]>).slice().forEach((handler) => {
  103 + handler(evt as Events[Key]);
  104 + });
  105 + }
  106 +
  107 + handlers = all!.get('*');
  108 + if (handlers) {
  109 + (handlers as WildCardEventHandlerList<Events>).slice().forEach((handler) => {
  110 + handler(type, evt as Events[Key]);
  111 + });
  112 + }
92 }, 113 },
93 114
94 /** 115 /**