이 연습에서는 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