You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

useLocalStorage Hook的setState回调类型为any,如何让其识别正确类型?

泛型useLocalStorage Hook的TypeScript类型推断问题

问题原因

你当前的useLocalStorage中定义的setValue只接受T类型的直接值,但React的状态更新器(比如useState返回的setter)本身支持两种更新方式:

  • 直接传入新状态值
  • 传入一个回调函数,接收当前状态作为参数并返回新状态

而你的setValue类型定义没有覆盖第二种函数式更新的场景,所以当你传入回调函数时,TypeScript无法推断回调参数的类型,只能默认是any。

解决方法

修改setValue的类型,让它支持React状态更新器的两种形式——可以直接复用React内置的SetStateAction<T>类型,它已经封装了「值或返回值的函数」的联合类型。

修改后的useLocalStorage Hook代码

import { useState, useEffect, SetStateAction, Dispatch } from "react"

export default function useLocalStorage<T>(key: string, initialValue: T) {
  const [storedValue, setStoredValue] = useState<T>(() => {
    const item = localStorage.getItem(key)
    return item ? JSON.parse(item) : initialValue
  })

  useEffect(() => {
    localStorage.setItem(key, JSON.stringify(storedValue))
  }, [key, storedValue])

  // 用Dispatch<SetStateAction<T>>定义setValue的类型,兼容两种更新方式
  const setValue: Dispatch<SetStateAction<T>> = (value) => {
    setStoredValue(value)
  }

  return [storedValue, setValue] as const
}

验证效果

现在调用setCurrentNote使用函数式更新时,回调参数currentNote会被正确推断为Note类型:

setCurrentNote(currentNote => ({ ...currentNote, [property]: newValue }))

补充说明

如果你不想依赖React的内置类型,也可以自行定义等效的联合类型:

type SetStateAction<T> = T | ((prevState: T) => T)
type Dispatch<T> = (value: T) => void

替换后效果与使用React内置类型完全一致。

内容的提问来源于stack exchange,提问作者David Martin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 14:02:35