I have a function that can take either a number or an array of numbers as it's input. This function returns a string if a number is inputted, or an array of strings if an array of numbers is inputted.
Here's my problem
I use array.map
to get the resulting array. array.map
's implicit return type is any. This means that TypeScript expects my function's return type to be any
, or it'll throw me this error:
ignore the typeof
in my arrow function in this screenshot, leftover code
Notice I'm using a bit of recursion here.
I know that the array.map
function will only return an array of strings, so I don't want my function's return type to be any
. I want my functions return type to be string | string[]
. However, since TypeScript thinks the array.map might return something else, it yells at me.
Is there a way to force the array.map
function to return an array of strings? Or to make TS understand what I'm trying to do here?
// Function that swaps a note value with it's numerical value for calculations function numToLet(input: number | number[], isSharp: boolean) {
// Determine which reference key to use based on if we're viewing flats or sharps (isSharp)
let reference = [];
if (isSharp) {
reference = ['G#', 'A', 'A#', 'B', 'C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G'];
} else {
reference = ['Ab', 'A', 'Bb', 'B', 'C', 'Db', 'D', 'Eb', 'E', 'F', 'Gb', 'G'];
}
if (typeof input === 'number') {
return reference[input];
}
if (typeof input === 'object') {
return input.map(item => numToLet(item, isSharp));
}
}
CodePudding user response:
The problem is not the .map
itself, really, but the recursion. As the error message says, you should add a return type so TypeScript can understand what the return type can be, given the recursion.
To make TS understand that all code paths return a value, return unconditionally if the input isn't a number.
function numToLet(input: number | number[], isSharp: boolean): string | Array<string> {
const reference = isSharp
? ['G#', 'A', 'A#', 'B', 'C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G'];
: ['Ab', 'A', 'Bb', 'B', 'C', 'Db', 'D', 'Eb', 'E', 'F', 'Gb', 'G'];
if (typeof input === 'number') {
return reference[input];
}
return input.map(item => typeof numToLet(item, isSharp));
}
But this might not be entirely desirable because it results in
const result = numToLet(3, true);
being typed as a string, not a number - you might want a more precise type, which could be accomplished by declaring beforehand:
function numToLet(input: number, isSharp: boolean): string;
function numToLet(input: number[], isSharp: boolean): string[];