javascript - Angular7: Hur man evaluerar en aritmetisk sträng


Jag använder Angular 7 och jag vill utvärdera en aritmetisk funktion som jag får som en sträng på följande sätt:

Jag får ett "värde" från en tjänst som är ett nummer. Jag får också en "regel" att tillämpa på detta värde som en @Input-parameter, vilken är en sträng och kan innehålla ">", "<" och "==". Exempel:

value = 10;
rule = ">2"

Jag vill sedan tillämpa den regeln och kontrollera om den är sann:

if (10 > 2) {
  console.log("this rule applies!");
}

Jag försökte använda eval på det här sättet:

const strValue: string = value.toString();
const expression = strValue.concat(rule);
if (eval(expression)) {
  console.log("this rule applies!");
}

Men jag får ett fel:

Nekades att utvärdera en sträng som JavaScript eftersom 'unsafe-eval' inte är en tillåten källa för skript i följande Content Security Policy-direktiv: "script-src 'self' 'unsafe-inline'".

Så jag antar att jag inte borde använda "eval" för att göra detta. Har du någon idé om hur jag skulle kunna lösa det?

Svar #1

Du kan använda regex (\D+)(\d+) för att få vilken operator som helst följd av ett nummer. Du kan lägga till fler operatorer i switch om du väljer att utöka det.

function evaluate(value, rule) {
  const [,operator, number] = rule.match(/(\D+)(\d+)/)
  
  switch(operator) {
    case ">" : return value > number
    case "<" : return value < number
    case "==" : return value == number
  }
  
  return null
}

console.log(evaluate(3, ">1"))
console.log(evaluate(3, "<2"))
console.log(evaluate(3, "==3"))

Svar #2

Du kan få operatören och använda en funktion för varje operatör.

function evaluate(value, rule) {
    const
        operators = {
            '<': (a, b) => a < b,
            '>': (a, b) => a > b,
            '==': (a, b) => a == b
        },
        [op, value2] = rule.match(/^(<|>|==)|.*$/g);

    return operators[op](value, value2);
}

console.log(evaluate(10, '<2'));
console.log(evaluate(10, '>2'));
console.log(evaluate(10, '==2'));
console.log(evaluate(10, '==10'));