TypeScript中如何为useUndo Hook参数定义类型,匹配useState值与setter?
问题:React自定义Hook useUndo的类型定义优化
我正在React应用中编写一个支持撤销/重做(undo/redo)的自定义Hook useUndo,希望它能接收一组由useState返回的状态值与设置器对。调用方式如下:
const myDogsState = useState<Dog[]>([]); const [myDogs, setMyDogs] = myDogsState; const areDogsSleepingState = useState(false); const [areDogsSleeping, setAreDogsSleeping] = areDogsSleepingState; const foo = useUndo([myDogsState, areDogsSleepingState]);
当前的问题是无法为useUndo的参数正确定义类型,我希望确保每个状态值与其对应的设置器类型一致。目前的实现如下:
type StateItem<Type> = [Type, React.Dispatch<React.SetStateAction<Type>>]; const useUndo = (items: StateItem<any>[]) => { // 撤销/重做逻辑 };
但使用any类型并不合适,想知道能否让TypeScript自动推断第一个元素的类型并应用到React.Dispatch<React.SetStateAction<Type>>,或者有没有更简便的实现方式?
解决方案
你可以通过泛型元组+映射类型让TypeScript自动推断每个状态项的类型,完全避免any的使用,同时保证状态值和设置器的类型严格匹配:
方式一:可变参数泛型自动推断
import { useState, Dispatch, SetStateAction } from 'react'; type StateItem<T> = [T, Dispatch<SetStateAction<T>>]; // 用可变参数泛型让TS自动识别传入的每个StateItem类型 const useUndo = <T extends StateItem<any>[]>(items: [...T]) => { // 示例:访问第一个状态时,类型会被自动推断为Dog[](对应你的调用场景) const firstState = items[0][0]; // 编写你的撤销/重做核心逻辑... return { // 可返回封装后的状态、设置器,以及undo/redo控制方法 }; };
方式二:映射类型明确约束
如果需要更明确的类型约束,可通过映射类型确保每个元素都是对应的StateItem:
import { useState, Dispatch, SetStateAction } from 'react'; type StateItem<T> = [T, Dispatch<SetStateAction<T>>]; // 泛型States代表所有状态值的类型数组,映射为对应的StateItem数组 const useUndo = <States extends any[]>( items: { [K in keyof States]: StateItem<States[K]> } ) => { // 实现逻辑... };
效果验证
当你按示例调用useUndo([myDogsState, areDogsSleepingState])时,TypeScript会自动完成类型推断:
- 第一个元素类型为
StateItem<Dog[]> - 第二个元素类型为
StateItem<boolean>
全程无需手动指定类型,既保证了类型安全,又避免了any带来的潜在问题。
内容的提问来源于stack exchange,提问作者Robo Robok
相关产品推荐
相关产品推荐

