はじめに
filterのコールバックって、条件が多くなってくると見づらいですよね
最近思いついたリファクタが、めちゃ初歩的で地味だけど
案外気に入ってるので記事にしてみます
Before
車の情報を持つinterfaceがあるとします
interface Car {
name: string
type: CarType
color: BodyColor
}
enum CarType {
VAN,
SUV,
COUPE,
}
enum BodyColor {
BLACK,
WHITE,
RED
}
Car
の配列があるとします
const cars: Car[] = [
{name: 'HIACE', type: CarType.VAN, color: BodyColor.BLACK},
{name: 'LAND CRUISER', type: CarType.SUV, color: BodyColor.WHITE},
{name: '86', type: CarType.COUPE, color: BodyColor.RED},
{name: 'CARAVAN', type: CarType.VAN, color: BodyColor.RED},
{name: 'HILUX SURF', type: CarType.SUV, color: BodyColor.BLACK},
{name: 'SUPRA', type: CarType.COUPE, color: BodyColor.WHITE},
]
黒いSUVが大好きなので
「CarType
が SUV
、かつ BodyColor
が Black
」
の条件でfilterしたいとします
const suvList1 = cars.filter(car => car.type === CarType.SUV && car.color === BodyColor.BLACK)
普通にfilterしたらこうですね
After
by
というfilterのコールバックを作ります
const by = (type: CarType, color: BodyColor) => (car: Car) => {
return car.type === type && car.color === color
}
filterの条件となる引数 type
, color
を受け取り、関数を返します。
返される関数はcar
を受け取り、条件のbooleanを返します
by
コールバックを使ってみるとこうなります
const suvList = cars.filter(by(CarType.SUV, BodyColor.BLACK))
Cars filter by SUV and BLACK
気持ち良いくらい英文的で綺麗なコードになりました
おわりに
めっちゃ地味だけど、結構好きなリファクタです
ただスコープ内に複数コールバック作りたい時は命名に困るので
declare globalでfilterByXX
みたいな拡張関数作っても良いけど
お手軽にできるところはいいところですね
可読性にはとことんこだわりたい