TypeScript Quirks: Spreading types
The spread operator - amazing. One of my favorite additions to javascript in recent years, and one of the most flexible operators in javascript and typescript alike. Unfortunately though, it does have some limitation currently.
I have a bunch of types that define an array of possible names combinations.
type FirstNames = 'Jake' | 'Sid';
type MiddleNames = 'Sid' | 'Unknown';
type LastNames = 'Smith' | 'Something';
type FullName = [FirstNames, MiddleNames, LastNames];
Now, I can use the FullName
type for a function parameter to create a full name out of only the possible names I’ve defined above.
function createFullName (args: FullName) {
return args.join(' ');
}
Well, that works perfectly. I can only call my function with the first, middle and last names I defined myself.
Hang on a second, what if I were to call the function with apply
. That way I can turn an array into a list of arguments. Well, I guess I’d define my function like this:
function createFullName (...args: FullName) {
Oh, no, that doesn’t work because “A rest parameter must be of an array type.”… but it is an array, right? Not exactly (actually a tuple, more on this here).
If we instead use the following:
type FullName = Array<FirstNames | MiddleNames | LastNames>;
function createFullName (...args: FullName) {
Then it doesn’t complain about it not being an array, but it does have a few other serious problems.
- Now our array of names can be any length
- Our names don’t have to be in the correct order
Not ideal.
So, there’s only really one solution - just define the function parameters as regular function parameters. We know how many there are and exactly what types they’ll be anyway.
function createFullName (firstName: FirstName, middleName: MiddleName, lastName: LastName) {
Yes, in this instance this works perfectly well. Probably a bad example on my part, but my point is that the spread operator in typescript is unfortunately a little limited currently.
Another example is that we cannot define an exact set of items in an array, followed by arbitrary ones. For example if I wanted to have other names in my array after first, middle and last, I cannot use this syntax:
type FullName = [FirstNames, MiddleNames, LastNames, ...string];
// type expected ^
Regardless, the spread operator is still awesome, and typescript is developing rapidly with awesome new features all the time, so maybe we’ll see some improvements very soon.