TL;DR
function foo(x: string[] | number[]) {
// HOW TO DETERMINE WHETHER x IS OF TYPE string[] OR number[]?
}
Full Story
I have a class X which can be instantiated with either no args or an array of string or an array of number:
class X {
constructor(...args?: string[] | number[]) {
// ensure there are args and array isn't empty
if (!args || args.length === 0) {
return;
}
// check for number[]
if (typeof args[0] === 'number') { // <<<< THIS IS WHERE I'M LOOKING FOR A DIFFERENT SOLUTION
this.setNumbers(...args); // <<<< THE ERROR
}
// it's a string[]
else {
this.setStrings(...args);
}
}
function setNumbers(...args: number[]): X {
// TODO: validate and set numbers
return this;
}
function setStrings(...args: string[]): X {
// TODO: validate and set strings
return this;
}
}
I couldn't find a solution on how to determine the type of the args array, other than checking the type of the actual content.
And logically speaking this would be a valid solution: The args array can only ever be either of type string[] or number[]. It can never be a mix of both types (like a (string | number)[] would allow it to be).
So if it's non-empty and has an element of type number, then it has to be of type number[], but TypeScript doesn't agree with me on that:
TS2345: Argument of type 'string | number' is not assignable to parameter of type 'number'.
Ideas to a Solution
It would be nice if we could check if (args instanceof number[]), but that won't work on primitive data types, because they can't be instantiated and what gets instantiated here is an array of a certain type (not the type itself) and TypeScript kinda agrees: TS2693: 'number' only refers to a type, but is being used as a value here.
So how about if (args instanceof Array<number>)? Would be nice as well, but TS2359: The right-hand side of an 'instanceof' expression must be of type 'any' or of a type assignable to the 'Function' interface type..
What would be the correct way to check the type of the args array?