Reputation: 221
I'm writing rather a simple sorting function for backend api.
If there's no sorting it returns an empty string.
If there's sorting it returns a value taken from an enum based on column + some minor modifications.
However I have a trouble regarding types.
sort
when not null has, a sortBy
which is T
passed to this function (union of strings), this works ok.
I do not know how do I pass Enum to the function where sort. sortBy is a valid key of that enum.
type SortState = null | {sortBy: string; sortAsc: boolean; }
const handleSort = <T, K extends T>(sort: SortState, sortEnum: K) => {
if (!sort) {
return '';
}
const name = sort.sortBy as T;
const order = sort.sortAsc;
const newQuery = `${order ? '-' : ''}${order ? sortEnum[name].replaceAll(',', ',-') : sortEnum[name]}`;
return newQuery;
};
enum SortEnum {
bar = 'bar',
foo = 'foo'
}
type TableHeaders = 'foo' | 'bar'
const sortQuery = handleSort<TableHeaders>({sortBy: 'bar', sortAsc: false}, SortEnum)
Upvotes: 2
Views: 36
Reputation: 330216
Given your implementation and call, I'd be inclined to make handleSort()
generic in the type K
corresponding to the sortBy
property of the sort
argument, which is also a key of the sortEnum
argument. Like this:
const handleSort = <K extends PropertyKey>(
sort: null | { sortBy: K, sortAsc: boolean },
sortEnum: Record<K, string>
) => {
if (!sort) {
return '';
}
const name = sort.sortBy;
const order = sort.sortAsc;
const newQuery = `${order ? '-' : ''}${
order ? sortEnum[name].replaceAll(',', ',-') : sortEnum[name]
}`;
return newQuery;
};
The sortEnum
parameter is of type Record<K, string>
using the Record
utility type to mean "a type with a string
-valued property at every key of type K
". The implementation type checks because the compiler understands that name
is of type K
(if sort
is truthy) and therefore that sortEnum[name]
is of type string
.
Let's test the call side:
const sortQuery = handleSort(
{ sortBy: 'bar', sortAsc: false },
SortEnum
); // okay
const sortQuery2 = handleSort(
{ sortBy: 'baz', sortAsc: false },
SortEnum // error!
// ~~~~~~~~ <-- Property 'baz' is missing in type 'typeof SortEnum'
);
Looks good. The compiler is happy when sortBy
matches a key in SortEnum
, and unhappy when it doesn't.
Upvotes: 2