Null-coalescing default values in destructuring
Given input valid JSON JSON.parse() or JSON.stringify() replacer function can be utilized to substitute "undefined" for null.
const convertJSONNullToUndefined = json =>
Object.assign({}
// if input is valid JSON string and not a JavaScript plain object omit JSON.stringify(), use JSON.parse() with same replacer function
, ...Object.entries(JSON.parse(JSON.stringify(json, (key, value) => value === null ? `${void 0}` : value)))
.map(([key, value]) => value === `${void 0}` ? {[key]: void value} : value)); // {x: undefined, y: undefined, z: undefined}
const {z = "a"} = convertJSONNullToUndefined({ x: null, y: 123, z: null }); // "a" assigned to z
Alternatively RegExp can be used to replace JSON string values
const convertJSONNullToUndefined = json =>
Object.assign({},
...function*() {
// use negative lookahead to match ":" followed by null followed by comma or closing curly bracket character
// replace null with "undefined"
const o = JSON.parse(JSON.stringify(json).replace(/(?![:])null(?=[,}])/g, `"${void 0}"`));
// set value to undefined
for (const key in o) yield {[key]: o[key] === `"${void 0}"` ? void o[key] : o[key]}
}());
const {z = "a"} = convertJSONNullToUndefined({ x: null, y: 123, z: null }); // "a" assigned to z
Given input valid JSON JSON.parse() or JSON.stringify() replacer function can be utilized to substitute "undefined" for null.
guest271314, that’s a lot of code! It feels like if anything, your example backs up the proposal.
const { z =? 'a' } = { z: null };
I’m not sure I like the proposed syntax. The question mark indicates to me that it’s the value on the lhs that’s optional - when in reality, it’s the other way around.
The bytes used for code can be reduced. JSON.stringify()
or JSON.parse()
and replace()
could be used. The original proposal mentions JSON
, though includes the case of
const { y =? 'a' } = { y: undefined }; // z === 'a'
which is not valid JSON
but a JavaScript plain object. The brief
example handles JSON
and/or JavaScript plain object input.
Is the actual input a JSON
string?
There would probably at least that amount of code to implement the
extension to the =
operator in JavaScript.
Slightly less code (still un-golfed as that does not appear to be the stated requirement described at OP) using the same/similar pattern.
let input_json_string = `{"z":null}`;
const convertJSONNullToUndefined = json => {
const o = JSON.parse(json);
for (const key in o) if (o[key] === null) o[key] = void 0;
return o;
}
convertJSONNullToUndefined(input_json_string); // do destructuring stuff
Alternatively a single use function expecting a single input parameter that is a valid JSON string consisting of a {"key":"value"}
const convertJSONNullToUndefined = (json, o = JSON.parse(json), [k] = Object.keys(o), res = o[k] !== null ? o : {[k]: void 0}) => res;
const { z = 'a' } = convertJSONNullToUndefined(`{"z":null}`);
Since .find()
returns undefined
if the value is not matched
const [z = 'a'] = [Object.values(JSON.parse(`{"z":null}`)).find(value => value !== null)];
or
const [z = 'a'] = Object.values(JSON.parse(`{"z":null}`)).filter(value => value !== null);
Similarly to
const { x = 'a' } = {}; // z === 'a' const { y = 'a' } = { y: undefined }; // z === 'a' const { z = 'a' } = { z: null }; // z === null
I'd like to propose
const { x =? 'a' } = {}; // z === 'a' const { y =? 'a' } = { y: undefined }; // z === 'a' const { z =? 'a' } = { z: null }; // z === 'a'
Which would handle also null values in default cases
This is because default destructuring introduced in ES6 doesn't handle null values, null values in JSON are quite common from APIs, it'd be convenient
It's also inspired by the null-coalescing operator tc39/proposal-nullish-coalescing