grian
grian

Reputation: 318

Equivalent of multiple expressions in a typescript switch statement

Since

switch(1 === 1, 2 === 2) {
    case true, true:
        console.log("true, true");
        break;
    default:
        console.log("default");
        break;
}

doesn't work(only goes off of the right side of the comma to my knowledge), I was wondering if there was a typescript equivalent to something like rust's match:

match(1 == 1, 2 == 2) {
    (true, true) => println!("true, true"),
    _ => println!("default"),
}

I've tried doing something with tuples but it always goes to the default condition, see below for code.

switch([1 === 1, 2 === 2]) {
    case [true, true]:
        console.log("true, true");
        break;
    default:
        console.log("default");
        break;
}

Upvotes: 6

Views: 14357

Answers (3)

Evgeny
Evgeny

Reputation: 1283

While it's not possible in JS and TS, to avoid if/else mess I'm using following approach based on comparison:

const obj = {
    color: "red",
    size: 7,
    used: false,
};

const cmp = (condition: any): boolean =>
    _.isMatch(obj, condition);

switch (true) {
    case cmp({ size: 7, color: "red" }): {
        console.log("red 7");
        break;
    }
    case cmp({ used: true }): {
        console.log("used one");
        break;
    }
    default: {
        console.log("default one");
        break;
    }
}

Link to example

Also you can change approach with cmp(conditionObj) function to cmp(condition(obj)) - condition via lamda, or to direct condition in case statement without function.

Upvotes: 0

Rogelio
Rogelio

Reputation: 1094

not sure if this is what you're looking for but maybe you could use this as a workaround

const tuple: [number, number] = [3, 3]

switch (tuple.join(",")) {
    case "3,3": 
      console.log('1');
      break;
    case "3,4":
      console.log('2');
      break;
    default: throw "invalid"
}

Upvotes: 3

CRice
CRice

Reputation: 32186

This is not possible using the JS switch statement. In JS, and TS by extension, the switch statement operates in a very straightforward way:

  • Evaluate the expression in the switch.
  • Compare it (strictly) with each case.

So the behavior you see is caused in part by both of those actions. The first thing to understand is that using a comma doesn't work because that is interpreted as an expression using the comma operator, which as you noticed simply results in the value of the final comma'd expression.

For your second attempt, it is hitting the default expression because under strict comparison, two objects are equal only if they are the same reference. So using an array literal in your switch produces a new array object (reference) which will never be equal to the different references created by the literals in each case.

In order to get the behavior you want, you have to do that comparison the old fashioned way: manually using a collection of if statements. That will allow you to compare each item in your tuple individually. Perhaps something like:

function compareTuples(tup1, tup2) {
  if (tup1.length !== tup2.length) return false;
  return tup1.every((value, index) => tup2[index] === value);
}

const base_tuple = [1 === 1, 2 === 2]

if (compareTuples(base_tuple, [true, true])) {
  console.log("Matched [true, true]")
} else if (compareTuples(base_tuple, [true, false])) {
  console.log("Matched [true, false]")
} else {
  console.log("Matched default")
}

Upvotes: 4

Related Questions