Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make a generic add operator in TypeScript that works with numbers and strings

While learning about generics in TypeScript, I wanted to try to recreate the following JavaScript:

function add(x, y){
    return x + y;
}

I tried like:

type StringOrNumber = string | number;

function add<MyType extends StringOrNumber>(x: MyType, y: MyType): MyType {
    return x + y;
}

This errors with:

error TS2365: Operator '+' cannot be applied to types 'MyType' and 'MyType'.

Why doesn't this work? I'd assume that MyType could be either a string or a number, and once "chosen" TypeScript would know it is either adding two strings or two numbers.

like image 284
Justin Meyer Avatar asked Mar 05 '23 14:03

Justin Meyer


1 Answers

A case that could also happen is that MyType can be string | number which extends StringOrNumber. For example add<string | number>('', 1); is a perfectly valid call to the function with the signature you have defined. A type extending a union type doesn't mean "pick exactly one".

Since your signature makes sense and you are learning about generics so we want to stick with it, we can also turn off type checking at that point. Sometimes typescript really can't figure out your complex scenario and you are left with no other option than to return (x as any) + y to abandon the type checking at this point.

Another way to handle this type of situation is with overloaded signatures like the following

function add(x: string, y: string): string;
function add(x: number, y: number): number;
function add(x: any, y: any): any {
    return x + y;
}

const t1: string = add(10, 1); // Type 'number' is not assignable to type 'string'.
const t2: number = add(10, 1); // OK
const t3: string = add('10', '1'); // OK
const t4: number = add('10', 1); // Argument of type '"10"' is not assignable to parameter of type 'number'.
like image 86
SpencerPark Avatar answered Apr 27 '23 01:04

SpencerPark