Reputation: 3637
I have an interface IFilterSet with nullable fields:
export interface IFilterSet {
filter1?: boolean;
filter2?: boolean;
filter3?: number;
fitler4?: string;
}
I receive another object X, that may contain IFilterSet object among others.
I want to map the IFilterSet properties of object X. First quess would be to make a loop for those properties, but because they are nullable, it won't work, there will be nothing to loop through. Initialiazing an empty IFilterSet would defeat the purpose of those properties being nullable, right?
Upvotes: 2
Views: 6056
Reputation: 3726
Defining optional properties like filter1?
does not means that the value will be defined or null
. It means that the property may be defined (or not).
Let say you receive the following object:
{
"name": "foo",
"type": "bar"
}
You can use it like this:
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');
You don't really need to use null
for those cases.
If you really need to isolate the properties of IFilterSet in a different object. I would recommend using a function like this one:
const filterSetFrom = (source: any) => {
const filterSet = {};
['filter1', 'filter2', 'filter3', 'filter4']
.forEach((property) => filterSet[property] = source[property] || null);
return filterSet;
};
Upvotes: 1
Reputation: 2682
To have properties of IFilterSet
as as properties of X
, all you need to do is declare that X
extends IFilterSet
, or use type assertions if you can't control X
s declaration.
class X implements IFilterSet {
...
}
...
const x:X = ...
const filterSet = x as IFilterSet;
If you're making properties of IFilterSet
optional to obey lose structure of X
, you could have IFilterSet
with required properties (without ?
) and have
X
implement Partial<IFilterSet>
. Partial<T>
gives you a type with all properties of T
, but made optional.
Upvotes: 0
Reputation: 7345
I'm not sure if I fully get your question, but how about this:
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;
}
This way, the X instance will get all the properties of filterSet
and gets undefined
for the ones are not present, but all the fields will end up there.
Or this (if you try to construct a new IFilterSet
instance):
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']
}
}
Here you will get an instance of IFilterSet
, with their fields either undefined
or the value of the filter1
through filter4
.
Either way you HAVE TO hardcode the name of fields, I'm not sure if you can get it differently.
Upvotes: 1