React TypeScript泛型Hook中如何约束类型参数解决setFieldValue报错?
解决Formik泛型Hook中setFieldValue的类型不兼容问题
问题描述
需要实现一个泛型Hook,返回用于清除过滤值的函数,仅传入类型参数FilterParams(结构与示例中的SomeFilterParams一致)。但TypeScript对setFieldValue的inputName参数报错,错误信息:
Argument of type 'string | number | symbol' is not assignable to parameter of type 'string'. Type 'number' is not assignable to type 'string'.ts(2345)
原Hook及用法代码:
//... export const useBuildClearValue = <FilterParams>() => { const { setFieldValue, } = useFormikContext(); const buildClearValue = useCallback((inputName: keyof FilterParams) => { return () => { setFieldValue(inputName, null); // 报错位置 }; }, [ setFieldValue, ]); return buildClearValue; }; //... USAGE type SomeFilterParams = { name?: string; status?: string; } const buildClearValue = useBuildClearValue<SomeFilterParams>();
解决方案
通过泛型约束强制FilterParams的键为字符串类型,值为可选字符串类型,同时配合类型断言消除TypeScript的歧义判断。
修改后的Hook代码
// 约束FilterParams为键是string、值是可选string的对象 export const useBuildClearValue = <FilterParams extends Record<string, string | undefined>>() => { const { setFieldValue } = useFormikContext(); const buildClearValue = useCallback((inputName: keyof FilterParams) => { return () => { // 类型断言确保inputName符合setFieldValue的参数类型要求 setFieldValue(inputName as string, null); }; }, [setFieldValue]); return buildClearValue; };
关键说明
- 泛型约束:
extends Record<string, string | undefined>限定了FilterParams的结构,使得keyof FilterParams的类型被缩小为string,而非默认的string | number | symbol,从根源上缩小了类型范围。 - 类型断言:虽然泛型约束已经保证键为字符串,但TypeScript需要明确的断言来匹配
setFieldValue对第一个参数必须是字符串的要求,消除类型报错。
验证用法
原有的SomeFilterParams完全符合约束,使用方式不变,且调用时会自动提示合法的字段名:
type SomeFilterParams = { name?: string; status?: string; } const buildClearValue = useBuildClearValue<SomeFilterParams>(); // 正常调用,无类型报错 buildClearValue('name')();
内容的提问来源于stack exchange,提问作者LukaszBielsko
相关产品推荐
相关产品推荐

