typescripttypescript-genericsunion-types

Typescript: Class with generic type 3 | 4


I would like to implement a class for squared matrices, with a generic size. Then I would like to implement standard methods (add, multiply) between matrices, but only of the same size.

The goal is to regroup every matrices types in one class, but to be able to catch the size errors at compilation time, not during execution.

I tried to use a generic type given by the union of the size I need to consider. Like Class Matrix<S = 3|4>. I don't know how to test if S == 3 or S == 4, and to handle it afterwards.

I know I could implement a abstract matrix class and extends it for every size I need. But it is very tedious...

EDIT

The answer I was given works well. I want to add a additional comment in case it may help anyone. To define the multiplication whose errors are cached during the compilation, you can add generic types in the parameters, as follows:

type Size = 1|2|3|4;
class Matrix<I extends Size, J extends Size> {
    readonly iMax: I;
    readonly jMax: J;
    // add coefficients

    constructor(iMax: I, jMax: J){
        this.iMax = iMax;
        this.jMax = jMax;
        // add coefficients
    }

    mult<K extends Size>(x: Matrix<J,K>): Matrix<I,K>{
        // Compute the product
    }
}

new Matrix(3,3).mult(new Matrix(2,2); // Error catch on compilation.

Solution

  • The size will need to be a concrete value you can use in runtime code, since TypeScript type information isn't available at runtime (other than a small runtime aspect to enums).

    Note that your example Class Matrix<S = 3 | 4> has two issues:

    1. Class should be class (case matters)
    2. S = 3 | 4 should be S extends 3 | 4 if you're trying to apply a constraint to the generic type parameter

    Here's a simple example:

    class Matrix<Size extends 3 | 4> {
        readonly size: Size;
    
        constructor(size: Size) {
            this.size = size;
        }
    
        example() {
            const { size } = this;
            if (size === 3) {
               console.log("It's three")
            } else {
               console.log("It's four")
            }
       }
    }
    
    new Matrix(3).example(); // It's three
    new Matrix(4).example(); // It's four
    new Matrix(5).example(); // Compilation Error, because matrix doesn't allow 5
    

    Playground link