我有这些接口:
export interface QueryObject {
id: ID;
path: string[];
filters: Filters;
}
export interface Filters {
state: string;
localeID: string;
role: string;
}
并尝试提出一个函数式编程解决方案,以便仅将tmp对象中存在的具有值的属性复制到现有数据模型中。现在,..显然这是行不通的。Filters
会丢失属性localeID
和时被完全覆盖role
。
let queryObject: QueryObject;
let filters: Filters = { state: 'GB'}; // this obviously gives an error on Interface implementation
queryObject.filters = filters;
现在,我正在获取原始对象,遍历该属性并用更新后的值覆盖它。
const queryObject: QueryObject = _.cloneDeep(this.queryObject);
queryObject.filters.state = state; // 'GB'
this.portareService.update(queryObject, this.portareQuery.getActiveId());
最好使用Object.assign或传播...
解决方案来解决此问题,例如:
{
return ...createQueryObject, updatedQueryObject
}
我知道如何使用使用循环的函数来执行此操作,但是正在寻找使用函数式编程的方法。
您可以concat
同时为QueryObject
和实现一个方法Filters
。在中concat
,您定义要使用的“合并逻辑”。在内部QueryObject
调用Filters
concat方法。
在这些concat
方法中,您可以使用传播语法或任何其他逻辑来确保创建新对象,并且您不会对任何内容进行突变。
通过添加empty
构造函数,您可以轻松地在areduce
或其他自动合并中开始使用那些串联器。
我在汤姆·哈丁(Tom Harding)的Semigroups博客上找到了这篇超级启发的博客文章。这篇有关Monoids的帖子中包含有关empty
零件的一些信息。
const QueryObject = ({id = null, path = null, filters = Filters.empty() })=> ({
id,
path,
filters,
concat: other => QueryObject({
id: other.id || id,
path: other.path || path,
filters: filters.concat(other.filters)
}),
toString: () => `QueryObject(${id}, ${path}, ${filters.toString()})`
});
QueryObject.empty = () => QueryObject({});
QueryObject.merge = (x, y) => x.concat(y);
const Filters = ({ state = null, localeID = null, role = null }) => ({
state,
localeID,
role,
concat: other => Filters({
state: other.state || state,
localeID: other.localeID || localeID,
role: other.role || role
}),
toString: () => `Filters(${state}, ${localeID}, ${role})`
});
Filters.empty = () => Filters({});
Filters.merge = (x, y) => x.concat(y);
const userFilter = Filters({ role: "User" });
const gbFilter = Filters({ localeID: "GB" });
const filterSettings = [userFilter, gbFilter];
const mergedFilter = filterSettings.reduce(Filters.merge, Filters.empty());
console.log(
"Merged Filter:",
mergedFilter.toString()
);
// Some base query
const accountQuery = QueryObject({ id: "CUSTOM_Q_1", path: "/accounts" });
// Derived queries
const userQuery = accountQuery.concat(QueryObject({ filters: userFilter }));
const gbQuery = accountQuery.concat(QueryObject({ filters: gbFilter }));
console.log(
"User Query:",
userQuery.toString()
);
console.log(
"Brittish Users Query",
userQuery.concat(gbQuery).toString()
);
编辑:当然,没有“理论”,也有更通用的方法:
const uniques = xs => Array.from(new Set(xs));
const nullMergeStrategy = (obj1, obj2) =>
uniques(
Object.keys(obj1)
.concat(Object.keys(obj2))
).reduce(
(acc, k) => Object.assign(acc, { [k]: obj2[k] || obj1[k] }),
{}
);
const Filter = ({ state = null, localeID = null, role = null }) =>
({ state, localeID, role });
const userFilter = Filter({ role: "User" });
const gbFilter = Filter({ localeID: "GB" });
console.log(
nullMergeStrategy(userFilter, gbFilter)
)
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句