Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Enums 不同的枚举变量如何在TypeScript中工作?_Enums_Typescript - Fatal编程技术网

Enums 不同的枚举变量如何在TypeScript中工作?

Enums 不同的枚举变量如何在TypeScript中工作?,enums,typescript,Enums,Typescript,TypeScript有许多不同的方法来定义枚举: enum Alpha { X, Y, Z } const enum Beta { X, Y, Z } declare enum Gamma { X, Y, Z } declare const enum Delta { X, Y, Z } 如果我试图在运行时使用Gamma中的值,我会得到一个错误,因为Gamma未定义,但Delta或Alpha的情况并非如此?在这里的声明中,const或declare是什么意思 还有一个preserveConstE

TypeScript有许多不同的方法来定义枚举:

enum Alpha { X, Y, Z }
const enum Beta { X, Y, Z }
declare enum Gamma { X, Y, Z }
declare const enum Delta { X, Y, Z }
如果我试图在运行时使用
Gamma
中的值,我会得到一个错误,因为
Gamma
未定义,但
Delta
Alpha
的情况并非如此?在这里的声明中,
const
declare
是什么意思


还有一个
preserveConstEnums
编译器标志——它是如何与它们交互的?

在TypeScript中,枚举有四个不同的方面需要注意。首先,一些定义:

“查找对象” 如果编写此枚举:

enum Foo { X, Y }
TypeScript将发出以下对象:

var Foo;
(function (Foo) {
    Foo[Foo["X"] = 0] = "X";
    Foo[Foo["Y"] = 1] = "Y";
})(Foo || (Foo = {}));
我将把它称为查找对象。其目的有两个:充当从字符串到数字的映射,例如在编写
Foo.X
Foo['X']
时,以及充当从数字到字符串的映射。这种反向映射对于调试或日志记录非常有用——您通常会获得值
0
1
,并希望获得相应的字符串
“X”
“Y”

“声明”或“环境” 在TypeScript中,您可以“声明”编译器应该知道的事情,但不能实际为其发出代码。当您有像jQuery这样的库来定义某些对象(例如,
$
)时,这非常有用,因为您需要这些对象的类型信息,但不需要编译器创建任何代码。规范和其他文件提到了在“环境”上下文中以这种方式做出的声明;需要注意的是,
.d.ts
文件中的所有声明都是“环境声明”(需要显式的
declare
修饰符或隐式的,具体取决于声明类型)

“内联” 出于性能和代码大小的原因,通常最好在编译时将对枚举成员的引用替换为其等效数字:

enum Foo { X = 4 }
var y = Foo.X; // emits "var y = 4";
规范称之为替代,我称之为内联,因为它听起来更酷。有时您不希望枚举成员内联,例如,因为枚举值可能在API的未来版本中更改


枚举,它们是如何工作的? 让我们按枚举的每个方面来分解它。不幸的是,这四个部分中的每一部分都会引用所有其他部分的术语,因此您可能需要不止一次地阅读整个内容

计算与非计算(常数) 枚举成员可以计算也可以不计算。规范将非计算成员称为常量,但我将它们称为非计算成员,以避免与常量混淆

计算枚举成员是编译时其值未知的成员。当然,对计算成员的引用不能内联。相反,非计算枚举成员在编译时的值已知。对非计算成员的引用始终是内联的

const enum Foo { A = 4 }
var x = Foo.A; // emitted as "var x = 4;", always
哪些枚举成员是计算的,哪些是非计算的?首先,顾名思义,
const
enum的所有成员都是常量(即非计算)。对于非常量枚举,这取决于您查看的是环境(声明)枚举还是非环境枚举

声明枚举的成员(即环境枚举)是常量,当且仅当其具有初始值设定项时。否则,将对其进行计算。请注意,在
声明枚举
中,只允许使用数字初始值设定项。例如:

declare enum Foo {
    X, // Computed
    Y = 2, // Non-computed
    Z, // Computed! Not 3! Careful!
    Q = 1 + 1 // Error
}
最后,非declare非const枚举的成员总是被认为是计算的。但是,如果它们在编译时是可计算的,则它们的初始化表达式将缩减为常量。这意味着从不内联非常量枚举成员(此行为在TypeScript 1.5中已更改,请参阅底部的“TypeScript中的更改”)

常量与非常量 常数 枚举声明可以有
const
修饰符。如果枚举是
常量
,则对其成员的所有引用都将内联

const enum Foo { A = 4 }
var x = Foo.A; // emitted as "var x = 4;", always
常量枚举在编译时不生成查找对象。因此,在上述代码中引用
Foo
是错误的,但作为成员引用的一部分除外。运行时不会出现
Foo
对象

非常量 如果枚举声明没有
const
修饰符,则仅当成员为非计算成员时,才会内联对其成员的引用。非常量、非声明枚举将生成查找对象

声明(环境)与非声明 一个重要的前言是,TypeScript中的
declare
有一个非常具体的含义:这个对象存在于其他地方。它用于描述现有对象。使用
declare
定义实际上不存在的对象可能会产生不良后果;我们稍后将探讨这些问题

声明
声明枚举
不会发出查找对象。如果这些成员是计算的,则对其成员的引用是内联的(请参见上文关于计算的与非计算的)

需要注意的是,允许以其他形式引用
声明枚举
,例如,此代码不是编译错误,但在运行时会失败:

// Note: Assume no other file has actually created a Foo var at runtime
declare enum Foo { Bar } 
var s = 'Bar';
var b = Foo[s]; // Fails
此错误属于“不要对编译器撒谎”类别。如果在运行时没有名为
Foo
的对象,请不要编写
declare enum Foo

declare const-enum
const-enum
没有区别,除了--preserveConstenum(见下文)的情况

不申报 如果非声明枚举不是
const
,它将生成查找对象。内联如上所述

--保留常量枚举标志 此标志只有一个效果:非declare const enum将发出一个查找对象。内联不受影响。这对于调试很有用


常见错误 最常见的错误是在常规
枚举
常量枚举
更合适时使用
声明枚举
。一种常见的形式是:

module MyModule {
    // Claiming this enum exists with 'declare', but it doesn't...
    export declare enum Lies {
        Foo = 0,
        Bar = 1     
    }
    var x = Lies.Foo; // Depend on inlining
}

module SomeOtherCode {
    // x ends up as 'undefined' at runtime
    import x = MyModule.Lies;

    // Try to use lookup object, which ought to exist
    // runtime error, canot read property 0 of undefined
    console.log(x[x.Foo]);
}
记住黄金法则:永远不要声明实际上不存在的东西。使用
co
var Cheese;
(function (Cheese) {
    Cheese[Cheese["Brie"] = 0] = "Brie";
    Cheese[Cheese["Cheddar"] = 1] = "Cheddar";
})(Cheese || (Cheese = {}));
const enum Bread { Rye, Wheat }
Bread.Rye
Bread['Rye']
declare enum Wine { Red, Wine }
declare const enum Fruit { Apple, Pear }