我有一个像这样的单子数据结构:
export abstract class Data<A> {
static initial<A>(): Data<A> {
return new Initial<A>()
}
static failed<A>(error?: any): Data<A> {
return new Failed<A>(error)
}
static loaded<A>(value: A): Data<A> {
return new Loaded<A>(value)
}
static loading<A>(): Data<A> {
return new Loading<A>()
}
static getData<A>(data: Loaded<A>): A {
return data.getData()
}
constructor(public readonly kind: Kind) {}
abstract map<B>(f: (a: A) => B): Data<B>
abstract chain<B>(f: (a: A) => Data<B>): Data<B>
abstract flatMap<B>(f: (a: A) => Data<B[]>): Data<B>[]
}
Initial
,Failed
,Loaded
和Loading
是我类型中的四个不同“形状”。
有时在我的代码中得到一个Data<A>[]
,我想根据A
上的条件进行过滤。我当前的实现是这样:
static filter<A>(data: Data<A>[], pred: (a:A) => boolean): Data<A>[] {
return data.filter(datum => {
if(datum.isLoaded()) {
return pred(datum.data)
}
return false
})
}
大多数代码使用链式方法,例如:
data.map(...).filter(...).doThis().doThat()
但是由于static
,有时订单会变得混乱:
Data.filter(data.map(...).flatMap(...), myPredicate).map(...).doThis(...) ........
我想知道是否有一种方法可以使此函数变为非静态,并使用“流利的”样式链接方法?
我应该为此扩展数组的原型吗?
答案 0 :(得分:0)
您不应该在Array::filter
函数中调用filter
,而应该返回包装的谓词函数:
static loadedAnd<A>(pred: (a:A) => boolean): Data<A> => boolean {
return datum => datum.isLoaded() && pred(datum.data);
}
随你写
data.map(...).flatMap(...).filter(Data.loadedAnd(myPredicate)).map(...).doThis(...)
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^