TypeScript: Varargs Overload Signatures

Image for post
Image for post
Photo by Matt Artz on Unsplash

I thought I’d write up a short post to explain a TypeScript problem that took up far too much of my time.

The TL;DR is that if you have overload signatures for a function that takes a variable number of (initial) arguments, the ordering of the signatures matters in a way that is not obvious. And the ‘simplest’ signature should be placed first.

The types I was working with were in RxJS, but to keep things general let’s use an example that combines a bunch of arrays in some way, like this:

Image for post
Image for post
alt (github.com)

The function will take elements from each of the input arrays that are passed — the caller can pass as many as is necessary — and will return an array containing the combined elements. (How they are combined doesn’t matter; we’re only interested in the types.)

could be typed like this:

Image for post
Image for post
alt (github.com)

Without going into too much detail, is mapped type that maps a tuple of element types to a tuple of read-only arrays — for the input array parameters — like this:

Image for post
Image for post
alt (github.com)

And the element type of the returned array is obtained — from the type parameter — using this mechanism:

Image for post
Image for post
alt (github.com)

With the signature declared like this, the return value’s type is inferred correctly:

Image for post
Image for post
alt (github.com)

Let’s say the function can also be passed a count to specify how many elements at a time should be taken from each input array. We can add an overload signature like this:

Image for post
Image for post
alt (github.com)

With these signatures, the return value’s type is still inferred correctly:

Image for post
Image for post
alt (github.com)

Let’s say we add another overload signature that allows the direction of the combination to be specified:

Image for post
Image for post
alt (github.com)

With these signatures, the return value’s type is inferred correctly for this usage:

Image for post
Image for post
alt (github.com)

However, there is a problem. If is passed only a single input array, the return value’s type is not inferred correctly:

Image for post
Image for post
alt (github.com)

This doesn’t make much sense. The only overload signature that should be matched is the last one.

It turns out that the order of the overload signatures is significant. It shouldn’t be, but it is.

If they are ordered like this:

Image for post
Image for post
alt (github.com)

the inference is correct:

Image for post
Image for post
alt (github.com)

So the take away from this is that if you have overloaded varargs signatures, they should be ordered so that the first signature is the signature without trailing parameters.

This post was first published on my personal blog: ncjamieson.com.

RxJS core team member; front-end developer; mentor; speaker; open-source contributor

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store