背景
Native型の拡張として 有名な lodash を使ってきたのだけど、
処理が重たいのでやめましょ、というコメントをもらいました。たしかに重たい。 lodash の実装は メソッドチェインにしづらい ので、シーケンシャルに処理を記述できないのが、前々からうーんとなっていた。
lodash でもメソッドチェインはできる点、「lodashが重たい」という点について、コメントをいただきました。確かに lodash でも書きかたでカバーできる可能性がありそうです。
実装
例として、Array型 自体をちょっと拡張してしまおう。
公式にもドキュメントがあります。Declaration-merging という手法を使います。
https://www.typescriptlang.org/docs/handbook/declaration-merging.html
以下は重複を取り除くuniqというメソッドを追加する例です。
array.extensions.ts
export {}
declare global {
interface Array<T> {
uniq<T> (comparer: (value1: T, valu2: T) => boolean): T[];
contains<T> (value: T): boolean;
}
}
/* eslint no-extend-native: ["error", { "exceptions": ["Array"] }] */
Array.prototype.uniq = function<T> (comparer: (value1: T, valu2: T) => boolean): T[] {
return this.filter((value1, index1, array1): boolean => {
const index2 = array1.findIndex((value2): boolean => comparer(value1, value2))
return (index1 === index2)
})
}
使うところ
import './array.extensions'
['aaa','bbb','ccc','bbb','ccc']
.filter(elem => elem === 'ccc')
.uniq((v1,v2) => (v1 === v2))
objectの配列でも
[{ID:'aaa'}, {ID:'bbb'},{ID:'ccc'},{ID:'bbb'},{ID:'ccc'}]
.filter(elem => elem.ID === 'ccc')
.uniq((v1,v2) => (v1.ID === v2.ID))
補足
eslint が効いている場合は、no-extend-native がデフォルト有効なので、OFFにしておきます。
無下に拡張すると、もともとのメソッドを上書きしてしまうので、よく検討した上で都度OFFにするコメントを記載しておくのがベターです。
Native型の拡張は、名前を侵食するリスクと隣合わせではありますが、うまく使えると余計なクラス、Interfaceを定義しなくて済むので、頭の片隅においてて損はないと思います。