7

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.

1
  • 1
    But each argument could be either string or number, your current types don't require them to be the same... Commented Jan 31, 2019 at 22:55

1 Answer 1

9

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'.
Sign up to request clarification or add additional context in comments.

4 Comments

Unless you also rely on implicit conversions, i.e. add(1, '2') = 3. While that's anti-typescript, but it depends on your use cases. :)
Thanks. I considered that case. Though I couldn't understand why that case could happen. Your explanation of add<string | number> make the problem clear. I assumed either add<string> or add<number> would be allowed.
How is the question answered, since even if the user would call "add<string | number>(' ', 1);", typescript could add " " + 1 without errors (as it lets this behaviour)
This is fine as long as you aren't using arrow functions.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.