From 08ed3d406f178f372899fd76b982bf20597756c1 Mon Sep 17 00:00:00 2001 From: Asko Nõmm Date: Sat, 19 Apr 2025 18:49:32 +0300 Subject: Impl generics on dispatch/subscription arguments. --- src/shapex.ts | 82 +++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 52 insertions(+), 30 deletions(-) (limited to 'src/shapex.ts') diff --git a/src/shapex.ts b/src/shapex.ts index fce55d4..d12e159 100644 --- a/src/shapex.ts +++ b/src/shapex.ts @@ -18,21 +18,21 @@ export type SubscriptionResponse = { }; const isSubscriptionResponseList = ( - dispatch: SubscriptionResponseDispatch | SubscriptionResponseDispatch[], + dispatch: SubscriptionResponseDispatch | SubscriptionResponseDispatch[] ): dispatch is SubscriptionResponseDispatch[] => Array.isArray(dispatch); /** * A callback passed to subcriptions, called when the event * that the subscription is listening to is called. */ -export type EventCallback = ( +export type EventCallback = ( state: T, - ...args: unknown[] + ...args: S ) => SubscriptionResponse; -type Subscription = { +type Subscription = { listener: string; - callback: EventCallback; + callback: EventCallback; once: boolean; }; @@ -43,11 +43,17 @@ export type ShapeXInstance = { /** * Subcribe to an event. */ - subscribe: (listener: string, callback: EventCallback) => number; + subscribe: ( + listener: string, + callback: EventCallback + ) => number; /** * Subscribe to an event once. */ - subscribeOnce: (listener: string, callback: EventCallback) => number; + subscribeOnce: ( + listener: string, + callback: EventCallback + ) => number; /** * Unsubscribe from an event. @@ -67,7 +73,7 @@ export type ShapeXInstance = { /** * Dispatch an event. */ - dispatch: (eventName: string, ...args: unknown[]) => void; + dispatch: (eventName: string, ...args: S) => void; /** * Get the current state. @@ -82,10 +88,13 @@ export type ShapeXInstance = { * @returns {ShapeXInstance} The ShapeX object. */ export default function ShapeX( - initialState: T, + initialState: T ): ShapeXInstance { let _state = initialState; - const _subscriptions: Map[]> = new Map(); + const _subscriptions: Map< + string, + Array> + > = new Map(); let subscriptionId = 0; /** @@ -95,16 +104,22 @@ export default function ShapeX( * @param {EventCallback} callback * @returns */ - const subscribe = (listener: string, callback: EventCallback): number => { + const subscribe = ( + listener: string, + callback: EventCallback + ): number => { if (!_subscriptions.has(listener)) { _subscriptions.set(listener, []); } - _subscriptions.get(listener)?.push({ - listener, - callback, - once: false, - }); + const subscriptions = _subscriptions.get(listener); + if (subscriptions) { + subscriptions.push({ + listener, + callback: callback as unknown as EventCallback, + once: false, + }); + } return ++subscriptionId; }; @@ -116,19 +131,22 @@ export default function ShapeX( * @param {EventCallback} callback * @returns */ - const subscribeOnce = ( + const subscribeOnce = ( listener: string, - callback: EventCallback, + callback: EventCallback ): number => { if (!_subscriptions.has(listener)) { _subscriptions.set(listener, []); } - _subscriptions.get(listener)?.push({ - listener, - callback, - once: true, - }); + const subscriptions = _subscriptions.get(listener); + if (subscriptions) { + subscriptions.push({ + listener, + callback: callback as unknown as EventCallback, + once: true, + }); + } return ++subscriptionId; }; @@ -148,11 +166,11 @@ export default function ShapeX( */ const changedState = ( oldState: T, - newState: T, + newState: T ): string[] => { const paths = ( state: R, - path: string, + path: string ): { path: string; value: unknown }[] => { const _paths = [] as { path: string; value: unknown }[]; @@ -207,17 +225,21 @@ export default function ShapeX( * @param {unknown[]} args The arguments to pass to the event listeners. * @returns {void} */ - const dispatch = (eventName: string, ...args: unknown[]): void => { + const dispatch = ( + eventName: string, + ...args: S + ): void => { if (!_subscriptions.has(eventName)) { return; } const scopedSubsriptions = _subscriptions.get(eventName) ?? []; - const remainingSubscriptions = [] as Subscription[]; + const remainingSubscriptions = [] as Array>; let callbackCount = 0; for (const subscription of scopedSubsriptions) { - const response = subscription.callback(_state, ...args); + const callback = subscription.callback as unknown as EventCallback; + const response = callback(_state, ...args); // Updates state, and checks for state changes, and if any changes present, // fires a dispatch for all the state listeners (if there are any). @@ -239,7 +261,7 @@ export default function ShapeX( } else { dispatch( response.dispatch.eventName, - ...(response.dispatch.args ?? []), + ...(response.dispatch.args ?? []) ); } } @@ -284,7 +306,7 @@ export default function ShapeX( */ const state = (): T => { return _state; - } + }; return { subscribe, -- cgit v1.2.3