打字稿动态useReducer

时间:2019-08-24 09:38:29

标签: typescript

我正在尝试创建一个可重复使用的useReducer钩子。

这是我当前的代码:

type State<T> = {
  data?: T
  isLoading: boolean
  error?: string
}

type Action<T> =
  | { type: "request" }
  | { type: "success"; results: T }
  | { type: "failure"; error: string }

function reducer<T>(state: State<T>, action: Action<T>): State<T> {
  switch (action.type) {
    case "request":
      return { isLoading: true }
    case "success":
      return { isLoading: false, data: action.results }
    case "failure":
      return { isLoading: false, error: action.error }
  }
}

export function useFetchState<T>() {
 return useReducer(reducer<T>, {isLoading: false});
}

如您所见,该钩子应该用于保持获取状态,但是数据应该是动态的,以便可以在不同的上下文中使用:

const [videoFetch, dispatchVideo] = useFetchState<Video[]>()
const [userFetch, dispatchUser] = useFetchState<User[]>()

我的问题是,由于{em> Error:(26,20)TS2345,表达式reducer<T>失败了:类型'boolean'的参数不能分配给类型'Reducer'的参数。

,但未指定T,则数据类型未知。

我不确定在TypeScript领域如何称呼这种情况,所以我希望有人可以向我解释,是否以及如何实现我想要的。

非常感谢您。

1 个答案:

答案 0 :(得分:4)

reducer<T>在语法上不是无效的。 reducer只是reducer。没有像reducer<T>这样的东西。编译器将其理解为reducer < T >(比较运算符),它认为以表达式形式完成时很可能是布尔值。这就是为什么它抱怨“类型boolean的参数不能分配给类型Reducer的参数”的原因-编译器在值的位置发现布尔值或布尔值可疑对象类型Reducer(只是您的reducer变量)应该出现。

不传递通用参数也是错误的。例如,videoFetch的类型推断将是错误的:videoFetch被推断为State<{}>(在最新版本中可能为State<unknown>。我不确定100%这个)。

那么通用参数T实际上应该在哪里?请注意,类型推断实际上发生在useReducer上。因此,我们只需要手动提供useReducer的正确类型参数:

export function useFetchState<T>() {
  return useReducer<Reducer<State<T>, Action<T>>>(reducer, { isLoading: false });
}

在这种情况下,您可以检查是否正确推断出videoFetch的类型。所有其他变量的类型也是如此。