Home > Blockchain >  Can you map typescript types to other types generically?
Can you map typescript types to other types generically?

Time:08-25

I have a function that can return one of 2 different types. I want to specify the return type using a generic parameter, but I don't want to specify the actual return type. Instead, I want to specify true or false and have the function map that to the actual return type. Is this possible in TypeScript?

Playground link

// function that gets some data that can be parsed as a string[] or as a number
const getData = () => {
    return JSON.parse('...');
};

// function that parses the data as a string[]
const fooTrue = () => {
    return getData() as string[];
};

// function that parses the data as a number
const fooFalse = () => {
    return getData() as number;
};

// the types for x and y work out, but I had to make 2 functions for foo (fooTrue and fooFalse)
const x = fooTrue(); // string[]
const y = fooFalse(); // number

// single function for foo
const foo = (flag: boolean) => {
    if(flag) {
        return getData() as string[];
    }
    return getData() as number;
}

// the types for xx and yy don't work out :(
const xx = foo(true); // number | string[]
const yy = foo(false); // number | string[]

// generic version, but you have to specify the actual return type
const fooGeneric = <T extends unknown>() => {
    return getData() as T;
}

// the types for xxx and yyy work out, but I had to specify string[] and number instead of true/false
const xxx = fooGeneric<string[]>(); // string[]
const yyy = fooGeneric<number>(); // number

// function that converts true/false types to string[]/number types, respectively
const functionIWant = <???>(???) => {
    ???
}

const xxxx = functionIWant<true>(); // should return a string[]
const yyyy = functionIWant<false>(); // should return a number

CodePudding user response:

Typescript supports function overloading. So something like this is possible:

function foo(flag: true): string[];
function foo(flag: false): number;
function foo(flag: boolean) {
    if(flag) {
        return getData() as string[];
    }
    return getData() as number;
}

Note: Arrow functions cannot be overloaded

CodePudding user response:

A simple conditional type should work for you.

const functionIWant = <T extends boolean>(): T extends true ? string[] : number => {};
  • Related