Algebraic data types in TypeScript

In another way :

How would you introduce the windowState DOM property in TypeScript?

SOLVED (in TypeScript 2):

 declare var windowState: WindowState const enum WindowState { STATE_MAXIMIZED = 1, STATE_MINIMIZED = 2, STATE_NORMAL = 3, STATE_FULLSCREEN = 4 } ... var windowState = 5 // Type Error, as expected! 

The original question :

How to declare a type in TypeScript to describe the type of algebraic data? The purpose of this is to describe the existing API.

When I try to do the following, TypeScript obviously complains that type is expected :

 type Weather = 'sunny' | 'bad' 

One of my ideas is to use the JavaScript 2015 Symbol , however TypeScript doesn't seem to know about this.

Another idea was to use enum , however TypeScript complains that a member initializer must be constant expression :

 const enum Weather { sunny = 'sunny', bad = 'bad', windy = Symbol('windy') } 

I would think that the string constant is a constant expression.

+6
source share
3 answers

TypeScript 2.0 has support for recognizable joins / algebraic data types. The documentation is here .

You can combine string literal types, join types, security types, and type aliases to create an advanced template called discriminated joins, also called tagged joins or algebraic data types. Discriminative unions are useful in functional programming. Some languages ​​automatically discriminate alliances for you; TypeScript instead builds on JavaScript patterns that exist today. There are three components:

  • Types that have a common property of a literal (or enumeration); discriminant.
  • The alias of the type that combines these types is union.
  • Enter security features of a general property.

Let the beginning:

 interface Square { kind: "square"; size: number; } interface Rectangle { kind: "rectangle"; width: number; height: number; } interface Circle { kind: "circle"; radius: number; } 

First we declare the interfaces that we integrate. Each interface has a kind property with a different string literal. The kind property is called the discriminant or tag. Other properties are specific to each interface. Please note that the interfaces are not currently connected. Put them in a union:

 type Shape = Square | Rectangle | Circle; 

Now let me use a discriminated union:

 function area(s: Shape) { switch (s.kind) { case "square": return s.size * s.size; case "rectangle": return s.height * s.width; case "circle": return Math.PI * s.radius ** 2; } } 

In each of these branches, TypeScript will narrow the type. If you try to use a case clause with a value that is missing like any kind property, then TypeScript will fail.

+9
source

To use an enumeration, you must write something like this :

 enum Weather { Sunny, Windy }; let currently = Weather.Sunny; 

Line literals

Another way that the OP asks for this to be allowed comes in TypeScript 1.8 .

They will allow you to do something like this:

 type Weather = 'Sunny' | 'Windy'; 
+4
source

You cannot do an enumeration with strings: Create an enumeration with string values ​​in Typescript , this is only a number: http://www.typescriptlang.org/Handbook#basic-types-enum

The symbol is only ES6 and is not yet supported in all browsers: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol - but you can install TypeScript -Compiler in ES6. I would not recommend using Symbol yet

Use the @Kitson solution if it suits you. But you have to use const enum for performance;)

 const enum Weather { sunny, windy }; var weather = Weather.sunny; // Type Weather (number) 

You can use this to get a string value (but don't use const here):

 enum Weather { sunny, bad, } var weather = Weather.sunny; // type Weather (number) var weather_str = Weather[weather]; // type string var weather_str = Weather[Weather.sunny]; // type string function weatherNow(is: Weather) { if (is == Weather.sunny) { } switch (is) { case Weather.sunny: break; case Weather.bad: break; } } weatherNow(Weather.sunny) 
-2
source

All Articles