Búsqueda de sitios web

javascript - Interfaz de Typescript con propiedades anulables


Tengo una interfaz IFilterSet con campos anulables:

export interface IFilterSet {
        filter1?: boolean;
        filter2?: boolean;
        filter3?: number;
        fitler4?: string;
    }

Recibo otro objeto X, que puede contener un objeto IFilterSet entre otros.

Quiero mapear las propiedades IFilterSet del objeto X. La primera suposición sería hacer un bucle para esas propiedades, pero como son anulables, no funcionará, no habrá nada por lo que iterar. Inicializar un IFilterSet vacío iría en contra del propósito de que esas propiedades sean anulables, ¿verdad?

Respuesta #1

No estoy seguro de si entiendo completamente tu pregunta, pero ¿qué tal esto:

function map(filterSet: IFilterSet, obj: X) {
    (obj as any)['filter1'] = filterSet.filter1;
    (obj as any)['filter2'] = filterSet.filter2;
    (obj as any)['filter3'] = filterSet.filter3;
    (obj as any)['filter4'] = filterSet.filter4;
}

De esta manera, la instancia X obtendrá todas las propiedades de filterSet y recibirá undefined para las que no estén presentes, pero todos los campos terminarán allí.

O esto (si intentas construir una nueva instancia de IFilterSet):

function map(obj: X): IFilterSet {
    return {
        filter1: (obj as any)['filter1'],
        filter2: (obj as any)['filter2'],
        filter3: (obj as any)['filter3'],
        filter4: (obj as any)['filter4']
    }
}

Aquí obtendrás una instancia de IFilterSet, con sus campos ya sea undefined o el valor de filter1 hasta filter4.

De cualquier manera, TIENES QUE codificar el nombre de los campos, no estoy seguro de si puedes obtenerlo de otra manera.

Respuesta #2

Definir propiedades opcionales como filter1? no significa que el valor estará definido o será null. Significa que la propiedad puede estar definida (o no).

Digamos que recibes el siguiente objeto:

{
   "name": "foo",
   "type": "bar"
}

Puedes usarlo así:

const filterSet = objectX as IFilterSet;

if (filterSet.filter1 === true) {
    console.log('Do something when filter1 is defined and true');
}
else if (filterSet.filter1 === false) {
    console.log('Do something when filter1 is defined and false');
}
else {
    console.log('filter1 is not true nor false (may be null, undefined or something else)');
}

const value2 = filterSet.filter2 || false;
const value3 = filterSet.filter3 || 0;
console.log('value2 and value3 will always have a value');

Realmente no necesitas usar null para esos casos.

Si realmente necesitas aislar las propiedades de IFilterSet en un objeto diferente, recomendaría usar una función como esta:

const filterSetFrom = (source: any) => {
    const filterSet = {};
    ['filter1', 'filter2', 'filter3', 'filter4']
        .forEach((property) => filterSet[property] = source[property] || null);
    return filterSet;
};