I am studying TS. I'm trying to make simple calculator. How can I make it this calculator without switch statement? If the if statement is used, an error occurs in return type.
type Command = 'add' | 'substract' | 'multiply' | 'divide' | 'remainder';
const calculate = function (command: Command, num1: number, num2: number): number {
if (command === 'add') return num1 num2;
if (command === 'substract') return num1 - num2;
if (command === 'multiply') return num1 * num2;
if (command === 'divide') return num1 / num2;
if (command === 'remainder') return num1 % num2;
// switch (command) {
// case 'add':
// return num1 num2;
// case 'substract':
// return num1 - num2;
// case 'multiply':
// return num1 * num2;
// case 'divide':
// return num1 / num2;
// case 'remainder':
// return num1 % num2;
// default:
// throw Error('unknown command');
// }
};
console.log(calculate('add', 1, 3)); // 4
console.log(calculate('substract', 3, 1)); // 2
console.log(calculate('multiply', 4, 2)); // 8
console.log(calculate('divide', 4, 2)); // 2
console.log(calculate('remainder', 5, 2)); // 1
CodePudding user response:
Typescript has a type checking paradigm as type inference
and here it tries to find out what should happen for the return type if all your conditions won't match . You need to handle all return types, one of these solutions could be the bellow one:
type Command = 'add' | 'substract' | 'multiply' | 'divide' | 'remainder';
const calculate = function (command: Command, num1: number, num2: number): number | void {
if (command === 'add') return num1 num2;
if (command === 'substract') return num1 - num2;
if (command === 'multiply') return num1 * num2;
if (command === 'divide') return num1 / num2;
if (command === 'remainder') return num1 % num2;
// switch (command) {
// case 'add':
// return num1 num2;
// case 'substract':
// return num1 - num2;
// case 'multiply':
// return num1 * num2;
// case 'divide':
// return num1 / num2;
// case 'remainder':
// return num1 % num2;
// default:
// throw Error('unknown command');
// }
};
console.log(calculate('add', 1, 3)); // 4
console.log(calculate('substract', 3, 1)); // 2
console.log(calculate('multiply', 4, 2)); // 8
console.log(calculate('divide', 4, 2)); // 2
console.log(calculate('remainder', 5, 2)); // 1
console.log(calculate("badcommand", 2, 4)) // this won't return any value just error or undefined
If you are trying to change the function implementation due to the error you can make all the calculation functions like:
type Calculation = (num1: number, num2: number) => number
const add: Calculation = (num1, num2) => {
return num1 num2;
}
const substract: Calculation = (num1, num2) => {
return num1 - num2;
}
// Others
CodePudding user response:
Here's one way to solve it:
type Command = 'add' | 'substract' | 'multiply' | 'divide' | 'remainder';
const calculate = function (command: Command, num1: number, num2: number): number {
return {
'add': () => num1 num2,
'substract': () => num1 - num2,
'multiply': () => num1 * num2,
'divide': () => num1 / num2,
'remainder': () => num1 % num2,
}[command]();
};
console.log(calculate('add', 1, 3)); // 4
console.log(calculate('substract', 3, 1)); // 2
console.log(calculate('multiply', 4, 2)); // 8
console.log(calculate('divide', 4, 2)); // 2
console.log(calculate('remainder', 5, 2)); // 1
CodePudding user response:
TypeScript narrowing is cool but I wouldn't advise you bet too much on it.
Instead you can use a refactoring technique called "Replace Conditional with Polymorphism" to get rid of the if
statements. Like so:
class Command {
#num1 = 0;
#num2 = 0;
constructor(num1: number, num2: number) {
this.#num1 = num1;
this.#num2 = num2;
}
get num1() { return this.#num1; }
get num2() { return this.#num2; }
command() {}
}
class AddCmd extends Command {
command() {
return this.num1 this.num2;
}
}
class SubtractCmd extends Command {
command() {
return this.num1 - this.num2;
}
}
class MultiplyCmd extends Command {
command() {
return this.num1 * this.num2;
}
}
class DivideCmd extends Command {
command() {
return this.num1 / this.num2;
}
}
class RemainderCmd extends Command {
command() {
return this.num1 % this.num2;
}
}
console.log(new AddCmd(1, 3).command()); // 4
console.log(new SubtractCmd(3, 1).command()); // 2
console.log(new MultiplyCmd(4, 2).command()); // 8
console.log(new DivideCmd(4, 2).command()); // 2
console.log(new RemainderCmd(5, 2).command()); // 1
Think about how you can introduce typescript types to the above code.