Reputation: 321
I'm trying to create a generic hook that returns a function that clears the filter values.
I'm not passing any parameters, just a type parameter. FilterParams
will be in the shape of example SomeFilterParams
.
//...
export const useBuildClearValue = <FilterParams>() => {
const {
setFieldValue,
} = useFormikContext();
const buildClearValue = useCallback((inputName: keyof FilterParams) => {
return () => {
setFieldValue(inputName, null); //error is here
};
}, [
setFieldValue,
]);
return buildClearValue;
};
//... USAGE
type SomeFilterParams = {
name?: string;
status?: string;
}
const buildClearValue = useBuildClearValue<SomeFilterParams>();
TS is not happy with inputName
in the setFieldValue
.
Error: Argument of type 'string | number | symbol' is not assignable to parameter of type 'string'. Type 'number' is not assignable to type 'string'.ts(2345)
I guess that I need to type the passed type itself and enforce the key as a string and value as a string as well.
Any idea how this can be achieved?
Upvotes: 0
Views: 50
Reputation: 37081
You didn't show what the signature of setFieldValue
is, but based on the error and your example usage, it looks like it takes a property name as a string and a value to set for that property. However, keyof T
without any constraints on T
is defined as any of the types that are valid for keys in JavaScript, which is strings, numbers, and symbols. Because you can't pass a number or symbol to setFieldValue
, you get this error.
What you want is to restrict the input
to only the string property names of your generic type. You can do that by filtering all number and symbol keys out using a conditional mapped type.
Here's a simplified example, removing the React and Formik-specific parts.
declare const setFieldValue: (property: string, value: unknown) => void;
export const useBuildClearValue = <T,>() => {
return (inputName: Exclude<keyof T, number | symbol>) => {
return () => {
setFieldValue(inputName, null);
};
};
};
type SomeFilterParams = {
name?: string;
status?: string;
}
const buildClearValue = useBuildClearValue<SomeFilterParams>();
buildClearValue("name");
buildClearValue("status");
Upvotes: 1