Improve [react] useReducer type inference #63607
Replies: 5 comments 2 replies
-
|
Thanks for the discussion about "react", some useful links for everyone: Pinging the DT module owners: @johnnyreilly, @bbenezech, @pzavolinsky, @ericanderson, @DovydasNavickas, @theruther4d, @guilhermehubner, @ferdaber, @jrakotoharisoa, @pascaloliv, @Hotell, @franklixuefei, @Jessidhia, @saranshkataria, @lukyth, @eps1lon, @zieka, @dancerphil, @dimitropoulos, @disjukr, @vhfmag, @hellatan, @priyanshurav, @Semigradsky. |
Beta Was this translation helpful? Give feedback.
-
|
Looks like this may have been a TODO already? DefinitelyTyped/types/react/index.d.ts Line 1017 in e358cde // NOTE: without the ReducerState indirection, TypeScript would reduce S to be the most common
// supertype between the reducer's return type and the initialState (or the initializer's return type),
// which would prevent autocompletion from ever working.
// TODO: double-check if this weird overload logic is necessary. It is possible it's either a bug
// in older versions, or a regression in newer versions of the typescript completion service.
function useReducer<R extends Reducer<any, any>>(
reducer: R,
initialState: ReducerState<R>,
initializer?: undefined
): [ReducerState<R>, Dispatch<ReducerAction<R>>]; |
Beta Was this translation helpful? Give feedback.
-
|
The concern in that comment seems to be around autocompletion with the returned state object. I updated my repro to be an object with property When I try to return an extra property, TypeScript doesn't warn me. This is normal for TypeScript; the new object can be cast to the same type as const [state, dispatch] = useReducer(
(state, payload: number): {count: number} => ({
...state,
count: state.count + payload,
extraProp: 'asdf', // Type '{ count: number; extraProp: string; }' is not assignable to type '{ count: number; }'. Object literal may only specify known properties, and 'extraProp' does not exist in type '{ count: number; }'.(2322)
}),
{ count: 0 }
);However, I don't see the mentioned issue of TypeScript creating a superset state. When I mouse over the |
Beta Was this translation helpful? Give feedback.
-
|
I can make a PR for this if nobody has a problem. I'd just change that last overload to not have the 3rd argument |
Beta Was this translation helpful? Give feedback.
-
|
PR: #64412 |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
The problem
useReducerdoes not infer thestateparameter from the initial state passed in:This should infer
stateasnumber, but it makes it an implicitanyinstead.The cause of the problem
The 3rd parameter of
useReduceris aninitargument that returns the type thatstateshould be inferred as. Unfortunately, since the 3rd parameter is optional instead of defined with overloads, when you don't supply that parameter TypeScript has no way to know whatstateshould be.The solution
There should be an overload that doesn't have the 3rd parameter and infers
stateas the same exact type as the 2nd argument.Repro with solution
https://stackblitz.com/edit/react-ts-gy5gv6?file=App.tsx
Beta Was this translation helpful? Give feedback.
All reactions