2016-09-05 2 views
1

これは非常に単純なものを記述する非常に長いタイトルでした。要素型パラメータを使用するメソッドでtypescriptをArray.prototypeに拡張できますか?

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からいくつかのサンプルコードを実行すると、アレイの試作品にパッチを適用しようとしています、それを(これは良いアイデアであるかどうかについてのコメントが期待されています) 。

しかし、私はそれを呼び出す際に、活字体が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)(つまり、メソッドではなく関数)を呼び出すと、型パラメータが正しく機能します。

答えて

2

インターフェイス宣言の並べ替え機能によって、のTから新しいTsortBy<T, K>)が切り離されています。 sortBy<K>であり、ArrayTを再利用する必要があります。

正しい宣言

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); 
+0

パーフェクト、よろしく! – Jarrad

+0

しかし、 'T'型のパラメータを使って' sortBy'を実装することができましたか? –

0

私はちょうど実装がどのように動作するかを明確にしたいです。実装上の型パラメータは、インタフェース宣言と一致する必要はなく、配列型を含めることができます。

interface Array<T> { 
    sortBy<K>(
     keyFunction: (t: T) => K 
    ): T[]; 
} 

Array.prototype.sortBy = function <T, K>(
    keyFunction: (t: T) => K 
): T[] { 
    ... 
}; 

... 

const array = [] as Something[]; 
const sorted = array.sortBy(x => x.SomeProperty); 
関連する問題