user1543574
user1543574

Reputation: 863

Variable conditional output type for Arrays

I know that Typescript will automatically infer if the output is an array or not, but I'm trying to figure out how to set it explicitly using conditional type.

I've tried something like the below, but it doesn't seem to work.

function test<T>(...args:any[]): T extends any[] ? any[] : any {

    // If there is only 1 arg, return a string
    if(args.length === 1)
        return 1;

    // If there is more than 1 args, return an array
    else
        return [1,2,3]
}

Does anybody know what I'm doing wrong?

Upvotes: 1

Views: 48

Answers (1)

T.J. Crowder
T.J. Crowder

Reputation: 1074038

The error it gives (2322) is the same as the error you get with code like this:

function example<T>(x: number | string): T {
    if (typeof x === "number") {
        return x * 2;
    }
    return x + x;
}

Playground link

Type 'number' is not assignable to type 'T'. 'T' could be instantiated with an arbitrary type which could be unrelated to 'number'. (2322)

What that's saying is that I can write code like this:

example<object>(42);

...and then T is object, but neither number nor string is assignable to object.

The same applies to your test function.

I think you were just experimenting with conditional types, but just for completeness, as you say the TypeScript compiler could infer those return values, but it would infer a union type, in that specific case 1 | number[]. If you wanted to tell TypeScript that test with one argument returns number and test with more than one argument returns number[], you can do that with a function overload:

function test(x: any): number;
function test(x: any, y: any, ...more: any[]): number[];
function test(...args:any[]): number | number[] {

    // If there is only 1 arg, return a string
    if(args.length === 1)
        return 1;

    // If there is more than 1 args, return an array
    else
        return [1,2,3]
}

const x = test(1);          // type of `x` is `number`
const y = test(1, 2, 3);    // type of `y` is `number[]`

Playground link

Upvotes: 1

Related Questions