概要
TypeScript(JavaScript)の標準のsortメソッドが使いにくいので、compare処理を内蔵した拡張メソッドを実装してみたいと思います。
以下の内容で実装したいと思います。
- プリミティブ型配列の場合は通常の
Array.sort()
を実行する。 - オブジェクト型配列の場合はプロパティ名を可変長で指定してソートする。
動作環境
- TypeScript 2.9.x
サンプルソース
export {}; declare global { interface Array<T> { /** * [拡張メソッド] * 指定したプロパティを元に昇順にソートします。 * @param sortKeys 昇順キー * @return ソート後の配列 */ orderBy<K extends keyof T>(...sortKeys: K[]): T[]; } } Array.prototype.orderBy = function<T, K extends keyof T>(...sortKeys: K[]): T[] { const items = this as T[]; // ソートキーの指定がない場合は、Array.sort()を実行 if (!Array.isArray(sortKeys) || sortKeys.length === 0) return items.sort(); else { return items.sort((a: T, b: T) => compare(a, b, sortKeys)); } }; /** * ソート判定処理 * 再帰的にsortKeysを処理して、ソート判定を行います */ function compare<T, K extends keyof T>(value1: T, value2: T, sortKeys: K[]): number { const key = sortKeys[0]; const prop1 = value1[key]; const prop2 = value2[key]; if (prop1 !== prop2) { return (prop1 < prop2) ? -1 : 1; } else { if (sortKeys.length <= 1) return 0; else return compare(value1, value2, sortKeys.slice(1)); } }
K extends keyof T
でT
クラス内のプロパティのみを指定できるようにしています。
実行結果
プリミティブ型配列
const items = [ 3, 4, 2, 1 ]; const actual = items.orderBy(); // output: 1, 2, 3, 4
オブジェクト型配列
const items = [ { id: 2, name: 'bob' }, { id: 3, name: 'alex' }, { id: 1, name: 'char' }, { id: 4, name: 'bob' } ]; const actual = items.orderBy('name', 'id'); // output: // id: 3, name: 'alex' // id: 2, name: 'bob' // id: 4, name: 'bob' // id: 1, name: 'char'
その他
TypeScriptの拡張メソッド関連の記事は以下を参照。