NewbieProgrammer
NewbieProgrammer

Reputation: 89

Specifying argument Array length

Is it possible to specify the length of a double array upon parameter settings? for example:

class Matrix4x4{
    constructor(matrix: /*must be a 4x4 number matrix*/){
    }
}

Upvotes: 0

Views: 46

Answers (2)

thoughtrepo
thoughtrepo

Reputation: 8383

If you don't need to limit the length of the array, and only need to define the array's elements you can use tuples like in David D.'s answer. However, in your case that would be the same as doing number[][].

Otherwise it gets a little tricky.

interface Array4<T> {
    0: T;
    1: T;
    2: T;
    3: T;
    // Copied directly from the 'lib.d.ts' file
    push(...items: T[]): number;
}

interface MatrixArray4x4<T> {
    0: T;
    1: T;
    2: T;
    3: T;
    // Copied directly from the 'lib.d.ts' file
    map<U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[];
}

// Alias for clarity
type MatrixData4x4 = MatrixArray4x4<Array4<number>>;

class Matrix4x4{
    constructor(matrix: MatrixData4x4){
    }
}

Works

var matrix: MatrixData4x4 = [
    [1, 3, 3, 7],
    [1, 9, 8, 4],
    [9, 0, 0, 1],
    [2, 0, 3, 8],
];

The type of a is number.

var a = matrix[0][0];

The type of b is any. If --noImplicitAny is set, a type error will occur.

var b = matrix[4][0];

Works

new Matrix4x4([
    [1, 3, 3, 7],
    [1, 9, 8, 4],
    [9, 0, 0, 1],
    [2, 0, 3, 8],
]);

Error: Property 4 is not assignable in MatrixData4x4.

new Matrix4x4([
    [1, 3, 3, 7],
    [1, 9, 8, 4],
    [9, 0, 0, 1],
    [2, 0, 3, 8],
    [1, 2, 3, 4],
]);

Error: Property map missing in the literal object.

new Matrix4x4({
    0: [1, 3, 3, 7],
    1: [1, 9, 8, 4],
    2: [9, 0, 0, 1],
    3: [2, 0, 3, 8],
});

Error: Property 3 missing in MatrixData4x4.

new Matrix4x4([
    [1, 3, 3, 7],
    [1, 9, 8, 4],
    [9, 0, 0, 1],
]);

Error: Property 3 missing in Array4<number>.

new Matrix4x4([
    [1, 3, 3],
    [1, 9, 8, 4],
    [9, 0, 0, 1],
    [9, 0, 0, 1],
]);

Error: Type string is not assignable to number.

new Matrix4x4([
    [1, '3', 3, 5],
    [1, 9, 8, 4],
    [9, '0', 0, 1],
    [9, 0, 0, '1'],
]);

The limitation is that MatrixArray4x4 and Array4 don't extend Array. So type errors will occur if Array methods are called on it and they're not defined.

Works, since map is defined above in MatrixArray4x4.

matrix.map((x) => x[3]);

Works, since push is defined above in Array4.

matrix.map((arr) => arr.push(4));

Error: Property push doesn't exist on the type MatrixArray4x4.

matrix.push([1, 2, 3, 4]);

Error: Property map doesn't exist on the type Array4.

matrix.map((arr) => {
    arr.map((x) => x[3]);
});

They way I got around this was to make an interface called ArrayMethods containing all the methods from the Array class without the element definition. I then extended that interface to make new limited length array interfaces.

Upvotes: 1

David Driscoll
David Driscoll

Reputation: 1419

Yes it's possible using Tuples. (see : https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md#3.3.3 )

something like...

type TMatrixRow4x4 = [number, number, number, number];
type TMatrix4x4 = [TMatrixRow4x4, TMatrixRow4x4, TMatrixRow4x4, TMatrixRow4x4];

class Matrix4x4{
    constructor(matrix: TMatrix4x4){}
}

You can change it around for any size matrix you might need.

Upvotes: 1

Related Questions