blue112 blue112 - 19 days ago 8
TypeScript Question

Typescript enums with parameters

I'd like to have strictly typed mutable objects, exactly like the Haxe enums.

In haxe, you can do

enum Color {
Red;
Rgb(r:Int, g:Int, b:Int);
Rgba(r:Int, g:Int, b:Int, a:Int);
}


I'd like to be able to access the
a
parameter only if my object is a
Rgba
, and I can't access any parameters if my object is a
Red
.

I don't really care if I use the
enum
keyword or not in typescript.

Is there any way to achieve that in Typescript ?

Answer

As of version 2.0, Typescript supports tagged unions to some extent. The general syntax is

type MyType = A | B | C …;

Where A, B and C are interfaces. A MyType object can then be any of those types, and no other. The announcement gives a quick example:

interface Square {
    kind: "square";
    size: number;
}

interface Rectangle {
    kind: "rectangle";
    width: number;
    height: number;
}

interface Circle {
    kind: "circle";
    radius: number;
}

type Shape = Square | Rectangle | Circle;

function area(s: Shape) {
    // In the following switch statement, the type of s is narrowed in each case clause
    // according to the value of the discriminant property, thus allowing the other properties
    // of that variant to be accessed without a type assertion.
    switch (s.kind) {
        case "square": return s.size * s.size;
        case "rectangle": return s.width * s.height;
        case "circle": return Math.PI * s.radius * s.radius;
    }
}

However, the type safety if these union types needs to be guarded and checked manually with a so-called “discriminant property type guard” as the example shows (checking s.kind).