从类型声明快速掌握React Hook in TS

1,218 阅读1分钟

useReducer中学习查看源码类型声明(Typescipt)

  • 如果设计一个useReducer,应当确保哪些数据的类型安全?
    • State:应当让状态保持类型一致
    • Action:应当规范Action类型
  • 学习useReducer类型声明
    • 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>>];
      
    • 可见参数reducer的类型是Reducer<any, any>,并且返回的类型会被推断为ReducerState<R>

      • 我们根据api的设计可以合理地猜测:返回的tuple第一个参数必然是State的类型。
      • 观察返回值类型定义,可以确定ReducerState<R>的操作是根据R (extends Reducer<any, any>)返回了State的类型,这样可以保证返回类型的确定性。
    • State的类型从哪里来?

      • 进一步进入Reducer<any any>的声明

        • type Reducer<S, A> = (prevState: S, action: A) => S;
          
        • 不难看出,Reducer就是典型的Reducer函数的类型结构接收State(S)类型和Action(A)类型,返回State类型
        • 同时,我们可以通过ReturnType<Reducer<S, A>>来获取State的类型,这让useReducer获取State类型的时机下放到了Reducer函数的泛型中
      • 再进入ReducerState<R>来验证我们的猜想

        • type ReducerState<R extends Reducer<any, any>> = R extends Reducer<infer S, any> ? S : never;
          
        • 源码的实现并不是从ReturnType中获取,而是直接获取了Reducer函数的state参数的类型State,殊途同归。
  • 总结
    • useReducer的泛型是这样的:useReducer(reducer, initialState)中的reducer函数会预定义好自己的泛型(用于规范stateaction的类型),useReducer会通过infer来获取reducerstate的类型,用来规范返回值的类型。