定义特定类型的通用打字稿排序功能

时间:2018-07-28 16:27:52

标签: typescript

我有一堆对象,它们都具有Moment类型的属性,但是键的名称不同。

我正在尝试使用Typescript编写一个小的实用函数,在其中我可以对这些对象中的任何一个进行排序。可以在正确的方向使用一些推工具。

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

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

interface ExampleType3 {
    createdAt: Moment;
}

我希望我的函数看起来像这样(半伪代码):

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]
    }
}

我一直在摆弄这样的东西

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

尽管函数T [K]中没有类型?我不确定如何告诉函数“ T [K]必须为Moment类型”

1 个答案:

答案 0 :(得分:1)

您可以这样操作:

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

要将T约束为T[K]Moment的类型。这具有易于定义的优点,并且可以工作……但是,它可能不会给出很好的IntelliSense提示。例如:

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

这是由于ex1arr上的错误而不是"startdate"上的错误而给出的。此外,它不建议"startDate"作为更正。


相反,您可以像这样使用更复杂的conditional type

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[];

该签名将T约束为KT[K]匹配的密钥,而不是约束Moment。现在,同一示例为您提供了更好的错误:

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

当您开始输入dateKey参数(建议"startDate")时,IntelliSense提示会更好。


无论哪种方法都可以。希望能有所帮助。祝你好运!