Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implicitly cast an array type to a tuple type in TypeScript?

Tags:

typescript

Now, args is a rest parameter of a tuple type. How to make this constructor also accept arrays, which, when cast to tuple type, will result in a type that is specified in a said constructor?

Can it be done without manual assertion on construction, e.g.:

const args = [3, 5];

let vector = new Vector(...args as [number, number]);

or

const args: [number, number] = [3, 5];

let vector = new Vector(...args);

class Vector {
    x: number;
    y: number;

    constructor(...args: [] | [number] | [number, number]) {
        switch(args.length) {
            case 0:
                this.x = 0;
                this.y = 0;
                break;
            case 1:
                this.x = this.y = args[0];
                break;
            case 2:
                this.x = args[0];
                this.y = args[1];
                break;
        }
    }
}

const args = [3, 5];

let vector = new Vector(...args);

Playground

EDIT: Considering @philipp-fritsche answer, what if I would add these overloads?

class Vector {
    x: number;
    y: number;

    constructor();
    constructor(xy: number);
    constructor(x: number, y: number);
    constructor(arg1?: number, arg2?: number) {
        if(arg1 === undefined) {
            this.x = this.y = 0;
        } else if (arg2 == undefined) {
            this.x = this.y = arg1;
        } else {
            this.x = arg1;
            this.y = arg2;
        }
    }
}

const args = [1, 2];

let vector = new Vector(...args);
like image 310
Murolem Avatar asked Mar 22 '21 06:03

Murolem


1 Answers

There is no benefit here in defining the parameters per rest.

class Vector {
    x: number;
    y: number;

    constructor(x?: number, y?: number) {
        this.x = x ?? 0
        this.y = y ?? x ?? 0
    }
}

const args = [3, 5];

let vector = new Vector(...args);

This works because the type infered for args is number[]. And the elements 0 and 1 of number[] are number | undefined which matches the parameters for Vector.

If you specify ...args: [] | [number] | [number, number], 0, 1 or 2 arguments are allowed. But number[] can have >=0 elements. So this violates your explicit type.

like image 166
Philipp Fritsche Avatar answered Oct 03 '22 01:10

Philipp Fritsche