Как различные варианты перечисления работают в 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 имею в виду на декларациях здесь?



есть еще preserveConstEnums флаг компилятора -- как это взаимодействует с этим?

683   2  

2 ответов:

есть четыре различных аспекта перечислений в 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".

"объявить" или " ambient"

в TypeScript вы можете "объявлять" вещи, о которых компилятор должен знать, но на самом деле не выдавать код для. Это полезно, когда у вас есть библиотеки, такие как jQuery, которые определяют некоторый объект (например,$), что вы хотите ввести информацию о, но не нужно никакого кода, созданного компилятором. Спецификация и другая документация относятся к объявлениям, сделанным таким образом, как находящимся в" окружающем " контексте; важно отметить, что все объявления в .d.ts файл является "окружающим" (либо требует явного declare модификатор или неявно, в зависимости от декларации тип.)

"inlining"

по причинам производительности и размера кода часто предпочтительно иметь ссылку на элемент перечисления, замененный его числовым эквивалентом при компиляции:

enum Foo { X = 4 }
var y = Foo.X; // emits "var y = 4";

спецификация называет это замена, я назову его inlining потому что это звучит круче. Иногда вы будете не хотите, чтобы элементы перечисления были встроены, например, потому что значение перечисления может измениться в a будущая версия API.


перечисления, как они работают?

давайте разберем это по каждому аспекту перечисления. К сожалению, каждый из этих четырех разделов будет ссылаться на термины из всех остальных, поэтому вам, вероятно, придется прочитать все это несколько раз.

вычисляется против не вычисляется (константа)

перечисление членов может быть либо вычисляемые или нет. Спецификация вызывает не вычисляемые члены постоянный, но я буду называть их невычисляемые чтобы избежать путаницы с const.

A вычисляемые элемент перечисления - это тот, значение которого неизвестно во время компиляции. Ссылки на вычисляемые члены не могут быть встроены, конечно. И наоборот, a невычисляемые перечисление член один раз чье значение и известен во время компиляции. Ссылки на не вычисляемые члены всегда встроены.

что члены перечисления вычисляются, а какие не вычисляются? Во-первых, все члены const перечисления являются постоянными (т. е. не вычисляются), как следует из названия. Для неконстантного перечисления это зависит от того, смотрите ли вы на ambient (объявлять) перечисление или не перечисление окружающей среды.

член a declare enum (т. е. окружающее перечисление) является постоянным если и только если он имеет инициализатор. В противном случае он вычисляется. Обратите внимание, что в declare enum, только числовые инициализаторы допустимый. Пример:

declare enum Foo {
    X, // Computed
    Y = 2, // Non-computed
    Z, // Computed! Not 3! Careful!
    Q = 1 + 1 // Error
}

наконец, члены не объявленных неконстантных перечислений всегда считаются вычисленными. Однако их инициализирующие выражения сводятся к константам, если они вычислимы во время компиляции. Это означает, что неконстантные элементы перечисления никогда не вставляются (это поведение изменилось в TypeScript 1.5, см." изменения в TypeScript " внизу)

константный против неконстантной

const

перечисление объявление может иметь const модификатор. Если перечислимый составляет const,все ссылки на его членов встроены.

const enum Foo { A = 4 }
var x = Foo.A; // emitted as "var x = 4;", always

перечисления const не создают объект поиска при компиляции. По этой причине, это-ошибка ссылка Foo в приведенном выше коде, за исключением как часть ссылки на элемент. Нет

здесь происходит несколько вещей. Давайте разберемся в каждом конкретном случае.

перечисление

enum Cheese { Brie, Cheddar }

во-первых, просто перечисление. При компиляции в JavaScript, это будет выдавать таблицу подстановки.

таблица поиска выглядит так:

var Cheese;
(function (Cheese) {
    Cheese[Cheese["Brie"] = 0] = "Brie";
    Cheese[Cheese["Cheddar"] = 1] = "Cheddar";
})(Cheese || (Cheese = {}));

тогда, когда у вас есть Cheese.Brie в TypeScript, он испускает Cheese.Brie в JavaScript, который оценивается в 0. Cheese[0] выдает Cheese[0] и на самом деле оценивает в "Brie".

const перечисление

const enum Bread { Rye, Wheat }

никакой код на самом деле не испускается для этого! Его значения встроены. Следующие выделяют само значение 0 в JavaScript:

Bread.Rye
Bread['Rye']

const enums' встраивание может быть полезно по соображениям производительности.

а насчет Bread[0]? Это будет ошибка во время выполнения и ваш компилятор должен поймать его. Там нет таблицы подстановки и компилятор не встроен здесь.

обратите внимание, что в приведенном выше случае флаг --preserveConstEnums будет заставьте хлеб выдавать таблицу подстановки. Однако его значения все равно будут встроены.

объявить перечислимый

как и в других случаях использования declare,declare выделяет код и ожидает, что вы определили фактический код в другом месте. Это не выдает таблицу поиска:

declare enum Wine { Red, Wine }

Wine.Red выдает Wine.Red в JavaScript, но не будет никакой таблицы поиска вина для ссылки, поэтому это ошибка, если вы не определили ее в другом месте.

объявить const перечисление

это не выдает таблицу поиска:

declare const enum Fruit { Apple, Pear }

но он делает встроенный! Fruit.Apple выдает 0. Но опять Fruit[0] будет ошибка во время выполнения, потому что он не встроен и нет таблицы подстановки.

Я написал это в этой детская площадка. Я рекомендую играть там, чтобы понять, какой TypeScript испускает какой JavaScript.

Comments

    Ничего не найдено.