Múltiples Constantes en TypeScript

Múltiples constantes nos permiten definir un conjunto de constantes con nombre. El uso de múltiples constantes facilita aclarar la intención de usar el código o crear un conjunto de diferentes estados. TypeScript también proporciona polinomios dependientes de números y dependientes de cadenas.

Tabla de contenidos


Enumeraciones numéricas (enum)

Comenzaremos con constantes escalares, que le resultarán familiares a cualquier persona de otros lenguajes de programación. Una constante múltiple se puede definir con la palabra clave enum:

enum Direction {
    Up = 1,
    Down,
    Left,
    Right,
}

En el código anterior, tenemos una constante escalar, Up cuyo elemento se inicializa con el valor 1. Todos los elementos que le siguen tendrán sus valores incrementados automáticamente a partir de este punto en orden ascendente. En otras palabras, el elemento tendrá Direction.Up el valor 1, el elemento Down tendrá el valor 2Left su valor 3 y finalmente Right su valor 4. También podemos dejar el primer valor sin iniciar:

enum Direction {
    Up,
    Down,
    Left,
    Right,
}

Aquí el elemento tiene Up su valor 0Down su valor 1, y así sucesivamente. Este autoincremento es útil en los casos en los que puede que no nos importen los valores de los mismos elementos, pero sí que cada valor sea diferente del resto de los valores en un mismo múltiplo.

Usar una constante transitiva es simple, simplemente puede acceder a cualquier elemento como una propiedad en la constante enumerada y declarar los tipos usando el nombre de la constante enumerada:

enum Response {
    No = 0,
    Yes = 1,
}

function respond(recipient: string, message: Response): void {
    // ...
}

respond("Princess Caroline", Response.Yes)

Las constantes poli escalares pueden ser una combinación de elementos constantes y calculados (ver más abajo). Las constantes poli que no tienen elementos inicializados deben inicializarse primero o vienen después de las constantes escalares que se inicializan a constantes escalares o miembros de enumeración constante. En otras palabras, lo siguiente no puede:

enum E {
    A = getSomeValue(),
    // Falso, el elemento 'A' 
    // no se inicializa con una constante, por lo que el elemento 
    // 'B' necesita un inicializador de 
    B,
}

Enumeraciones de cadena

Varias constantes de cadena funcionan de manera similar, pero tienen algunas pequeñas diferencias durante el tiempo de ejecución, como se documenta a continuación. Todos los elementos deben inicializarse con una constante inicializada mediante un valor literal de cadena o con otra enumeración de cadena:

enum Direction {
    Up = "UP",
    Down = "DOWN",
    Left = "LEFT",
    Right = "RIGHT",
}

Aunque varias constantes de cadena no tienen un incremento automático, tienen la ventaja de ser fáciles de serializar. En otras palabras, si tiene que leer el valor de una constante escalar durante la depuración, el valor generalmente será ambiguo, lo que significa que no tiene ningún significado útil por sí solo; pero el mapeo inverso puede ayudar a ser legible cuando se ejecuta su código, independientemente del nombre de la constante enumerada en sí.

Constantes heterogéneas

Es técnicamente posible mezclar elementos numéricos y de texto en varias constantes, pero hacerlo no suele ser sencillo:

enum BooleanLikeHeterogeneousEnum {
    No = 0,
    Yes = "YES",
}

Esto no se recomienda a menos que desee utilizar las funciones de tiempo de ejecución de JavaScript de forma más inteligente.

Calculado y constante

Cada uno de los elementos de las constantes múltiples tiene un valor asociado, y este valor puede ser constante o calculado. Una constante múltiple se considera constante si:

  • El primer elemento de la constante múltiple no tenía inicializador, y 0en :
// valor E.X 
// constante aquí 
enum E { X }
  • No tiene inicializador y el valor del elemento que lo precede es una constante escalar. En este caso, su valor es el valor del elemento que le precede más uno:
// todos los elementos en 
// 'E1' y 'E2' enumeración constante 
enum E1 { X, Y, Z }

enum E2 {
    A = 1, B, C
}
  • Inicializado con una expresión de enumeración constante. Es una expresión de TypeScript que se puede evaluar completamente en tiempo de compilación. Una expresión es un múltiplo constante si:
    • Una expresión constante múltiple literal (es decir, un texto o un valor numérico).
    • Una referencia que apunta a una constante enumeración cuyo valor es una constante predefinida (que se puede derivar de otra constante enumerable).
    • Una expresión constante múltiple constante entre paréntesis.
    • Uno de los operadores unarios ~-+ aplicado a una expresión constante múltiple.
    • Operadores binarios ‎%‎, ‎/‎, ‎*‎, ‎-‎, ‎+,‎ ‎>>>, ‎>>, ‎<<, ‎&, ‎|‎, ‎^, con las expresiones de múltiples constantes siendo operandos, y se generará un error durante la compilación (error de tiempo de compilación) Cuando las expresiones se evalúan como NaN o Infinity.

En todos los demás casos, el elemento se cuenta:

enum FileAccess {
    // Elementos estáticos 
    None,
    Read    = 1 << 1,
    Write   = 1 << 2,
    ReadWrite  = Read | Write,
    // elemento calculado 
    G = "123".length
}

Enumeraciones de unión(union enums) y tipos de miembros de enumeración(enum member types)

