From f608028f57916c9ed3aabdb57807a6b380c92b73 Mon Sep 17 00:00:00 2001 From: Arthur <45236453+ArthurMJ96@users.noreply.github.com> Date: Sat, 15 Mar 2025 08:41:58 +0100 Subject: [PATCH 1/2] feat(typescript-utils): add EndsWith utility type --- packages/core/utils/typescript-utils.d.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/core/utils/typescript-utils.d.ts b/packages/core/utils/typescript-utils.d.ts index 2b7de2fd33..140e46ffd3 100644 --- a/packages/core/utils/typescript-utils.d.ts +++ b/packages/core/utils/typescript-utils.d.ts @@ -4,3 +4,12 @@ * // returns: { eventName: string; object?: Observable } */ export type Optional = Omit & { [P in K]?: T[P] }; + +/** + * Determines if a string type ends with a specified suffix. + * @example type IsChangeEvent = EndsWith<"propertyNameChange", "Change", true, false> + * // returns: true + * @example type IsChangeEvent = EndsWith<"someEvent", "Change", true, false> + * // returns: false + */ +export type EndsWith = T extends `${infer _}${S}` ? PassType : FailType; \ No newline at end of file From d6eb87afc8151be3f46ab4a3fb7b5d97ba4f1e33 Mon Sep 17 00:00:00 2001 From: Arthur <45236453+ArthurMJ96@users.noreply.github.com> Date: Sat, 15 Mar 2025 08:46:36 +0100 Subject: [PATCH 2/2] feat(observable): enhance event callback type specificity using EndsWith --- packages/core/data/observable/index.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/core/data/observable/index.ts b/packages/core/data/observable/index.ts index 8f75ff67d0..584e622f66 100644 --- a/packages/core/data/observable/index.ts +++ b/packages/core/data/observable/index.ts @@ -1,4 +1,4 @@ -import { Optional } from '../../utils/typescript-utils'; +import { Optional, EndsWith } from '../../utils/typescript-utils'; /** * Base event data. @@ -160,7 +160,7 @@ export class Observable { * `this` context when the callback is called. Falsy values will be not be * bound. */ - public on(eventName: string, callback: (data: EventData) => void, thisArg?: any): void { + public on(eventName: S, callback: (data: EndsWith) => void, thisArg?: any): void { this.addEventListener(eventName, callback, thisArg); } @@ -175,7 +175,7 @@ export class Observable { * `this` context when the callback is called. Falsy values will be not be * bound. */ - public once(eventName: string, callback: (data: EventData) => void, thisArg?: any): void { + public once(eventName: S, callback: (data: EndsWith) => void, thisArg?: any): void { this.addEventListener(eventName, callback, thisArg, true); } @@ -188,7 +188,7 @@ export class Observable { * @param thisArg An optional parameter which, when set, will be used to * refine search of the correct event listener to be removed. */ - public off(eventName: string, callback?: (data: EventData) => void, thisArg?: any): void { + public off(eventName: S, callback?: (data: EndsWith) => void, thisArg?: any): void { this.removeEventListener(eventName, callback, thisArg); }