Skip to content

Commit

Permalink
🤖 Merge PR #69504 [@types/lodash] Infer lodash.throttle return type f…
Browse files Browse the repository at this point in the history
…rom 'leading' option by @dawaltconley
  • Loading branch information
dawaltconley committed May 16, 2024
1 parent aebfd29 commit 91003f3
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 16 deletions.
10 changes: 10 additions & 0 deletions types/lodash/common/function.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1354,6 +1354,7 @@ declare module "../index" {
*/
trailing?: boolean | undefined;
}
type ThrottleSettingsLeading = (ThrottleSettings & { leading: true }) | Omit<ThrottleSettings, 'leading'>
interface LoDashStatic {
/**
* Creates a throttled function that only invokes func at most once per every wait milliseconds. The throttled
Expand All @@ -1371,12 +1372,17 @@ declare module "../index" {
* @param options.trailing Specify invoking on the trailing edge of the timeout.
* @return Returns the new throttled function.
*/
throttle<T extends (...args: any) => any>(func: T, wait?: number, options?: ThrottleSettingsLeading): DebouncedFuncLeading<T>;
throttle<T extends (...args: any) => any>(func: T, wait?: number, options?: ThrottleSettings): DebouncedFunc<T>;
}
interface Function<T extends (...args: any) => any> {
/**
* @see _.throttle
*/
throttle(
wait?: number,
options?: ThrottleSettingsLeading
): T extends (...args: any[]) => any ? Function<DebouncedFuncLeading<T>> : never;
throttle(
wait?: number,
options?: ThrottleSettings
Expand All @@ -1386,6 +1392,10 @@ declare module "../index" {
/**
* @see _.throttle
*/
throttle(
wait?: number,
options?: ThrottleSettingsLeading
): T extends (...args: any[]) => any ? FunctionChain<DebouncedFuncLeading<T>> : never;
throttle(
wait?: number,
options?: ThrottleSettings
Expand Down
6 changes: 3 additions & 3 deletions types/lodash/fp.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4173,10 +4173,10 @@ declare namespace _ {
interface LodashThrottle {
(wait: number): LodashThrottle1x1;
<T extends (...args: any) => any>(wait: lodash.__, func: T): LodashThrottle1x2<T>;
<T extends (...args: any) => any>(wait: number, func: T): lodash.DebouncedFunc<T>;
<T extends (...args: any) => any>(wait: number, func: T): lodash.DebouncedFuncLeading<T>;
}
type LodashThrottle1x1 = <T extends (...args: any) => any>(func: T) => lodash.DebouncedFunc<T>;
type LodashThrottle1x2<T extends (...args: any) => any> = (wait: number) => lodash.DebouncedFunc<T>;
type LodashThrottle1x1 = <T extends (...args: any) => any>(func: T) => lodash.DebouncedFuncLeading<T>;
type LodashThrottle1x2<T extends (...args: any) => any> = (wait: number) => lodash.DebouncedFuncLeading<T>;
interface LodashThru {
<T, TResult>(interceptor: (value: T) => TResult): LodashThru1x1<T, TResult>;
<T>(interceptor: lodash.__, value: T): LodashThru1x2<T>;
Expand Down
63 changes: 50 additions & 13 deletions types/lodash/lodash-tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3656,25 +3656,62 @@ fp.now(); // $ExpectType number

// _.throttle
{
const options: _.ThrottleSettings = {
const optionsLeading: _.ThrottleSettingsLeading = {
leading: true,
trailing: false,
}
const optionsNoLeading: _.ThrottleSettings = {
leading: false,
};

const optionsAmbiguous = {
leading: true as boolean,
};
const boolean = false as boolean; // $ExpectType boolean
const maybeUndefined = true as true | undefined; // $ExpectType true | undefined

const func = (a: number, b: string): boolean => true;

_.throttle(func); // $ExpectType DebouncedFunc<(a: number, b: string) => boolean>
_.throttle(func, 42); // $ExpectType DebouncedFunc<(a: number, b: string) => boolean>
_.throttle(func, 42, options); // $ExpectType DebouncedFunc<(a: number, b: string) => boolean>
_(func).throttle(); // $ExpectType Function<DebouncedFunc<(a: number, b: string) => boolean>>
_(func).throttle(42); // $ExpectType Function<DebouncedFunc<(a: number, b: string) => boolean>>
_(func).throttle(42, options); // $ExpectType Function<DebouncedFunc<(a: number, b: string) => boolean>>
_.chain(func).throttle(); // $ExpectType FunctionChain<DebouncedFunc<(a: number, b: string) => boolean>>
_.chain(func).throttle(42); // $ExpectType FunctionChain<DebouncedFunc<(a: number, b: string) => boolean>>
_.chain(func).throttle(42, options); // $ExpectType FunctionChain<DebouncedFunc<(a: number, b: string) => boolean>>

fp.throttle(42, func); // $ExpectType DebouncedFunc<(a: number, b: string) => boolean>
fp.throttle(42)(func); // $ExpectType DebouncedFunc<(a: number, b: string) => boolean>
_.throttle(func); // $ExpectType DebouncedFuncLeading<(a: number, b: string) => boolean>
_.throttle(func, 42); // $ExpectType DebouncedFuncLeading<(a: number, b: string) => boolean>
_.throttle(func, 42, {}); // $ExpectType DebouncedFuncLeading<(a: number, b: string) => boolean>
_.throttle(func, 42, { leading: true, trailing: false }); // $ExpectType DebouncedFuncLeading<(a: number, b: string) => boolean>
_.throttle(func, 42, { leading: false }); // $ExpectType DebouncedFunc<(a: number, b: string) => boolean>
_.throttle(func, 42, { leading: boolean }); // $ExpectType DebouncedFunc<(a: number, b: string) => boolean>
_.throttle(func, 42, optionsAmbiguous); // $ExpectType DebouncedFunc<(a: number, b: string) => boolean>

_(func).throttle(); // $ExpectType Function<DebouncedFuncLeading<(a: number, b: string) => boolean>>
_(func).throttle(42); // $ExpectType Function<DebouncedFuncLeading<(a: number, b: string) => boolean>>
_(func).throttle(42, {}); // $ExpectType Function<DebouncedFuncLeading<(a: number, b: string) => boolean>>
_(func).throttle(42, { leading: true, trailing: false }); // $ExpectType Function<DebouncedFuncLeading<(a: number, b: string) => boolean>>
_(func).throttle(42, { leading: false }); // $ExpectType Function<DebouncedFunc<(a: number, b: string) => boolean>>
_(func).throttle(42, { leading: boolean }); // $ExpectType Function<DebouncedFunc<(a: number, b: string) => boolean>>
_(func).throttle(42, optionsAmbiguous); // $ExpectType Function<DebouncedFunc<(a: number, b: string) => boolean>>

_.chain(func).throttle(); // $ExpectType FunctionChain<DebouncedFuncLeading<(a: number, b: string) => boolean>>
_.chain(func).throttle(42); // $ExpectType FunctionChain<DebouncedFuncLeading<(a: number, b: string) => boolean>>
_.chain(func).throttle(42, {}); // $ExpectType FunctionChain<DebouncedFuncLeading<(a: number, b: string) => boolean>>
_.chain(func).throttle(42, { leading: true, trailing: false }); // $ExpectType FunctionChain<DebouncedFuncLeading<(a: number, b: string) => boolean>>
_.chain(func).throttle(42, { leading: false }); // $ExpectType FunctionChain<DebouncedFunc<(a: number, b: string) => boolean>>
_.chain(func).throttle(42, { leading: boolean }); // $ExpectType FunctionChain<DebouncedFunc<(a: number, b: string) => boolean>>
_.chain(func).throttle(42, optionsAmbiguous); // $ExpectType FunctionChain<DebouncedFunc<(a: number, b: string) => boolean>>

fp.throttle(42, func); // $ExpectType DebouncedFuncLeading<(a: number, b: string) => boolean>
fp.throttle(42)(func); // $ExpectType DebouncedFuncLeading<(a: number, b: string) => boolean>

// _.throttle treats an explicit `leading: undefined` the same as `leading: false`
const badOptionsLeading: _.ThrottleSettingsLeading = {
// @ts-expect-error explicit undefined is not allowed here
leading: undefined,
};

// any invokation where leading might be set as undefined should return DebouncedFunc, not DebouncedFuncLeading
_.throttle(func, 42, { leading: undefined }); // $ExpectType DebouncedFunc<(a: number, b: string) => boolean>
_.throttle(func, 42, { leading: maybeUndefined }); // $ExpectType DebouncedFunc<(a: number, b: string) => boolean>
_.chain(func).throttle(42, { leading: undefined }); // $ExpectType FunctionChain<DebouncedFunc<(a: number, b: string) => boolean>>
_.chain(func).throttle(42, { leading: maybeUndefined }); // $ExpectType FunctionChain<DebouncedFunc<(a: number, b: string) => boolean>>
_(func).throttle(42, { leading: undefined }); // $ExpectType Function<DebouncedFunc<(a: number, b: string) => boolean>>
_(func).throttle(42, { leading: maybeUndefined }); // $ExpectType Function<DebouncedFunc<(a: number, b: string) => boolean>>
}

// _.unary
Expand Down

0 comments on commit 91003f3

Please sign in to comment.