Los miembros de enumeración literal son un subconjunto de los miembros de enumeración literal. Un miembro de enumeración literal es un miembro de enumeración constante cuyo valor es un miembro de enumeración constante, pero no tiene ningún valor pre inicializado o tiene valores inicializados como:

  • Un valor literal de cadena ( ‎"foo"‎como ‎"bar"‎, o ‎"baz"‎) .
  • Un valor numérico literal (como 1100).
  • Se aplica un menos unario a cualquier valor de número literal (como el valor ‎-1‎‎-100‎).

Cuando todos los elementos de una constante múltiple tienen valores de enumeración literales, habrá una semántica especial que nos permitirá usarlos de varias maneras. Por ejemplo, se puede decir que los elementos finitos solo pueden tener el valor de una constante múltiple:

enum ShapeKind {
    Circle,
    Square,
}

interface Circle {
    kind: ShapeKind.Circle;
    radius: number;
}

interface Square {
    kind: ShapeKind.Square;
    sideLength: number;
}

let c: Circle = {
    kind: ShapeKind.Square,
    // ~~~~~~~~~~~~~~~~ error
    radius: 100,
}

En segundo lugar, los múltiples tipos de constantes se convertirán en una unión para cada elemento de la constante múltiple. Aunque todavía no hemos hablado de los tipos de unión, todo lo que necesita saber es que un sistema de tipos puede, junto con las enumeraciones de unión, explotar el hecho de que conoce el conjunto exacto de valores que existen en la misma enumeración. Es por eso que TypeScript puede detectar errores que pueden ocurrir cuando los valores se comparan incorrectamente. por ejemplo:

enum E {
    Foo,
    Bar,
}

function f(x: E) {
    if (x !== E.Foo || x !== E.Bar) {
        //             ~~~~~~~~~~~
        // Error, no se puede aplicar el operador 
        // '!==' Sobre los dos tipos 'E.Foo' y 'E.Bar'. 
    } 
}

En el ejemplo anterior, primero comprobamos que x no es lo mismo ‎E.Foo‎. Si esto tiene éxito, entonces no se comprobará el otro || y se ejecutará el código del cuerpo de la condición if. Pero si eso no funciona, la variable x sólo puede ser E.Foo, por lo que no tiene sentido verificar si es igual a E.Bar.

Múltiples constantes durante la ejecución (Enums at runtime)

Las constantes múltiples son objetos reales que existen durante la ejecución. Por ejemplo, la siguiente constante polimórfica se puede pasar

enum E {
    X, Y, Z
}

a funciones de la siguiente manera:

function f(obj: { X: number }) {
    return obj.X;
}
// Esta llamada funcionará porque 'E' 
// tiene una propiedad escalar llamada 'X' 
f(E);

Mapeos inversos

Además de crear un objeto con los nombres de propiedades de los elementos, los elementos de constantes múltiples también tienen una asociación inversa, esta asociación de los valores de las constantes múltiples a los nombres de las constantes múltiples. Por ejemplo, vea el siguente ejemplo:

enum Enum {
    A
}
let a = Enum.A;
let nameOfA = Enum[a]; // "A"

TypeScript puede traducirlo a algo similar al siguiente JavaScript:

var Enum;
(function (Enum) {
    Enum[Enum["A"] = 0] = "A";
})(Enum || (Enum = {}));
var a = Enum.A;
var nameOfA = Enum[a]; // "A"

En este código generador, la constante múltiple se traduce en un objeto que almacena las asociaciones directas (nombre -> valor) e inversas (nombre -> valor). Las referencias a elementos de otras constantes múltiples son siempre acceso de propiedad y nunca en línea. Recuerde que los elementos de las constantes multi textuales no tienen una asociación inversa genérica.

Múltiples constantes que comienzan con const

Múltiples constantes es una buena solución en la mayoría de los casos, pero a veces los requisitos son más restrictivos. Para evitar pagar de más por el código generado al acceder a los valores de múltiples constantes, la palabra clave se puede usar const con múltiples constantes. Esto se puede hacer usando la palabra clave const con de la siguiente manera:

const enum Enum {
    A = 1,
    B = A * 2
}

Los polinomios const suelen usar expresiones de enumeración constante y, a diferencia de los polinomios regulares, se omiten por completo cuando se compilan. Los elementos const de las múltiples alineados en los sitios de uso. Esto es posible porque varias pueden tener elementos const calculados.

const enum Directions {
    Up,
    Down,
    Left,
    Right
}

let directions = [Directions.Up, Directions.Down, Directions.Left, Directions.Right]

El código generado será el siguiente:

var directions = [0 /* Up */, 1 /* Down */, 2 /* Left */, 3 /* Right */];

Enum ambientales

Los polinomios circundantes se utilizan para describir cómo se ven los tipos de enumeración preexistentes:

declare enum Enum {
    A = 1,
    B,
    C = 2
}

Una de las diferencias más importantes entre los enteros cerrados y no cerrados es que los elementos de un invariante ordinario que no tienen un inicializador se consideran invariantes si el elemento envolvente que los precede es una constante. En los polinomios circundantes (que no están precedidos por la palabra clave const) siempre se calculan los elementos que no tienen un inicializador.


Recursos del Artículo


Deja un comentario