Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeScript, bind multiple params to same type

Tags:

typescript

Is there a way to achieve the following with TypeScript?

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

I want the following to compile:

add(1, 2);
add("hello ", "world");

But I do not want the following to compile:

add(4, "world");
add("hello ", 4);

Note also, I want it to compile for strings and numbers only.

like image 573
Balzard Avatar asked Nov 21 '16 15:11

Balzard


1 Answers

You can do this with generic types:

function add<T extends string | number>(x: T, y: T): T {
  return x + y;
}

add<string>("a", "b"); // OK
add<number>(5, 3); // OK
add<boolean>(true, false); // Type 'boolean' does not satisfy constraint 'string | number'

Notice that you don't always need to give the generic type when calling the function, as long as it satisfies the constraints:

add("a", "b"); // OK
add(5, 3); // OK
add(5, "b"); // Type argument candidate 'number' is not a valid type argument because it is not a supertype of candidate 'string'.
add(true, "c"); // Type argument candidate 'boolean' is not a valid type argument because it is not a supertype of candidate 'string'.

As you can see, this is saying:

  • x and y must be the same type
  • that type must either be a string or a number (or an extension of either)

The TypeScript compiler is clever enough to work out the type without specifying the generics in the calls (but you must put them in the definition).


As you noticed, this is an issue with the TypeScript compiler. I've logged it on the TypeScript Github repo.

For now, you can do this:

function add<T extends string | number>(x: T, y: T): T {
    return <any>x + <any>y;
}

x and y are still of type T (ensured by the compiler) but we trick it into letting us do + on them.

like image 167
James Monger Avatar answered Sep 21 '22 22:09

James Monger