我正在尝试创建一个可重复使用的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领域如何称呼这种情况,所以我希望有人可以向我解释,是否以及如何实现我想要的。
非常感谢您。
答案 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
的类型。所有其他变量的类型也是如此。