Say I have a list of "nades" where a nade has this interface:
interface Nade {
id: string;
createdAt: Date | string;
viewCount: number;
favoriteCount: number;
commentCount: number;
}
and I want to sort nades based on one of the possible sorting properties which could be denoted by:
type SortBy = Pick<Nade, "viewCount" | "favoriteCount" | "commentCount">;
So I have/want this function:
function sortNades(nades: Nade[], sortBy: SortBy = "viewCount") {
return [...nades].sort((a, b) => b[sortBy] - a[sortBy]);
}
where sortBy: SortBy = "viewCount"
is the conceptual part that I'm trying to achieve. sortBy
should only be able to be one of the possible SortBy
types and is defaulted to viewCount.
I am aware you can't use types and computed properties interchangeable exactly like this, but I'm wondering then if possible, how can I generate the strings from the types automatically?
Something like this for example, but I don't want to have to implement it manually:
const SortByStrings = {
viewCount: "viewCount",
favoriteCount: "favoriteCount",
commentCount: "commentCount",
}
But rather I want to compute SortByStrings
from SortBy
automatically, if possible. Even better would be if I didn't have to use/compute SortByStrings
at all.
CodePudding user response:
You can use keyof
(documentation) operator to define your SortBy
type as following :
interface Nade {
id: string;
createdAt: Date | string;
viewCount: number;
favoriteCount: number;
commentCount: number;
}
type SortBy = keyof Pick<Nade, "viewCount" | "favoriteCount" | "commentCount">;
Now, all SortType
variables have to equals either "viewCount", "favoriteCount" or "commentCount". You can then use it like that :
function sortNades(nades: Nade[], sortBy: SortBy = "viewCount") {
return [...nades].sort((a, b) => b[sortBy] - a[sortBy]);
}
const nades = [
{
id: '1',
createdAt: 'before',
viewCount: 5,
favoriteCount: 65,
commentCount: 20
},
{
id: '2',
createdAt: 'after',
viewCount: 10,
favoriteCount: 10,
commentCount: 10
}
]
const result = sortNades(nades, 'viewCount')
Make it generic
You can make it generic if you want to reuse this concept for other interfaces/types, as following :
type SortBy<T, V extends keyof T> = V
type NadeSortableKeys = SortBy<Nade, 'viewCount' | 'favoriteCount' | 'commentCount'>
function sortNades(nades: Nade[], NadeSortableKeys: SortByNade = "viewCount") {
return [...nades].sort((a, b) => b[sortBy] - a[sortBy]);
}
sortNades([], 'viewCount') // no type error
sortNades([], 'createdAt') // triggers error