TypeScript中useState泛型定义里Dispatch<SetStateAction<S>>解析
深入理解useState泛型定义中的Dispatch<SetStateAction>
先明确你贴出的useState泛型定义:
function useState<S>(initialState: S | (() => S)): [S, Dispatch<SetStateAction<S>>];
1. Dispatch是什么
Dispatch是一个函数类型别名,它的作用是定义「触发状态更新的函数」的类型规范。简单说,它规定了:这个更新函数接收一个符合特定类型的参数,执行状态更新操作,没有返回值。
它的底层定义大概是这样:
type Dispatch<A> = (value: A) => void;
这里的A就是传入的动作类型,对应到useState里就是SetStateAction<S>。
2. SetStateAction的作用
SetStateAction是TypeScript为useState更新参数定义的联合类型,本质是:
type SetStateAction<S> = S | ((prevState: S) => S);
它直接对应了日常使用useState更新状态的两种方式:
- 直接传入新的状态值(类型为S),比如
setCount(5) - 传入一个回调函数,接收当前旧状态prevState,返回新的状态值(类型也为S),比如
setCount(prev => prev + 1)
3. 两者结合的意义
Dispatch<SetStateAction>就是把上面两个部分组合起来,给useState返回的更新函数做了明确的类型约束:
这个更新函数必须接收一个「要么是状态值S、要么是基于旧状态计算新状态的函数」的参数,然后执行状态更新,且没有返回值。
举个实际例子:
// 定义一个字符串类型的状态 const [name, setName] = useState<string>('Alice');
这里的setName就是Dispatch<SetStateAction<string>>类型,所以:
- 合法用法:
setName('Bob')(直接传字符串,符合S类型) - 合法用法:
setName(prevName => prevName.toUpperCase())(传回调函数,接收旧字符串返回新字符串) - 不合法用法:
setName(123)(类型不匹配,123不是string类型)
这样的类型约束能帮我们在写代码时提前发现类型错误,避免把不符合状态类型的值传入更新函数。
内容的提问来源于stack exchange,提问作者j obe
相关产品推荐
相关产品推荐

