이 연습에서는 useReducer와 Typescript를 사용하여 reducer 함수를 타입지정하는 방법을 살펴보겠습니다.

useReducer 훅은 stateaction이라는 두 개의 인수를 받는 reducer 함수를 받습니다.

reducer의 목적은 제공된 action.type에 따라 새로운 상태를 반환하는 것입니다.

여기에는 state.count를 얼마만큼 증가시키는 addaction.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" });

Challenge

reducer 함수를 올바르게 작동시키기 위해 reducer 함수를 타입지정 하는 방법을 알아내는 것이 과제입니다.

세가지 해결책이 있지만 대부분 타입을 재구성하는 것과 관련이 있습니다. (그리고 한 해결책이 다른 해결책보다 더 매력적일 수 있습니다.)

힌트: 솔루션에 접근하기 위한 아이디어를 얻으려면 Discriminated Unions 에 대한 도움말을 참조하세요

my solution