Typescript中如何解决多类型值React.useState的类型不匹配报错
报错原因
该错误是TypeScript函数参数逆变特性导致的:你声明的setValue是仅能处理number类型更新的调度器,而Select组件要求传入的调度器可以处理string | number两种类型的更新。TypeScript判定如果将仅支持number的调度器传给允许接收string的组件,组件内部如果传入字符串值会触发类型异常,因此抛出了不匹配错误。
解决方案(按适用场景排序)
方案1:直接给useState指定联合类型(最省事,适合当前场景确实需要同时支持两种类型的情况)
在声明state的时候显式指定类型为number | string,让setValue的类型和组件要求匹配:
// 显式指定泛型参数为联合类型 const [value, setValue] = React.useState<number | string>(0); <Select selectValue={setValue} />
方案2:给Select组件加泛型支持(推荐,适合组件要适配多种业务场景的情况)
如果你的Select组件在不同业务场景下可能仅需支持number、仅需支持string,或者需要支持联合类型,可以把组件props改成泛型定义,避免不必要的类型放宽:
// 定义泛型props,默认值为string | number兼容旧用法 export interface SelectProps<T = string | number> { selectValue: React.Dispatch<React.SetStateAction<T>>; // 其他props定义 } // 组件声明时加上泛型约束 const Select = <T extends string | number>(props: SelectProps<T>) => { // 组件内部逻辑 }
调用时根据你的实际需求指定泛型即可:
const [value, setValue] = React.useState(0); // 指定当前组件实例仅处理number类型 <Select<number> selectValue={setValue} />
方案3:包装一层转换函数(适合父组件state不需要兼容string类型的情况)
如果你确定父组件的state只需要存number类型,不需要支持string,可以在父组件包一层转换函数,做类型兼容处理:
const [value, setValue] = React.useState(0); // 接收联合类型参数,转成number再更新父组件state const handleSelect = (val: string | number) => { setValue(Number(val)); } <Select selectValue={handleSelect} />
内容的提问来源于stack exchange,提问作者ANTARES_SEO
相关产品推荐
相关产品推荐

