Reputation: 4919
I'm learning TypeScript and currently, I'm trying to create a generic sort function.
I have two interfaces:
interface RefreshToken {
client_icon?: string;
client_id?: string;
client_name?: string;
created_at?: string;
id?: string;
is_current?: boolean;
last_used_at?: string;
last_used_ip?: string;
type: "normal" | "long_lived_access_token";
}
interface PersistentNotification {
created_at: string;
message?: string;
notification_id?: string;
title: string;
status?: "read" | "unread";
}
And my current function looks like so:
function SortByDateAscending<T, K extends keyof T>(values: T[], key: K) {
const compare = (first: T, second: T) => {
const timeA = first[key] ? new Date(first[key]) : 0;
const timeB = second[key] ? new Date(second[key]) : 0;
if (timeA < timeB) {
return 1;
}
if (timeA > timeB) {
return -1;
}
return 0;
};
return values.sort(compare);
}
the above code works, but I get warnings:
No overload matches this call. Overload 1 of 5, '(value: string | number | Date): Date', gave the following error. Argument of type 'T[K]' is not assignable to parameter of type 'string | number | Date'. Type 'T[keyof T]' is not assignable to type 'string | number | Date'. Type 'T[string] | T[number] | T[symbol]' is not assignable to type 'string | number | Date'. Type 'T[string]' is not assignable to type 'string | number | Date'. Type 'T[string]' is not assignable to type 'Date'. Type 'T[keyof T]' is not assignable to type 'Date'. Type 'T[K]' is not assignable to type 'Date'.
Not sure if there is a way to add a constraint that will tell that T[K]
must be string | number | Date
Here is my test project: https://stackblitz.com/edit/typescript-yzualr
I currently passing only string types (one is optional), but will also use Date, so if T[K] is Date I shouldn't use new Date
.
I'd like to avoid any changes to interfaces and of course creating separate functions per type.
Upvotes: 0
Views: 266
Reputation: 1932
You could pass your sort method a method instead of a key name
function sortByDateAscending<T>(
values: T[], getDate: (val: T) => string | number | Date) {
// ...
}
tokens = sortByDateAscending(tokens, token => token.last_used_at);
Upvotes: 1