копировать реквизиты из obj в obj функциональным способом программирования - PullRequest
0 голосов
/ 10 декабря 2018

У меня есть эти интерфейсы:

  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
}

Я знаю, как сделать это с помощью функции loop (s).), но ищет подход к функциональному программированию.

1 Ответ

0 голосов
/ 10 декабря 2018

Вы можете реализовать метод concat для QueryObject и Filtersconcat вы определяете, какую «логику слияния» вы хотите использовать.QueryObject вызывает внутренний метод Filters 'concat.

Внутри методов concat вы можете использовать синтаксис распространения или любую другую логику, чтобы гарантировать создание новых объектов и ничего не мутировать.

Добавив конструктор empty, вы можете легко начать использовать эти конкатенаторы внутри reduce или другого автоматического слияния.

Я нашел этот пост в блоге о полугруппах Тома Хардинга супер вдохновляющим. Этот пост о моноидах содержит некоторую информацию о 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)
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...