Prior to TypeScript 3.0, utilizing a union type was the best option available, similar to what you are currently using. However, with the introduction of several new features designed to enhance tuple types and their relationship to lists of function parameters, there have been significant improvements. Functions now support a final rest parameter that represents an indefinite number of parameters as an array, leading to the addition of a final rest element in a tuple which represents an indefinite number of tuple elements as an array.
Your specific scenario is highlighted as an example in the documentation:
For instance, [number, ...string[]]
denotes tuples with a number
element followed by any number of string
elements.
Let's implement this concept:
type MyArray = [number, ...string[]];
const okay0: MyArray = [0]; // valid
const okay1: MyArray = [1, "a"]; // valid
const okay2: MyArray = [2, "a", "b"]; // valid
const okay3: MyArray = [3, "a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]; // valid
const bad0: MyArray = [0, "a", false]; // error!
// ~~~~ <-- boolean cannot be assigned to string
const bad1: MyArray = ["x", "y"]; // error!
// ~~~ <-- string cannot be assigned to number
const bad2: MyArray = []; // error!
// ~~~~ <--- property '0' is missing (i.e., bad2[0] is missing)
This implementation appears to be correct. I hope this explanation aids you, good luck!
Link to code