【问题标题】:Parsing error trying to add TypeScript to useReducer hook?尝试将 TypeScript 添加到 useReducer 钩子时解析错误?
【发布时间】:2019-07-02 07:06:35
【问题描述】:

我正在尝试了解如何将 TypeScript 与 useReducer 挂钩一起使用。这是一个使用常规 JavaScript 的简单计数器:

function reducer(state, action) {
  switch (action.type) {
    case "+":
      return { ...state, no: state.no + 1}
    case "-":
      return { ...state, no: state.no - 1}
    default:
      throw new Error("All conditions missed");
  }
}

function App() {

  const [state, dispatch] = React.useReducer(reducer, {no: 1})

  return (
    <div className="App">
      <h1>{state.no}</h1>
      <button type="button" onClick={()=>dispatch({type: "-"})}>-</button>
      <button type="button" onClick={()=>dispatch({type: "+"})}>+</button>
    </div>
  );
}

https://codesandbox.io/s/zealous-austin-eog2p

我尝试添加类型,但出现解析错误:

interface IState {
  no: string;
}

function reducer(state: IState[], action) {
  switch (action.type) {
    case "+":
      return { ...state, no: state.no + 1}
    case "-":
      return { ...state, no: state.no - 1}
    default:
      throw new Error("All conditions missed");
  }
}

function App() {

  const [state, dispatch] = React.useReducer(reducer, {no: 1}: IState[])

  return (
    <div className="App">
      <h1>{state.no}</h1>
      <button type="button" onClick={()=>dispatch({type: "-"})}>-</button>
      <button type="button" onClick={()=>dispatch({type: "+"})}>+</button>
    </div>
  );
}

https://codesandbox.io/s/patient-forest-1gp88

【问题讨论】:

标签: reactjs typescript


【解决方案1】:

供参考,useReducer() 的签名是

type Reducer<S, A> = (prevState: S, action: A) => S;
type ReducerState<R extends Reducer<any, any>> = R extends Reducer<infer S, any> ? S : never;
type ReducerAction<R extends Reducer<any, any>> = R extends Reducer<any, infer A> ? A : never;
type Dispatch<A> = (value: A) => void;
function useReducer<R extends Reducer<any, any>>(
  reducer: R,
  initialState: ReducerState<R>,
  initializer?: undefined,
): [ReducerState<R>, Dispatch<ReducerAction<R>>];

看起来像

interface IState {
  no: number;
}

const reducer: React.Reducer<IState, any> = (state: IState, action) => {
  switch (action.type) {
    case "+":
      return { ...state, no: state.no + 1 };
    case "-":
      return { ...state, no: state.no - 1 };
    default:
      throw new Error("All conditions missed");
  }
};

// ...
const [state, dispatch] = React.useReducer(reducer, { no: 1 });

解析、类型检查和运行良好——与您的版本不同:

  • 接口中的no 是一个数字(需要使reducer 中的算术有意义,以及初始状态)。
  • reducer 是一个显式类型的箭头函数。

【讨论】:

  • reducer 需要是箭头函数吗?如果不是,我将无法正常工作:function reducer: React.Reducer (state, action) {
  • 老实说,我不确定如何显式键入命名函数。 :D
  • 如果你想使用 TypeScript 和 useReducer,这是正确的答案!
猜你喜欢
  • 1970-01-01
  • 2020-11-05
  • 2023-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多