@JeanPaulBelmondo

Как отфильтровать сразу по нескольким динамическим полям?

Есть список товаров:

[
    {
       "id":746,
       "variant_id":43310568833259,
       "display_name":"Samsung Galaxy S22 Ultra - 128GB / Black",
       "image_url":"https://cdn.shop.com/s/files/1/0645/3287/3451/products/61U6oC65TTL._AC_SL1500.jpg?v=1662545789",
       "image_alt":null,
       "price":"1300.00",
       "sold_out":false,
       "compare_at_price":null,
       "currency":"USD",
       "options":{
          "size":"128GB",
          "color":"Black"
       }
    },
    {
       "id":747,
       "variant_id":43310568866027,
       "display_name":"Samsung Galaxy S22 Ultra - 128GB / Green",
       "image_url":"https://cdn.shop.com/s/files/1/0645/3287/3451/products/61nhOdlKpDL._AC_SL1500.jpg?v=1662545789",
       "image_alt":null,
       "price":"1300.00",
       "sold_out":false,
       "compare_at_price":null,
       "currency":"USD",
       "options":{
          "size":"128GB",
          "color":"Green"
       }
    },
    {
       "id":748,
       "variant_id":43310568898795,
       "display_name":"Samsung Galaxy S22 Ultra - 128GB / White",
       "image_url":"https://cdn.shop.com/s/files/1/0645/3287/3451/products/817aOXLoNpL._AC_SL1500.jpg?v=1662545789",
       "image_alt":null,
       "price":"1300.00",
       "sold_out":false,
       "compare_at_price":null,
       "currency":"USD",
       "options":{
          "size":"128GB",
          "color":"White"
       }
    }
 ]


Есть фильтр по options:
{
    size: '512GB', 
    color: 'Green'
}


И вот этих фильтров может быть сколько угодно много, и имена у них тоже разные (может пользователь создавать).

Как отфильтровать нужные варианты?
Понятное дело, что я могу написать что-то вроде

state.product.variants.find(variant => variant.options.color === colorValue && variant.options.size === sizeValue);

, но это хардкод, а нужна динамика.
  • Вопрос задан
  • 64 просмотра
Решения вопроса 1
Например так.
type FilterOptions<T> = {
  [K in keyof T]?: T[K] extends object ? FilterOptions<T[K]> : T[K];
};

const isOverlaps = <T>(entry: T, options: FilterOptions<T>): boolean => {
  const keys = Object.keys(options) as Array<keyof T>;
  
  return keys.every((key) => {
    if (typeof options[key] === 'object') {
      return isOverlaps(entry[key], options[key]!);
    }

    return entry[key] === options[key];
  });
};

const filterBy = <T>(collection: T[], options: FilterOptions<T>) => {
  return collection.filter((entry) => isOverlaps(entry, options));
};
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы