DEV Community

Jess Edwards
Jess Edwards

Posted on

What's the difference?

I found myself wrangling with what I thought was an odd TS issue yesterday afternoon. During a quick chat about it, my boss gave me this gem of an example and I had to share it.

What's the difference between?

someString && obj[someString] ? [obj[someString]] : []
Enter fullscreen mode Exit fullscreen mode

and

const specificVal = someString && obj[someString];
const result = specificVal ? [specificVal] : [];
Enter fullscreen mode Exit fullscreen mode

To break down the first statement, we're saying

  • If someString is truthy (not null or undefined etc.) and obj has a key someString, the ternary should return an array that holds the value of someString.
  • If the conditional is falsy, an empty array is returned.

The second statement breaks this into two steps, first by defining specificVal, and then using a ternary to return an array with that value or an empty array.

Just looking at them, they're pretty similar statements, so what's the difference between them?

A whole lot. It might manifest itself as a TypeScript issue, but it's there for a reason.
 
Typescript can't infer and guarantee that obj[someString] in the conditional statement is going to be the same as obj[someString] in the return statement, so we split it in to two variables.

Here's a fun example of that - Proxies make objects that on access, can run code to return a result!

const map = new Proxy({}, {get(target, prop, receiver) {return Math.random(); }})
Enter fullscreen mode Exit fullscreen mode

A console.log of map[32] to show how it changes each time

Consider doing something like:

const value = map[1] > 0.5 ? map[1] : 0
Enter fullscreen mode Exit fullscreen mode

This won't be consistent with returning something higher than 0.5 or 0.

Splitting it up now fixes that problem.

const v = map[1]
if v > 0.5 ? v : 0
Enter fullscreen mode Exit fullscreen mode

Essentially object and array access can be just as dynamic as functions (via Proxies, getters and other traps) and we need to treat them as such in places to make TypeScript happy.

Shoutout (and all credit) to James Canning for the example and explanation!

Top comments (0)