在Typescript中的枚举问题

时间:2018-02-22 01:52:55

标签: angular typescript

尝试初始化对象并尝试理解一些怪癖。首先,我想部分初始化对象使用。我在枚举方面遇到了一些奇怪的怪癖。

考虑这种类型层次结构:

enum CalcType {
  EXPRESS,
  EXPRESS_LESS_EARNED,
  COST_BASIS
}

interface Program {
  active: boolean;
  code: string;
  displayOrder: number;
  dpld: boolean;
  calcType: CalcType;
}

this.p = <Program> {
  active: false,
  displayOrder: 100,
  dpld: true,
  calcType: CalcType[CalcType.EXPRESS_LESS_EARNED],     // Does not work in Angular!!
  //calcType: CalcType['1']       // Works, value is a string
  //calcType: CalcType.EXPRESS_LESS_EARNED      // Works, value is the ordinal
};

当我尝试使用接口类型创建/初始化新程序时如果我使用CalcType [CalcType.EXPRESS_LESS_EARNED]填充calcType属性,它在JSBin Typescript中工作没有问题,但拒绝在Angular Typescript 2.6.1中工作。有什么想法吗?我得到的错误如下:

Type '{ active: false; displayOrder: number; dpld: true; calcType: string; }' cannot be converted to type 'Program'.
  Property 'code' is missing in type '{ active: false; displayOrder: number; dpld: true; calcType: string; }'.

但是,如果我使用CalcType.EXPRESS_LESS_EARNED或CalcType ['1'],它可以正常工作。

JSBin: http://jsbin.com/bipofim/edit?js,console

StackBlitz: https://stackblitz.com/edit/enums-test

我在这里缺少什么?我应该能够使用Enum [ordinal]语法来获取字符串值。另外,为什么它会抱怨在某些情况下缺少字段而在其他情况下缺少字段?

修改

以下是问题,HTTP服务使用语法从JSON反序列化/序列化,其中resp是HttpResponse:

 return resp.body as Program;

在反序列化期间,JSON中的字符串将转换为枚举字符串,而不是它们的序数。在序列化期间,他们期望枚举的String等价物,否则它们只会被转换为服务器不理解的数字。

那么如何让JSON根据字符串值或序数来翻译枚举字段?

即。下游“EXPRESS”应转换为CalcType.EXPRESS或1 上游CalcType.EXPRESS或1应转换为“EXPRESS”

2 个答案:

答案 0 :(得分:2)

这主要是TypeScript问题。它会在任何地方引起错误,而不仅仅是在Angular中。它适用于JSBin,因为它忽略了编译错误。

这里有两个不同的问题,calcTypecode属性。

问题是这里使用的枚举不正确,可以通过类型检查来检测。

CalcType enum被骗了:

var CalcType;
(function (CalcType) {
    CalcType[CalcType["EXPRESS"] = 0] = "EXPRESS";
    CalcType[CalcType["EXPRESS_LESS_EARNED"] = 1] = "EXPRESS_LESS_EARNED";
    CalcType[CalcType["COST_BASIS"] = 2] = "COST_BASIS";
})(CalcType || (CalcType = {}));

它提供了属性名称及其各自数值的映射,并在对象中生成结果:

enum

然而,这是numeric enum,枚举值应该是数字。

这是类型错误,枚举值应该是数字,而CalcType[CalcType.EXPRESS_LESS_EARNED]是一个字符串:

calcType: CalcType[CalcType.EXPRESS_LESS_EARNED]

这只是禁用类型检查:

calcType: CalcType['1']

这是应该使用枚举的方式,因此它可以工作:

calcType: CalcType.EXPRESS_LESS_EARNED

如果应该能够使用Enum [ordinal]语法来获取字符串值,那么必须使用string enums,并且应该明确定义字符串值:

enum CalcType {
  EXPRESS = 'EXPRESS',
  ...
}

这种方式与普通对象没有什么不同:

const CalcType = {
  EXPRESS: 'EXPRESS',
  ...
};

此错误表明该对象没有code,而它应该存在于Program中:

  

财产代码&#39;类型&#39; {active:false; displayOrder:number; dpld:true; calcType:string; }&#39;

答案 1 :(得分:0)

<强> TLDR:

将您的界面更改为以下内容:

interface Program {
    active: boolean;
    code?: string;
    displayOrder: number;
    dpld: boolean;
    calcType: string;
}

完整答案

我无法准确回答原因,但我可以说如何解决您的一些问题。

您已指定Program有一个非可选参数code,然后您无法提供给this.p。如果您将code设为可选(code?: string;),则会使您的错误消息消失,然后您会收到真正的问题(这实际上不是问题!)

就Typescript而言,CalcType.EXPRESS_LESS_EARNEDCalcType['1']都返回CalcType类型的对象。但是,CalcType[CalcType.EXPRESS_LESS_EARNED]的返回类型为string。您通过将Program分配给string而不是calcType来违反CalcType界面。如果您将其更改为calcType: string;,那么其他问题就会消失。

至于你CalcType[CalcType.EXPRESS_LESS_EARNED]不起作用的说法,我已经在打字稿2.61和2.71中进行了测试,两次都正确地等同于&#39; EXPRESS_LESS_EARNED&#39;作为string