Home > Software engineering >  Generate strings from type properties to be used as computed properties
Generate strings from type properties to be used as computed properties

Time:11-15

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
  • Related