이 연습에서는 useReducer와 Typescript를 사용하여 reducer 함수를 타입지정하는 방법을 살펴보겠습니다.
useReducer 훅은 state와 action이라는 두 개의 인수를 받는 reducer 함수를 받습니다.
reducer의 목적은 제공된 action.type에 따라 새로운 상태를 반환하는 것입니다.
여기에는 state.count를 얼마만큼 증가시키는 add와 action.add에 대한 액션과 state.count를 action.substact만큼 감소시키는 subtract에 대한 액션이 있습니다.
const reducer = (state: unknown, action: unknown) => {
switch (action.type) {
case "add":
return { count: state.count + action.amount };
case "subtract":
return { count: state.count - action.amount };
default:
throw new Error();
}
};
reducer 함수는 작동할 수 있지만 타입핑에 문제가 있습니다.
초기 상태가 함수에 전달될 때 state.count가 any로 타입지정됩니다.
const reducer = (state: unknown, action: unknown) => {
switch (action.type) {
case "add":
return { count: state.count + action.amount };
case "subtract":
return { count: state.count - action.amount };
default:
throw new Error();
}
};
또한 테스트 및 dispatch 호출에서 몇 가지 오류가 발생하고 자동 완성 기능이 작동하지 않습니다.
type tests = [Expect<Equal<typeof state.count, number>>];
dispatch({ type: "add", amount: 1 });
// @ts-expect-error
dispatch({ type: "subtract" });
// @ts-expect-error
dispatch({ type: "add" });
// @ts-expect-error
dispatch({ type: "subtract", amount: "123" });
reducer 함수를 올바르게 작동시키기 위해 reducer 함수를 타입지정 하는 방법을 알아내는 것이 과제입니다.
세가지 해결책이 있지만 대부분 타입을 재구성하는 것과 관련이 있습니다. (그리고 한 해결책이 다른 해결책보다 더 매력적일 수 있습니다.)
힌트: 솔루션에 접근하기 위한 아이디어를 얻으려면 Discriminated Unions 에 대한 도움말을 참조하세요
my solution