/** * A function that emits a side effect and does not return anything. */ export type Procedure = (...args: any[]) => void export type Options = { isImmediate: boolean } export function debounce( func: F, waitMilliseconds: number = 50, options: Options = { isImmediate: false } ): F { let timeoutId: NodeJS.Timeout | undefined return function(this: any, ...args: any[]) { const context = this const doLater = function() { timeoutId = undefined if (!options.isImmediate) { func.apply(context, args) } } const shouldCallNow = options.isImmediate && timeoutId === undefined if (!!timeoutId) { clearTimeout(timeoutId) } timeoutId = setTimeout(doLater, waitMilliseconds) if (shouldCallNow) { func.apply(context, args) } } as any }