Home > Net >  TypeScript: array.map force return type?
TypeScript: array.map force return type?

Time:08-01

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[];
  • Related