Functions can be defined in js as follows:
function add(a, b) {return a b}
Then it is allowed to call as follows:
add(1, 2)
add('hello', 'world')
However, it is not allowed to call:
add(1, 'world')
add('hello', 2)
The following code cannot meet the above requirements:
function(a:string|number, b:string|number):string|number {return a b}
How to implement the same code in typescript ?
CodePudding user response:
I find this question interesting because this might be a legitimate limitation of TypeScript.
The obvious solution of simply returning a b
does not work, TypeScript complains that T T
can not be operated on despite what that we know a
and b
must be either string or number and both those types are valid in a concatenation or addition operation.
Thus, I bring you, without any casting, a solution to this problem:
function add<T extends string | number>(a: T, b: T): T {
return Array.from(arguments).reduce((t, c) => t c);
}
console.log(add("Hello", " World!")); // "Hello World!"
console.log(add(4, 3)); // 7
add("Foo", 1337); // Error
It should be noted this is a sort of hack, arguments
produces any[]
and is only available in non arrow functions.
CodePudding user response:
Thanks to @jonrsharpe for the tip, using Function Overloads
; also thanks to @Undo for his answer.
Below is my typescript code implemented using Function Overloads
:
function add(a: number, b: number): number
function add(a: string, b: string): string
function add(a: any, b: any): any {
if (typeof a === 'number' && typeof b === 'number') {
return a b // a and b have full type hints, for example: `a.toFixed`
}
if (typeof a === 'string' && typeof b === 'string') {
return a b // a and b have full type hints, for example: `a.length` .
}
throw new Error('the types of a and b must be the same!')
}
console.log(add(1, 2)) //OK, 3
console.log(add('hello', 'world')) //OK, helloworld
add(1, 'world') // Error