I have a simple case which transforms a nested string array to a nested number array, no flatting
const strArr = ["1", "2", ["3", "4"], "5"];
function mapToNumber(item: string | Array<string>): number | Array<number> {
if (Array.isArray(item)) {
return item.map(mapToNumber); // line Hey
} else {
return Number(item);
}
}
console.log(strArr.map(mapToNumber));
However TS yells at me: Type '(number | number[])[]' is not assignable to type 'number | number[]'. Then I changed line Hey to return item.map<number>(mapToNumber), doesn't work.
Function overloading came to my mind, I gave it a try:
const isStringArray = (arr: any): arr is Array<string> => {
return Array.isArray(arr) && arr.every(item => typeof item === "string");
}
function mapToNumber(item: string): number;
function mapToNumber(item: Array<string>): Array<number>;
function mapToNumber(item: any) {
if (isStringArray(item)) {
return item.map<number>(mapToNumber);
} else {
return Number(item);
}
}
console.log(strArr.map(mapToNumber));
Even though I added the custom type guard, still doesn't work.
The logic is quite simple, but how can I define the correct type for this simple case? The playground link
Edit:
I gave generics a try, still doesn't work
function mapToNumber3<T extends string | Array<string>>(item: T): T extends string ? number : Array<number> {
if (Array.isArray(item)) {
return item.map(mapToNumber3);
} else {
return Number(item);
}
}