1

I need to create a variable in JavaScript and assign it's value based on a condition. This works but feels a bit verbose:

  const color = (() => {
    switch (type) {
      case "primary":
        return CONSTANTS.colors.primary;
      case "secondary":
        return CONSTANTS.colors.secondary;
      case "tertiary":
        return CONSTANTS.colors.tertiary;
      case "positive":
        return CONSTANTS.colors.positive;
      case "negative":
        return CONSTANTS.colors.negative;
      case "disabled":
        return CONSTANTS.colors.disabled;
      default:
        throw new Error("A backgroundColor condition was missed");
    }
  })();

Is what I'm trying to do called "pattern matching"? Ive read that JavaScript doenst have this feature but Im not totally sure what it is.

Is there a more concise way of writing the code above? I could have lots of if statement but this feels messier and requires the variable to be let not const.

let color:
if (type === "primary") {
    color = CONSTANTS.colors.primary;
} else if(type === "secondary") {
    color = CONSTANTS.colors.secondary;
} else if(type === "tertiary") {
    color = CONSTANTS.colors.tertiary;
} else if(type === "secondary") {
    color = CONSTANTS.colors.secondary;
} else if(type === "positive") {
    color = CONSTANTS.colors.positive;
} else if(type === "negative") {
    color = CONSTANTS.colors.negative;
} else if(type === "disabled") {
    color = CONSTANTS.colors.disabled;
}
1
  • What do you mean JS doesn’t have pattern matching? You seem to be mixing up a few things here. Commented May 26, 2020 at 9:53

6 Answers 6

2

The easiest solution for your problem is to check if the type is defined in the object CONSTANTS.colors. If you want to access a property by variable, you need to use the bracket annotation. Everything inside the brackets is evaluated as an expression (so type is a variable, 'type' the String value). Therefore, object.type returns the same value as object['type'].

let color = null;
if (typeof CONSTANTS.colors[type] !== 'undefined') {
   color = CONSTANTS.colors[type];
} else {
   throw new Error('A backgroundColor condition was missed');
}
console.log(color);

You can also first check if the key is defined in the object with Object.keys() and includes():

let color = null;
if (Object.keys(CONSTANTS.colors).includes(type)) {
    color = CONSTANTS.colors[type];
} else {
   throw new Error('A backgroundColor condition was missed');
}
console.log(color);

If you want to support IE11, you cannot use .includes(). Use .indexOf(type) !== -1 instead of .includes(type).

Sign up to request clarification or add additional context in comments.

Comments

0

Pattern matching is generally referring to matching arguments passed to a function: testing to see if they match a specific "pattern". For example, a pattern match might allow you to write a function that takes an integer argument in "two different ways", one where the argument passed in is 0 and one when the argument passed is not 0 (the "otherwise" case). Switch statements are somewhat similar to this type of branching logic but aren't the same as a purely functional language like Haskell, and don't quite help with your goal here.

How about something like this instead?

const myColor = CONSTANTS["colors"][type];
if(typeof myColor !== 'undefined') {
    color = myColor;
} else {
   throw new Error("A backgroundColor condition was missed");
}

Comments

0

You are looking for property accessor:

color = CONSTANTS.colors[type];

Comments

0

An easy replacement for your code would be

const color = (() => {
    const color = CONSTANTS.colors[type];
    if (!color) {
        throw new Error("A backgroundColor condition was missed");
    }
    return color;
  }
  })();

And no, that is not pattern matching.

Comments

0

I think it is wise to introduce an Enum that will hold the color values.

var ColorType = {
        Primary: "primary",
        Secondary: "secondary",
        Tertiary: "tertiary,
        ...
};

Then you can use this enum in switch case and you will avoid the typos and referrence to string directly. I think it will make the code less verbose and less prone to errors.

Comments

0

You can access a property of an object by using the property name as a string in square brackets.

(This example doesn't include the error catching you were using in your switch statement, but you can add that.)

const CONSTANTS = {
  colors: {
    primary: "blue",
    secondary: "yellow"
  }
} 

function getColor(myPropName){
  // Pass dynamic property names like this
  return CONSTANTS.colors[myPropName];
}

console.log(getColor("secondary"));

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.