-
Notifications
You must be signed in to change notification settings - Fork 46
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Typescript: Selector type does not handle additional arguments #59
Comments
Hi @dahannes, I had a look to the typing declaration file and the proposed solution. I'll open PR to try it out. This library's typings were written from Greetings! |
I see that the typing error is related to the generic types used in the example: And the error pops up when using What's the reason for having them in the selector declaration? It seems to me that they are not actually used. |
@toomuchdesign Thanks for getting back to me. I have not used reselect before but I see that it behaves the same in that regard. Maybe I am understanding sth wrong, but I would like to pass the types to the createCachedSelector function once and not repeat the typings on every line. If I do so I get implicit any's for all arguments. That could be fixed by changing the type as originally proposed to Anyhow that's actually not an ideal solution since it will just make the arguments explicit any's. With the current typings it only expects state when it should actually show the types of the 3 arguments of the resolver function and the return type. I will see if I can come up with a solution for it during the week. |
I can clearly see what you are trying to achieve here but unfortunately, the limitations of current typings do not allow us to do it. First of all, the root cause of the error you see (implicit any) is that the typings do not support a dynamic number of arguments in the selector function. Only the first two arguments (see generic arguments It could be fixed by using the new feature of TypeScript 3.0 called Generic rest parameters, so that we could do something like this: Alternatively, you can avoid explicit typing by using helper functions, for example: const selectArgument1 = <T>(arg1: T): T => arg1;
const selectArgument2 = <T>(arg1: any, arg2: T): T => arg2;
const selectArgument3 = <T>(arg1: any, arg2: any, arg3: T): T => arg3;
const selectArgument4 = <T>(arg1: any, arg2: any, arg3: any, arg4: T): T => arg4;
const selector = createCachedSelector(
selectArgument2,
selectArgument3,
selectArgument4,
(arg1: string, arg2: number, arg3: boolean) => compute(arg1, arg2, arg3)
)(selectArgument2); So in general, following FP style to compose a selector rather than create a new one will reduce typings. I've successfully used such approach in the past and it helps make some of the most annoying cases less annoying. Another solution would be to combine all the extra arguments into only one extra argument |
Thanks @xsburg, the forked typings work pretty well already. Only one problem remains: When I now call the selector function I get the correct types, but not the argument names. Instead it just requests But that's probably the best we can get atm I guess. |
@dahannes, that's one of the issues and also the reason why I normally redefine the type of the resulting selector explicitly, so that I have meaningful names. Sadly, the more concerning problem is that you cannot specify selector functions without unnecessary arguments with these new typings: const selector = createCachedSelector(
(state: State, arg1: string) => arg1, // all OK
(state: State, arg1: string, arg2: number) => arg2, // Error, type inference assumed the selector signature to be "(state: State, arg1: string)" and doesn't allow "arg2".
(state: State, arg1: string, arg2: number, arg3: boolean) => arg3, // Same problem
(arg1, arg2, arg3) => compute(arg1, arg2, arg3)
)((state: State) => state.foo); So basically, TS wrongly guesses the signature of the selector based on the first selector function, which is wrong in this case, and as a result, this quite common scenario falls apart. On another hand, you are free to use these typings locally in your projects while they are still not merged, if this problem is unimportant. |
Hello! Any updates on this? Is there a workaround? |
Do you want to request a feature or report a bug?
bug
What is the current behaviour?
Passing types to the example with multiple arguments from the docs leads to type errors.
What is the expected behaviour?
No type errors.
Steps to Reproduce the Problem
Assign ts types to createCachedSelector, like:
Manually changing the Selector type from
export type Selector<S, R> = (state: S) => R;
to
export type Selector<S, R> = (state: S ,...args: any[]) => R;
would fix the issue.
The text was updated successfully, but these errors were encountered: