TypeScript中的代数数据类型

时间:2015-11-25 11:33:27

标签: typescript algebraic-data-types

另一种方式

如何在TypeScript中键入windowState DOM属性?

已解决 (在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!

原始问题

我如何在TypeScript中declare type以便它描述代数数据类型?这样做的目的是描述现有的API。

当我尝试以下操作时,TypeScript显然会抱怨 type is expected

type Weather = 'sunny' | 'bad'

我的一个想法是使用JavaScript 2015 Symbol,但TypeScript似乎并不知道这些。

另一个想法是使用enum,但是TypeScript抱怨 member initializer must be constant expression

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

我原以为string常量是一个常量表达式。

2 个答案:

答案 0 :(得分:15)

TypeScript 2.0支持有区别的联合/代数数据类型。文档为here

  

您可以组合字符串文字类型,联合类型,类型保护和类型别名来构建称为区分联合的高级模式,也称为标记的联合代数数据类型。   受歧视的联合在函数式编程中很有用。   有些语言会自动为您区分工会;而TypeScript则建立在当今存在的JavaScript模式之上。   有三个要素:

     
      
  1. 具有公共文字(或枚举)属性的类型 - 判别
  2.   
  3. 采用这些类型的并集的类型别名 - union
  4.   
  5. 在公共财产上打字。
  6.   

让我们开始吧:

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

首先我们声明要联合的接口。   每个接口都有一个kind属性,具有不同的字符串文字类型。   kind属性称为判别标记。   其他属性特定于每个接口。   请注意,接口当前不相关。   让我们把他们变成一个联盟:

type Shape = Square | Rectangle | Circle;
  

现在让我们使用受歧视的联盟:

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;
    }
}

在每个分支中,TypeScript将缩小类型。 如果您尝试使用case子句,其值不是任何kind属性,则TypeScript将会出错。

答案 1 :(得分:4)

要使用枚举,您可以将其写为like this

enum Weather {
    Sunny,
    Windy
};

let currently = Weather.Sunny;

字符串文字

OP要求解决此问题的另一种方式是TypeScript 1.8

他们会允许你做这样的事情:

type Weather = 'Sunny' | 'Windy';