Valentin Garreau
Valentin Garreau

Reputation: 1063

Initialize Destructuring props if null

I would like to initialize my variable to [] if it's null or non-existant.

Here my code:

  const {
columnDates = [],
rowTitles = [],
last3MonthComparisonDirections = [],
last3MonthComparisonMeanings = [],
last3MonthComparisonValues = [],
last3MonthValues = [],
last12MonthValues = [],
lastMonthComparisonDirections = [],
lastMonthComparisonMeanings = [],
lastMonthComparisonValues = [],
lastMonthValues = [],
yearToDateValues = [],
emphasisRow = [],
  } = table;

The problem right now is if columnDates in table is null, then my variable columnDates is null. I would like it initialize it at [] instead of null if it's null.

Any suggestion ? Thank you !

Upvotes: 1

Views: 1609

Answers (2)

Zac
Zac

Reputation: 1532

As mentioned in the previous answer Default values are applied for undefined props, but null is a value for an already defined prop, so you need to do these checks manually,

In addition to the suggested approaches, I'd suggest one more approach, to use a Proxy

const table = {
  columnDates: null,
  rowTitles: [1,2,3],
  last3MonthComparisonDirections: [],
  last3MonthComparisonMeanings: null,
  yearToDateValues: ['a,','b','c'],
  emphasisRow: null
}; 

var proxyObj = new Proxy(table, {
  get: (target, prop) => target[prop] === null ? undefined : target[prop]
});

const {
  columnDates = [],
  rowTitles = [],
  last3MonthComparisonDirections = [],
  last3MonthComparisonMeanings = [],
  last3MonthComparisonValues = [],
  last3MonthValues = [],
  last12MonthValues = [],
  lastMonthComparisonDirections = [],
  lastMonthComparisonMeanings = [],
  lastMonthComparisonValues = [],
  lastMonthValues = [],
  yearToDateValues = [],
  emphasisRow = [],
 } = proxyObj;

console.log(columnDates); // []
console.log(rowTitles); // [1,2,3]
console.log(lastMonthValues); // []
console.log(last3MonthComparisonDirections); // []

You don't want to use default values? you can return [] for undefined props too:

const table = {
  columnDates: null,
  rowTitles: [1,2,3],
  last3MonthComparisonDirections: [],
  last3MonthComparisonMeanings: null,
  yearToDateValues: ['a,','b','c'],
  emphasisRow: null
}; 

var proxyObj = new Proxy(table, {
  get: (target, prop) => target[prop] || []
});

const {
  columnDates,
  rowTitles,
  last3MonthComparisonDirections,
  last3MonthComparisonMeanings,
  last3MonthComparisonValues,
  last3MonthValues,
  last12MonthValues,
  lastMonthComparisonDirections,
  lastMonthComparisonMeanings,
  lastMonthComparisonValues,
  lastMonthValues,
  yearToDateValues,
  emphasisRow,
 } = proxyObj;

console.log(columnDates); // []
console.log(rowTitles); // [1,2,3]
console.log(lastMonthValues); // []
console.log(last3MonthComparisonDirections); // []

Also, you can check for specific allowed or expected keys, so not all undefined props will return []:

const table = {
  columnDates: null,
  rowTitles: [1,2,3],
  last3MonthComparisonDirections: [],
  last3MonthComparisonMeanings: null,
  yearToDateValues: ['a,','b','c'],
  emphasisRow: null
}; 

// Define possible allowed props, 
const possibleProps = [
  'columnDates',
  'rowTitles',
  'last3MonthComparisonDirections',
  'last3MonthComparisonMeanings',
  'last3MonthComparisonValues',
  'last3MonthValues',
  'last12MonthValues',
  'lastMonthComparisonDirections',
  'lastMonthComparisonMeanings',
  'lastMonthComparisonValues',
  'lastMonthValues',
  'yearToDateValues',
  'emphasisRow'
 ];

var proxyObj = new Proxy(table, {
  get: function(target, prop) {
    if (possibleProps.includes(prop)) {
      return target[prop] || [];
    }
    
    return Reflect.get(...arguments);
  }
});

const {
  columnDates,
  rowTitles,
  last3MonthComparisonDirections,
  last3MonthComparisonMeanings,
  last3MonthComparisonValues,
  last3MonthValues,
  last12MonthValues,
  lastMonthComparisonDirections,
  lastMonthComparisonMeanings,
  lastMonthComparisonValues,
  lastMonthValues,
  yearToDateValues,
  emphasisRow,
 } = proxyObj;

console.log(columnDates); // []
console.log(rowTitles); // [1,2,3]
console.log(lastMonthValues); // []
console.log(last3MonthComparisonDirections); // []

Upvotes: 4

Nick Parsons
Nick Parsons

Reputation: 50684

The default value will only be used if the value being destructured is undefined. Changing that isn't something you can do. You have a few options:

  1. Don't use destructuring, and instead use the newer nullish coalescing operator (??):

    const columnDates = table.columnDates ?? []; // default if columnDates is `null` or `undefined`
    ... continue for others ...
    

If you're only having this problem with columnDates, then perform the above for columnDates and then use destructuring for the other properties. Otherwise, if all values could be null, then perform the above for each property.

  1. Map the null values to undefined so you take the default values for null values:

    const {
      columnDates = [], 
      rowTitles = [], 
      ... etc ...
    } = Object.fromEntries(Object.entries(table).map(
      ([key, val]) => [key, val === null ? undefined : val]
    ));
    

The above maps over the entire table object's values and builds a new object for you with the previous null values now as undefined.

  1. Instead of mapping the entire object, you could instead create an array of string properties you want to extract, and map those from the object:

    const keys = ["columnDates", "rowTitles", ...];
    const desiredKeys = Object.fromEntries(keys.map(
      key => [key, table[key] == null ? [] : table[key]]
    ));
    

The above uses == to check if table[key] is equal to null or undefined, and if it is, it will default the value to an empty [] array. If you only want this behaviour for null, then use strict equality === instead.

Upvotes: 2

Related Questions