为何useState<string>()不会触发TypeScript错误?
useState<string>()合法但useState<string>(undefined)不合法? 先看两个代码示例:
- 合法代码:
const [foo, setFoo] = useState<string>()
- 不合法代码:
const [boo, setBoo] = useState<string>(undefined)
报错信息:
Argument of type 'undefined' is not assignable to parameter of type 'string | (() => string)'
你说的没错,运行时这两种写法的行为确实完全一致,无参数的useState内部就是把初始状态设为undefined。但TypeScript报错是因为React给useState定义的类型重载逻辑导致的。
React的useState有两个核心类型重载(简化后):
无参数的情况:
function useState<S>(): [S | undefined, Dispatch<SetStateAction<S | undefined>>]
当你不传参数时,TS会匹配这个重载,自动把状态类型推断为S | undefined(这里S是你指定的string,所以状态类型是string | undefined),完全符合类型要求。带初始值的情况:
function useState<S>(initialState: S | (() => S)): [S, Dispatch<SetStateAction<S>>]
当你传undefined作为参数时,TS会匹配这个重载,此时要求初始值必须是S(也就是string)或者返回S的函数,但undefined不属于string类型,所以触发类型错误。
简单说,TS不会自动把“不传参数”和“传undefined”划等号,而是通过不同的重载分支来处理这两种场景,这是类型系统设计上的区分,和运行时行为无关。
内容的提问来源于stack exchange,提问作者Steve Bennett

