useReducer 사용시 dispatch 함수에 generic으로 action 타입을 넘겨줄 때 에러가 발생합니다.
746
작성한 질문수 52
제로초님 안녕하세요.
TicTacToe 코드에서 질문이 있습니다.
const TicTacToe = () => {
const [state, dispatch] = useReducer<Reducer<ReducerState, ReducerActions>>(reducer, initialState);
...
if (win) {
dispatch<SetWinnerAction>({ type: SET_WINNER, winner: turn });
dispatch({ type: RESET_GAME});
} ...
}
위의 코드에서 SET_WINNER action을 dispatch 하는 부분에서처럼 dispatch에 generic으로 SetWinnerAction 인터페이스를 줘서 표기를 확실히하고 싶은데, 저렇게 하면 SetWinnerAction 부분에서 타입에러가 나면서 "Expected 0 arguments, but got 1" 이라는 메시지가 뜹니다. 현재 웹스톰 사용 중인데, type definition을 따라가보면 useReducer가
function useReducer<R extends ReducerWithoutAction<any>, I>(
reducer: R,
initializerArg: I,
initializer: (arg: I) => ReducerStateWithoutAction<R>
): [ReducerStateWithoutAction<R>, DispatchWithoutAction];
여기에 매칭이 되더라고요.
vscode로 보면
여기에 매칭이 되기는 하는데 어쨌든 IDE에나 컴파일해봤을 때나 같은 에러가 뜹니다.
이건 어떤 식으로 해결할 수 있을까요?
감사합니다.
답변 2
0
제로초님 안녕하세요. 빠른 답변 감사합니다.
function useReducer<R extends ReducerWithoutAction<any>, I>(
reducer: R,
initializerArg: I,
initializer: (arg: I) => ReducerStateWithoutAction<R>
): [ReducerStateWithoutAction<R>, DispatchWithoutAction];
/**
* An alternative to `useState`.
*
* `useReducer` is usually preferable to `useState` when you have complex state logic that involves
* multiple sub-values. It also lets you optimize performance for components that trigger deep
* updates because you can pass `dispatch` down instead of callbacks.
*
* @version 16.8.0
* @see https://reactjs.org/docs/hooks-reference.html#usereducer
*/
// overload where dispatch could accept 0 arguments.
function useReducer<R extends ReducerWithoutAction<any>>(
reducer: R,
initializerArg: ReducerStateWithoutAction<R>,
initializer?: undefined
): [ReducerStateWithoutAction<R>, DispatchWithoutAction];
/**
* An alternative to `useState`.
*
* `useReducer` is usually preferable to `useState` when you have complex state logic that involves
* multiple sub-values. It also lets you optimize performance for components that trigger deep
* updates because you can pass `dispatch` down instead of callbacks.
*
* @version 16.8.0
* @see https://reactjs.org/docs/hooks-reference.html#usereducer
*/
// overload where "I" may be a subset of ReducerState<R>; used to provide autocompletion.
// If "I" matches ReducerState<R> exactly then the last overload will allow initializer to be omitted.
// the last overload effectively behaves as if the identity function (x => x) is the initializer.
function useReducer<R extends Reducer<any, any>, I>(
reducer: R,
initializerArg: I & ReducerState<R>,
initializer: (arg: I & ReducerState<R>) => ReducerState<R>
): [ReducerState<R>, Dispatch<ReducerAction<R>>];
/**
* An alternative to `useState`.
*
* `useReducer` is usually preferable to `useState` when you have complex state logic that involves
* multiple sub-values. It also lets you optimize performance for components that trigger deep
* updates because you can pass `dispatch` down instead of callbacks.
*
* @version 16.8.0
* @see https://reactjs.org/docs/hooks-reference.html#usereducer
*/
// overload for free "I"; all goes as long as initializer converts it into "ReducerState<R>".
function useReducer<R extends Reducer<any, any>, I>(
reducer: R,
initializerArg: I,
initializer: (arg: I) => ReducerState<R>
): [ReducerState<R>, Dispatch<ReducerAction<R>>];
/**
* An alternative to `useState`.
*
* `useReducer` is usually preferable to `useState` when you have complex state logic that involves
* multiple sub-values. It also lets you optimize performance for components that trigger deep
* updates because you can pass `dispatch` down instead of callbacks.
*
* @version 16.8.0
* @see https://reactjs.org/docs/hooks-reference.html#usereducer
*/
// I'm not sure if I keep this 2-ary or if I make it (2,3)-ary; it's currently (2,3)-ary.
// The Flow types do have an overload for 3-ary invocation with undefined initializer.
// 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>>];
위의 파일이 제가 현재 사용하고 있는 버전의 useReducer가 정의되어 있는 react의 index.d.ts 파일인데요.
리턴값들을 보시면 첫 번째와 두 번째 정의의 리턴값은 DispatchWithoutAction을 리턴하지만, 나머지 3, 4, 5번째의 리턴값의 dispatch 함수는 Dispatch<ReducerAction<R>> 입니다. 이 경우는 action을 받을 수 있는 거 아닌가 생각했는데요.
리액트 노드버드 강좌 들을 때 제 나름대로 타이핑할 때 dispatch 함수에 제네릭을 줬던 기억이 나서 확인해보니 useDispatch는 react-redux의 index.d.ts 파일에
export function useDispatch<TDispatch = Dispatch<any>>(): TDispatch;
export function useDispatch<A extends Action = AnyAction>(): Dispatch<A>;
이렇게 정의되어 있더라고요. useDispatch의 Dispatch<any>나 위의 useReducer의 Dispatch<ReducerAction<R>>이나 마찬가지인 것 같아서 그렇게 사용할 수 있지 않을까 생각했습니다. 그래서 위의 useReducer 타입 정의 중에서 마지막 것에 맞춰보려고 useReducer의 generic을 이래저래 다르게 줘봐도 잘 안 되더라고요. 오버로딩 가능한 것들 중에서 엉뚱한 것을 가져와서 에러가 나는 경우에는 타입을 맞춰보라고 강의 중에 말씀하셨던 것 같은데, 이 경우는 어떻게 해결할 수 있을지 궁금하네요. 감사합니다.
0
저 코드에 따르면 dispatch는 Dispatch<ReducerAction<R>>인데 이미 <R>이 정해져있습니다. 저희가 useReducer할 때 제네릭으로 넣었습니다(Reducer<ReducerState, ReducerActions>). ReducerAction<R>은 그 R(Reducer)에서 ReducerActions를 꺼내는 것이고요. 따라서 dispatch에는 이미 ReducerActions가 적용되어 있습니다. 그래서 dispatch는 아무런 제네릭을 받지 못합니다.
0
제네릭은 마음대로 쓸 수 없습니다. 이미 useReducer을 호출할 때 dispatch의 매개변수가 ReducerActions로 결정되었습니다.
dispatch({ type: SET_WINNER, winner: turn });
dispatch는 제네릭을 받지 않습니다.
express response 타입
0
210
1
createRoot
0
285
1
babel-loader질문입니다! 왜쓰는지 궁금합니다!
0
685
1
undefined 처리
0
493
1
compilerOptions lib 관련
0
329
1
event type 찾기
0
324
1
정확한 type vs 가독성
0
292
1
useRef에 대해 질문드립니다.
0
305
1
tsx파일에서 에러 표시
0
863
1
Props type 질문드립니다.
0
227
1
webpack.config.ts/ Could not find a declaration file for module '@pmmmwh/react-refresh-webpack-plugin'.
0
589
1
18버전에서의 ReactDOM.render
1
658
1
깃허브에 react-router@6 업데이트 해주신 코드 질문드립니다.
0
293
1
2강 끝말잇기 npx webpack 오류가 질의사항
0
408
1
Property 'render' does not exist on type 'IntrinsicAttributes & (PathRouteProps | LayoutRouteProps | IndexRouteProps)'.
0
716
1
webpack.config.ts import 할 때 에러좀 봐주세요!!
0
307
1
React.FC에 대해 궁금합니다.
0
701
1
가위바위보 interval 타입과 이벤트타입에 관한질문
0
343
1
npm run dev 실행은 성공적으로 되는데
0
677
2
redux 유료강좌를 듣고 와야 되는지 여쭈어보려고 합니다.
0
320
1
git 내용과 강의 내용이 달라서 여쭈어봅니다.
0
220
1
Ball.tsx 타이핑
0
322
2
react-router 버젼 업그레이드 변경사항 문의
0
285
2
리액트 타입스크립트 공식문서
0
337
1





