gracias por ayudar. Tengo una variedad de objetos. Y no puedo encontrar una buena solución, excepto en muchos IF. La forma de filtrarlo depende de la variedad de propiedades que deben verificarse.
const offers = [ { isGrouped: true, isDiscarded: false, isCopy: false, isWarned: false, name: "qw", }, { isGrouped: false, isDiscarded: true, isCopy: false, isWarned: false, name: "qwer", }, { isGrouped: false, isDiscarded: true, isCopy: true, isWarned: false, name: "erw", }, { isGrouped: false, isDiscarded: false, isCopy: true, isWarned: false, name: "frew", }]y aquí está la matriz de filtros
export enum Status { DISCARDED = "Discarded", WARNED = "Warning", COPY = "Copy", GROUPED = "Grouped", } const filters: string[] = [Status.DISCARDED, Status.COPY];los filtros pueden incluir los cuatro estados o uno, dos, tres o cualquiera de ellos.
function check(offer, filters) { // I don't know actually how to handle filtering here. // only one idea is to check all possible variants ex. // if (filters.includes(Status.DISCARDED) && filters.length === 1) { // return offer.isDiscarded // } else if (filters.includes(Status.DISCARDED) && filters.includes(Status.COPY) && filters.length === 2) { // return offer.isDiscarded || offer.isCopy // } } offers.filter(offer => check(offer, filters))Mi solución no se ve bien. ¿Podría alguien echar un vistazo, por favor?
type Offer = { [K in Status as `is${K}`]?: boolean } function check(offer: Offer, filterStatus: Status[]): boolean { for (const status of filterStatus) { const propertyName = "is"+status as `is${typeof status}` if (!offer[propertyName]) return false } return true }Pondría esto encima de una función de propósito más general que prueba si una colección de pares clave/valor coincide con su objeto. Podemos superponer algo que mapea Discarded a isDiscarded , etc.
const checkProps = (entries) => (x) => entries .every (([k, v]) => x [k] == v) const check = (filters) => checkProps (filters .map (k => [`is${k}`, true])) const findMatches = (offers, filters) => offers .filter (check (filters)) const offers = [{isGrouped: true, isDiscarded: false, isCopy: false, isWarned: false, name: "qw"}, {isGrouped: false, isDiscarded: true, isCopy: false, isWarned: false, name: "qwer",}, {isGrouped: false, isDiscarded: true, isCopy: true, isWarned: false, name: "erw", }, {isGrouped: false, isDiscarded: false, isCopy: true, isWarned: false, name: "frew"}] const Status = {DISCARDED: "Discarded", WARNED: "Warning", COPY: "Copy", GROUPED: "Grouped"} console .log (findMatches (offers, [Status.DISCARDED, Status.COPY])) checkProps toma una matriz de pares clave-valor y devuelve una función que acepta un objeto, informando si todas esas claves en el objeto coinciden con el valor relevante. check toma sus filtros y los convierte en una matriz de pares clave-valor anteponiendo "is" al nombre del filtro y combinándolo con el valor true . Podríamos usar esto llamando directamente
offers .filter (check (filters)) pero me parece más limpio envolver eso en la función findMatches
Esto ofrece una API bastante flexible, pero probablemente podamos ser aún más flexibles sin que sea mucho más difícil de usar. Imagina esto:
students .filter (where ({ gpa: gte (3.0), grade: eq (11), gender: eq ('male'), demerits: lt (3) }))Sería relativamente fácil construir una API que funcionara así con principios muy similares a los anteriores, y sería sencillo superponer su función encima de esto. No intentaré escribirlo aquí. Pero esta es una demostración de un punto útil: a menudo ayuda a simplificar su código pensar en él de manera más genérica y luego agregar su caso especial encima de la abstracción genérica.