我经常必须按属性对对象进行排序,因此我编写了以下简单的帮助程序:
static sort = <T extends {}>(list: Array<T>, field: keyof T, descending: boolean = true) =>
list.sort((a, b) => {
if (a[field] > b[field]) {
return descending ? -1 : 1;
}
if (a[field] < b[field]) {
return descending ? -1 : 1;
}
return 0;
});
我经常不得不通过对象上类似日期的属性对对象进行排序,但是我收到的日期以"01-Apr-2018"
的格式进行字符串化,因此我必须先将它们转换为日期。
因此,我用以下内容扩展了上述内容:
static byDate = <T extends {}>(list: Array<T>, field: keyof T, descending: boolean = true) =>
list.sort((a, b) => {
if (new Date(a[field]).getTime() > new Date(b[field]).getTime()) {
return descending ? -1 : 1;
}
if (a[field] < b[field]) {
return descending ? 1 : -1;
}
return 0;
});
这将导致
TS2345:类型“ T [keyof T]”的参数不能分配给类型“ Date”的参数
在a[field]
和b[field]
上。
跟踪选择的WebStorm / TypeScript Service的Date实现,我注意到在new Date("hello")
中,它从lib.es5.d.ts
中选择以下接口:
interface DateConstructor {
new(): Date;
new(value: number): Date;
new(value: string): Date; // THIS ONE (which I expect)
new(year: number, month: number, date?: number, hours?: number, minutes?: number, seconds?: number, ms?: number): Date;
(): string;
readonly prototype: Date;
parse(s: string): number;
UTC(year: number, month: number, date?: number, hours?: number, minutes?: number, seconds?: number, ms?: number): number;
now(): number;
}
但是在我的排序比较器中,它选择the interface from lib.es2015.core.d.ts
,它只有:
interface DateConstructor {
new (value: Date): Date;
}
尝试使用new Date(a[field] as string)
或as Date
进行声明无效。
我正在使用TypeScript 2.7.2(我当前的Angular 6.0.9项目要求该属性,并且不能更改)。
所以:
在这些情况下,tsc
为什么要选择一个呢?
如何确定要使用的代码,或者至少在保持field: keyof T
参数的情况下使我的代码编译?
答案 0 :(得分:4)
我目前无法在2.7.2上进行测试,但是主要的问题是TypeScript认为a[field]
不一定是string
。这是有道理的,因为a
的类型为T
,而field
的类型为keyof T
,所以所知道的是a[field]
是{{1 }}。 可能为T[keyof T]
,或者您可能无法调用string
。
如果您确定只在new Date()
是byDate
的地方调用a[field]
,则可以将泛型更改为:
string
那应该使错误消失……它现在知道static byDate = <K extends keyof any, T extends Record<K, string>>(
list: Array<T>,
field: K,
descending: boolean = true
) => { ... }
是类型a[field]
,其中T[K]
扩展了T
,也称为{{1} },或“其键在Record<K, string>
中且其值是{[P in K]: string}
的对象”。因此K
扩展了string
,很高兴。
上面的应该可以在TypeScript 2.7.2上运行,但是如果遇到问题,请告诉我。
希望有帮助。祝你好运!