javascript - Typescript-gränssnitt med nullbara egenskaper


Jag har ett gränssnitt IFilterSet med nullbara fält:

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

Jag får ett annat objekt X, som kan innehålla IFilterSet-objekt bland andra.

Jag vill kartlägga IFilterSet-egenskaperna hos objekt X. Första gissningen skulle vara att göra en loop för dessa egenskaper, men eftersom de kan vara null kommer det inte att fungera, det kommer inte finnas något att loopa igenom. Att initiera en tom IFilterSet skulle motverka syftet med att dessa egenskaper kan vara null, eller hur?

Svar #1

Jag är inte säker på om jag fullt ut förstår din fråga, men vad sägs om detta:

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;
}

På det här sättet kommer X-instansen att få alla egenskaper från filterSet och får undefined för de som inte finns, men alla fälten kommer till slut att vara där.

Eller detta (om du försöker skapa en ny IFilterSet-instans):

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']
    }
}

Här får du en instans av IFilterSet, med deras fält antingen undefined eller värdet av filter1 till filter4.

Oavsett måste du hårdkoda namnet på fälten, jag är inte säker på om du kan få det på annat sätt.

Svar #2

Att definiera valfria egenskaper som filter1? betyder inte att värdet kommer att vara definierat eller null. Det betyder att egenskapen kan vara definierad (eller inte).

Säg att du får följande objekt:

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

Du kan använda det så här:

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');

Du behöver egentligen inte använda null för de fallen.

Om du verkligen behöver isolera egenskaperna hos IFilterSet i ett annat objekt, skulle jag rekommendera att använda en funktion som denna:

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