rbcasperson rbcasperson - 1 month ago 13
TypeScript Question

Use parameter as a generic type, and also give it a default assignment

I have a simple class

Board
with parameters
width
,
height
, and
types
in the constructor. Height and width will always have the type
number
, but
types
is an array of any type.

What I would like to do is to capture the type of the
types
parameter using a generic type
<T>
. Then
T
can be used for the return of another function that uses
this.types
. The problem is that I also would like to set the default types to an array of numbers.

This is what I thought might work, but I currently get the error
Type 'number[]' is not assignable to Type 'T[]' Type 'number' is not assignable to Type 'T'
.

export class Board<T> {
constructor(width: number = 8, height: number = 8, types: T[] = [0, 1, 2, 3, 4, 5, 6]) {
this.width = width;
this.height = height;
this.types = types;
}
getTypes(): T[] {
return this.types;
}
}


What am I doing wrong? Or is this setup even possible?

What I ultimately want is for the
T
to be assigned to whatever type that
this.types
ends up being after the class is instantiated. If I call
new Board(8, 8, ['a', 'b', 'c', 'd']);
, I'd like it to know that
T
should be
string
. AND if I just call
new Board()
it will know that
T
should be
number
.

Answer

Better approach using advanced types:

class Board<T> {
    private width:number;
    private height:number;
    private types:T[]|number[];

    constructor(width:number = 8, height:number = 8, types:T[]|number[] = [1, 2]) {
        this.width = width;
        this.height = height;
        this.types = types;
    }

    getTypes():T[]|number[] {
        return this.types;
    }
}

https://jsfiddle.net/r8uqn760/2/

Old answer using type alias:

This approach will always allow numbers in the this.types array.

For example new Board(0, 0, [0, "foo"]) will pass at compilation, and I think it's not what you want to happen.

type X<Y> = number | Y;

class Board<T> {
    private width:number;
    private height:number;
    private types:X<T>[];

    constructor(width:number = 8, height:number = 8, types = [1,2] as X<T>[]) {
        this.width = width;
        this.height = height;
        this.types = types;
    }

    getTypes():X<T>[] {
        return this.types;
    }
}

Fiddle