简体   繁体   中英

Define generic typescript sort function of a certain type

I have a bunch of objects that all have a property with the type of Moment but different names for the key.

I'm trying to write a small utility function using typescript where I can sort any of these objects. Could use some shoving in the right direction.

interface ExampleType1 {
    startDate: Moment;
    // ... other members
}

interface ExampleType2 {
    dueDate: Moment;
    // ... other members
}

interface ExampleType3 {
    createdAt: Moment;
}

I would expect my function look something like this (half pseudocode):

function sortByDateAsc(data: ATypeThatHasAMoment[], keyName: KeyToTheMomentTypeWithinATypeThatHasAMoment) {
    return data.sort((a, b) => {
        // whatever sort logic i use here
        // accessing the Moment object via a[keyName] and b[keyName]
    }
}

I've been fiddling with something like this

function sortByDateAsc<T, K extends keyof T>(data: T[], dateKey: K);

Though within the function T[K] doesn't have a type? I'm not sure how to tell the function "T[K] has to be of type Moment"

You could do it this way:

declare function sortByDateAsc<K extends keyof any, T extends Record<K, Moment>>(
  data: T[], 
  dateKey: K
): T[];

where you are constraining T to be a type where T[K] is Moment . This has the benefit of being simple to define and it works... but it might not give nice IntelliSense hints though. For example:

declare const ex1arr: ExampleType1[];
sortByDateAsc(ex1arr, "startdate"); // error
//            ~~~~~~ <-- "startdate" not in ExampleType1

This is given as an error on ex1arr , not an error on "startdate" . Moreover it does not suggest "startDate" as a correction.


Instead you can use a more complicated conditional type like this:

type KeysMatching<T, V> = {[K in keyof T]: T[K] extends V ? K : never}[keyof T];
declare function sortByDateAsc<T extends any, K extends KeysMatching<T, Moment>>(
  data: T[], 
  dateKey: K
): T[];

Instead of constraining T , that signature constrains K to be the keys where T[K] matches Moment . Now the same example gives you a better error:

declare const ex1arr: ExampleType1[];
sortByDateAsc(ex1arr, "startdate"); // error
//                    ~~~~~~~~~~~ <-- does not match "startDate"

with better IntelliSense hints when you start typing the dateKey parameter (it suggests "startDate" ).


Either way should work. Hope that helps. Good luck!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM