Reputation: 140
I came up with this solution to type-check that function parameters are valid keys of an object.
type SelectOption = {
value: string;
label: string;
}
const mapItem = <T extends Record<string, unknown>, K extends keyof T, V extends keyof T>(valueKey: K, labelKey: V) => {
return (itemToMap: T): SelectOption => ({
...itemToMap,
value: itemToMap[valueKey] as SelectOption['value'],
label: itemToMap[labelKey] as SelectOption['label'],
});
};
The reason behind this is that I need to map many arrays of objects across the application to objects with value
and label
props based on some other props.
One thing I don't like about this is the error message when trying to pass non-existing prop.
e.g.
type CustomObj = {
name: string;
id: number;
};
const myObjects: CustomObj[] = [...]
const mapped = myObjects.map(mapItem('id', 'name'));
const mapped2 = myObjects.map(mapItem('id', 'names')); // Argument of type '"names"' is not assignable to parameter of type 'keyof CustomObj'.
My question is if there exists some better solution to this that could perhaps provide a better error message.
Upvotes: 0
Views: 1552
Reputation: 26307
I agree with @ij7... this error message seems pretty self-explanatory... but anyways, if you want a custom error message, you could change the signature to something like this:
const mapItem = <T extends Record<string, unknown>, K extends keyof T, V extends string>(valueKey: K, labelKey: V extends keyof T ? V : Error & `'${V}' isn't a valid key bro`) => {
And now you'll get:
Argument of type '"names"' is not assignable to parameter of type 'Error & "'names' isn't a valid key bro"'. Type 'string' is not assignable to type 'Error'.(2345)
🤷 I don't know how helpful that's going to be to you, but hey, at least you can change the error message to your heart's content now!
Upvotes: 2