Repository navigation
Presence of a binding pattern changes inference for callback function parametersΒ #43605
Copy link
Copy link
Labels
BugA bug in TypeScriptA bug in TypeScriptFix AvailableA PR has been opened for this issueA PR has been opened for this issue
Milestone
Description
Bug Report
π Version & Regression Information
This bugs occurs in typescript 4.2.3, 4.2.4 and 4.3.0-beta, I didn't test the older typescripts.
β― Playground Link
Playground link with relevant code
π» Code
// type definitions simplified from `@reduxjs/toolkit`, `react` and `react-redux`
type Dispatch<A = { type: any; [extraProps: string]: any }> = { <T extends A>(action: T): T };
declare function useMemo<T>(factory: () => T, deps: ReadonlyArray<any> | undefined): T;
declare function useDispatch<TDispatch = Dispatch<any>>(): TDispatch;
// IDestructuring & Destructuring
type IFuncs = { readonly [key: string]: (...p: any) => void };
type IDestructuring<T extends IFuncs> = { readonly [key in keyof T]?: (...p: Parameters<T[key]>) => void };
type Destructuring<T extends IFuncs, U extends IDestructuring<T>> = (dispatch: Dispatch<any>, funcs: T) => U;
// functions
const funcs1 = {
funcA: (a: boolean): void => {},
funcB: (b: string, bb: string): void => {},
funcC: (c: number, cc: number, ccc: boolean): void => {},
};
const funcs2 = {
funcD: (d: boolean): void => {},
funcE: (e: string, ee: string): void => {},
funcF: (f: number, ff: number, fff: boolean): void => {},
};
type TFuncs1 = typeof funcs1;
type TFuncs2 = typeof funcs2;
// react hooks
function useReduxDispatch1<T extends IDestructuring<TFuncs1>>(destructuring: Destructuring<TFuncs1, T>): T {
return useMemo(() => ({ ...destructuring(useDispatch(), funcs1) }), []);
}
function useReduxDispatch2<T1 extends IDestructuring<TFuncs1>, T2 extends IDestructuring<TFuncs2>>(
destructuring1: Destructuring<TFuncs1, T1>,
destructuring2: Destructuring<TFuncs2, T2>,
): T1 & T2 {
return useMemo(() => ({ ...destructuring1(useDispatch(), funcs1), ...destructuring2(useDispatch(), funcs2) }), []);
}
// test examples
useReduxDispatch1(
(d, f) => ({ funcA: (...p) => d(f.funcA(...p)), funcC: (...p) => d(f.funcC(...p)) })
);
const _ = useReduxDispatch1(
(d, f) => ({ funcA: (...p) => d(f.funcA(...p)), funcB: (...p) => d(f.funcB(...p)) })
);
const { funcA, funcB, funcC } = useReduxDispatch1(
(d, f) => ({ funcA: (...p) => d(f.funcB(...p)), funcB: (...p) => d(f.funcB(...p)), funcC: (...p) => d(f.funcC(...p)) })
);
useReduxDispatch2(
(d, f) => ({ funcB: (...p) => d(f.funcB(...p)), funcC: (...p) => d(f.funcC(...p)) }),
(d, f) => ({ funcD: (...p) => d(f.funcD(...p)), funcF: (...p) => d(f.funcF(...p)) }),
);
const { funcA: _funcA, funcC: _funcC, funcE, funcF } = useReduxDispatch2(
(d, f) => ({ funcA: (...p) => d(f.funcA(...p)), funcC: (...p) => d(f.funcC(...p)) }),
(d, f) => ({ funcE: (...p) => d(f.funcE(...p)), funcF: (...p) => d(f.funcF(...p)) }),
);π Actual behavior
In the function call on line 55, typescript cannot infer the parameters of array functions funcA, funcB and funcC, actually it thinks the parameters ...args is any[].
But this bugs doesn't occur in function calls on line 46, 50, 58 and 63.
π Expected behavior
No compilation errors.
Typescript should infer the parameters ...args of array function funcA, funcB and funcC correctly.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
BugA bug in TypeScriptA bug in TypeScriptFix AvailableA PR has been opened for this issueA PR has been opened for this issue
Activity
andrewbranch commentedon Apr 9, 2021
Slightly reduced, cleaned up, and emphasizing the nature of the bug: playground
[-]Typescript fails to infer the parameters of functions[/-][+]Presence of a binding pattern changes inference for callback function parameters[/+]andrewbranch commentedon Jul 26, 2021
Moving to 4.5 since the fix will probably be a breaking change
3 remaining items
typescript-bot commentedon Sep 7, 2021
This issue has been marked 'Working as Intended' and has seen no recent activity. It has been automatically closed for house-keeping purposes.