diff --git a/packages/atomic/src/utils/utils.spec.ts b/packages/atomic/src/utils/utils.spec.ts index 234625e2383..b6de71aae77 100644 --- a/packages/atomic/src/utils/utils.spec.ts +++ b/packages/atomic/src/utils/utils.spec.ts @@ -17,6 +17,46 @@ describe('utils', () => { executeOnce(); expect(myFunction).toHaveBeenCalledTimes(1); }); + + it('should support arguments', () => { + const fn = (num: number, str: string) => { + return num * 10 + str.length; + }; + const fnOnce = once(fn); + const result = fnOnce(5, 'test'); + + expect(result).toBe(54); + }); + + it('should ignore arguments if called additional times', () => { + const fn = (num: number, str: string) => { + return num * 10 + str.length; + }; + const fnOnce = once(fn); + const result = fnOnce(5, 'test'); + const result2 = fnOnce(2, 't'); + + expect(result).toBe(54); + expect(result2).toBe(54); + }); + + it('should support void functions', () => { + const fn = (): void => {}; + const fnOnce = once(fn); + const result: unknown = fnOnce(); + + expect(result).toBeUndefined(); + }); + + it('should support typed functions', () => { + const fn = () => { + return 123; + }; + const fnOnce = once(fn); + const result: number = fnOnce(); + + expect(result).toBe(123); + }); }); describe('#camelToKebab', () => { diff --git a/packages/atomic/src/utils/utils.ts b/packages/atomic/src/utils/utils.ts index 76e243e9ff9..004919fc490 100644 --- a/packages/atomic/src/utils/utils.ts +++ b/packages/atomic/src/utils/utils.ts @@ -3,12 +3,13 @@ import DOMPurify from 'dompurify'; /** * Returns a function that can be executed only once */ -export function once(fn: (...args: T) => unknown) { - let result: unknown; +export function once(fn: (...args: T) => R) { + let result: R; + let callable: ((...args: T) => R) | null = fn; return function (this: unknown, ...args: T) { - if (fn) { - result = fn.apply(this, args); - fn = () => {}; + if (callable) { + result = callable.apply(this, args); + callable = null; // Allow garbage collection } return result; };