这是一个很长的标题来描述一些非常简单的事情。
interface Array<T> {
sortBy<T, K>(keyFunction: (t: T) => K): T[];
}
.
export namespace util {
export function sortBy<Element, Key>(array: Element[], keyFunction: (t: Element) => Key ): Element[] {
var arrayCopy = array.slice();
var mapped = arrayCopy.map(function(el, i) {
return { index: i, value: keyFunction(el) };
});
mapped.sort(function(a, b) {
return +(a.value > b.value) || +(a.value === b.value) - 1;
});
for (let i = 0; i < array.length; i++) {
let indexed = mapped[i];
array[i] = arrayCopy[indexed.index];
}
var result = mapped.map(function(el){
return arrayCopy[el.index];
});
return array;
}
}
.
Array.prototype.sortBy = function(keyFunction) {return util.sortBy(this, keyFunction)}
我在这里实现了一些来自 MDN 的示例代码,以按数组键而不是比较函数进行排序,并尝试用它来修补数组原型(prototype)(关于这是否是一个好主意的评论是预期的)。
但是,当我调用它时,Typescript 无法验证 keyfunction 的正确参数类型,因此需要强制转换以防止编译器错误:
it('should sort in-place', () => {
var list = [{a: 'z', i: 2}, {a: 'x', i: 0}, {a: 'y', i:1}];
// all good
list.sortBy(<Function>(obj) => obj.i);
expect(list.map((obj) => obj.a)
.join('')
).toBe('xyz');
})
it('should sort in-place', () => {
var list = [{a: 'z', i: 2}, {a: 'x', i: 0}, {a: 'y', i:1}];
// Error TS2339: Property 'i' does not exist on type '{}'
list.sortBy((obj) => obj.i);
expect(list.map((obj) => obj.a)
.join('')
).toBe('xyz');
})
有什么方法可以更改此定义使其生效吗?有趣的是,调用 util.sortBy(array, function)
(即作为函数,而不是方法)的类型参数可以正常工作。
最佳答案
您的接口(interface)声明的排序函数正在创建一个新的 T
( sortBy<T, K>
) 与 Array
断开连接的 T
.应该是sortBy<K>
并重复使用 Array
的 T
.
正确声明
interface Array<T> {
sortBy<K>(keyFunction: (t: T) => K): T[];
}
var list = [{a: 'z', i: 2}, {a: 'x', i: 0}, {a: 'y', i:1}];
// Okay
list.sortBy((obj) => obj.i);
关于generics - typescript 可以使用使用元素类型参数的方法扩展 Array.prototype 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39323238/