2

I would like to use property value shorthand but only when the value is defined, consider the following example:

const personByName = name => {
  const person = http(name)
  return { person, method: 'byName' }
}

personByName('john') // found person: { person: { name: 'john', age: 30 }, method: 'byName' }
personByName('paul') // not found: { method: 'byName' }

But the current output I get is:

personByName('paul') // not found: { person: undefined, method: 'byName' }
a--m
  • 4,716
  • 1
  • 39
  • 59
  • are you sure you dont want to `http.get(name)`? – Naramsim Jun 07 '18 at 12:27
  • 1
    why do you want this? – Daniel A. White Jun 07 '18 at 12:29
  • @Naramsim `http` is a method, in this case was just added there as an example... I could call it `foo` or `bar` but this way looks something real :) – a--m Jun 07 '18 at 12:34
  • What's wrong with `person: undefined`? That's exactly what the `undefined` value is good for. Always using objects with the same properties is also more efficient. – Bergi Jun 07 '18 at 13:12
  • @Bergi I think that's a different topic, I've specific question, and tried to simplify my problem with a specific and short example. I do agree with you in a general way, but in my specific case it does makes sense to omit the key if the value is undefined. – a--m Jun 07 '18 at 13:16

4 Answers4

4

In order to use shorthand property, Object.assign can be used:

const personByName = name => {
  const person = http(name);
  return Object.assign({ method: 'byName' }, person && { person });
}

Subsequent non-object Object.assign arguments are efficiently ignored, so falsy person doesn't affect the result.

This will work if person is expected to be an object, like is shown in original code.

In case only undefined values aren't allowed, it's:

Object.assign({ method: 'byName' }, person !== undefined && { person });
Estus Flask
  • 206,104
  • 70
  • 425
  • 565
1

I think you want something like this:

const personByName = name => {
  const person = http(name);
  const result = { method: 'byName' };
  if (person) { result.person = person; }
  return result;
}

There's no skipping declaring a property on an object if it's undefined.

halfer
  • 19,824
  • 17
  • 99
  • 186
Daniel A. White
  • 187,200
  • 47
  • 362
  • 445
  • Although it works I was trying to find a way to avoid that extra step conditional + mutation of the `result`... I guess you are right about that there is no way to skip a undefined property. – a--m Jun 07 '18 at 12:31
  • I don't understand why the downvote :/ it would be nice if the down-voter could add a comment – a--m Jun 07 '18 at 12:32
1

In ES2018, you may use the ternary operator to eval if a defined and object spread to build an object which contains a and b, or just b:

const a = 1
const b = { b: 2 }
const c = a ? { a, ...b } : b

console.log( c ) 

const a = undefined
const b = { b: 2 }
const c = a ? { a, ...b } : b

console.log( c ) 
Matías Fidemraizer
  • 63,804
  • 18
  • 124
  • 206
0

In ES2018 this can be done even without "type checks"

let a = { a: 1 }
let b = { b: 2 }
let c = undefined
let d = { d: 4 }

let x = {...a, ...b, ...c, ...d};      // {a: 1, b: 2, d: 4}
//                      ┗━━ undefined
console.log(x)

This works for falsy vars. Some attention to "non empty strings":

let a = { a: 1 }
let b = { b: 2 }
let c = undefined // ━┓
let c1 = false    //  ╏
let c2 = 0        //  ╏
let c3 = -0       //  ┣╍ falsy
let c4 = 0n       //  ╏
let c5 = ''       //  ╏
let c6 = null     //  ╏
let c7 = NaN      // ━┛
let d = { d: 4 }

let x = {...a, ...b, ...c, ...c1, ...c2, ...c3, ...c4, ...c5, ...c6, ...c7, ...d}; 
//                      ┗━━━━━━━━━━━━━━━━━━━━ falsy ━━━━━━━━━━━━━━━━━━━━━┛
console.log(x)   // OK: {a: 1, b: 2, d: 4}

let t1 = true   
let t2 = 789
let y = {...a, ...b, ...t1, ...t2, ...d}; 
console.log(y)   // OK: {a: 1, b: 2, d: 4}

// Non empty string!
let t3 = 'abc'
let z = {...a, ...b, ...t3, ...d}; 
console.log(z)   // {0: "a", 1: "b", 2: "c", a: 1, b: 2, d: 4}
//                   ┗━━━━━━━ !!! ━━━━━━━┛
Exodus 4D
  • 2,207
  • 2
  • 16
  • 19