¿Cuál es la diferencia entre enumeración y objeto en mecanografiado?

5 minutos de lectura

Estoy tratando de acceder a los valores de un mapa a través de una enumeración y también hacer una aplicación lista para traducir para todas las cadenas que contiene. Ambas preocupaciones se superponen y tengo que decidir entre usar enumeraciones o simplemente objetos en formato JSON.

Entonces, ¿cuál es exactamente la diferencia y el uso entre una enumeración y un objeto?

Por ejemplo:

  • Puedo usar enumeraciones para acceder a matrices, así como insertar etiquetas y otras cosas como
const enum FieldNames {
  FirstField: "Field One",
  SecondField: "Field Two"
};
    
someFieldArray[FieldNames.FirstField].label = FieldNames.FirstField;
someFieldArray[FieldNames.SecondField].label = FieldNames.SecondField;
  • O puedo lograr el mismo comportamiento a través del objeto.
const FieldNames = {
  FirstField: "Field One",
  SecondField: "Field Two"
};

someFieldArray[FieldNames.FirstField].label = FieldNames.FirstField;
someFieldArray[FieldNames.SecondField].label = FieldNames.SecondField;

Realmente no obtengo el beneficio de elegir enumeraciones sobre objetos simples. En mi opinión, un objeto tiene muchos más beneficios sin ningún inconveniente.

enumeración

Una enumeración puede brindarle beneficios adicionales, si desea las características:

const enum FieldNamesEnum {
  FirstField = "Field One",
  SecondField = "Field Two"
};

let x: FieldNamesEnum;

x = FieldNamesEnum.FirstField;
x = FieldNamesEnum.SecondField;

// Error - not assignable to FieldNames
x = 'str';

// Cannot assign
FieldNamesEnum.FirstField = 'str';

Es importante destacar que no puede asignar a los miembros de la enumeración y los tipos se verifican en los miembros de la enumeración, en lugar de en la cadena.

Además, debido a que ha utilizado un const enum en su ejemplo, la enumeración no existirá en tiempo de ejecución y todas las referencias se sustituirán por los valores literales (si usó un simple enum la enumeración haría existen en tiempo de ejecución).

Objeto

Compare esto con el ejemplo del objeto:

const FieldNames = {
  FirstField: "Field One",
  SecondField: "Field Two"
};

let y: string;

y = FieldNames.FirstField;
y = FieldNames.SecondField;

// Oops it works
y = 'str';

// Oops it works

FieldNames.FirstField = 'str';

Unión

Si no necesita la enumeración completa, pero desea limitar los valores, puede usar una unión de valores literales:

type FieldNames = "Field One" | "Field Two";

let x: FieldNames;

x = "Field One";
x = "Field Two";

// Error - not allowed
x = "Field Three";

  • Pero, ¿es posible hacer enumeraciones encapsuladas?

    – Florian Leitgeb

    17 de noviembre de 2017 a las 13:34

  • fabulosa explicación!! Especialmente el relacionado con la no asignación de miembros de enumeración.

    – Shanti

    29 de noviembre de 2018 a las 7:15

  • El problema con su solución es que establece el tipo de y a string y no al tipo real de los valores de la FieldNames objeto que debería ser el de @Martynas Skučas a continuación. Aquí está el enlace: stackoverflow.com/a/59932722/1681085

    – Florian Leitgeb

    4 de febrero de 2020 a las 15:40

No estoy de acuerdo con @Fenton. Los objetos son del tipo seguro.

const FieldNames = {
  FirstField: 'Field One',
  SecondField: 'Field Two',
} as const;

type ValueOf<T> = T[keyof T];
let y: ValueOf<typeof FieldNames>;

y = FieldNames.FirstField;
y = FieldNames.SecondField;

// TS2322: Type '"str"' is not assignable to type '"Field One" | "Field Two"'.
y = 'str';

// TS2540: Cannot assign to 'FirstField' because it is a read-only property
FieldNames.FirstField = 'str';

  • Me gusta tu forma de pensar. Ajuste y escribir una cadena no es la mejor manera. Muy buena respuesta en mi opinión. Sin embargo, no responde toda la pregunta.

    – Florian Leitgeb

    4 de febrero de 2020 a las 15:38

  • as const se introdujo en TS 3.4, que se lanzó en 2019. Y la respuesta original de @Fenton se publicó en 2017. Creo que esta es una respuesta actualizada válida. También, de hecho, los documentos oficiales de TS ahora dicen que la mayoría de las veces as const puede funcionar para reemplazar enum.

    – dios genial

    18 de junio de 2021 a las 5:39


  • @coolgod, ¿puede indicarme dónde en los documentos se dice “como const reemplazará a la enumeración la mayor parte del tiempo”? Podría encontrarlo.

    –Edu Ruiz

    29 de julio de 2021 a las 15:10

  • @EduRuiz typescriptlang.org/docs/handbook/enums.html#objects-vs-enums

    – Róbula

    21 de septiembre de 2021 a las 12:56

function (foo: FieldNames) { }

Si FieldNames es un objeto, esto significa que esta función espera una instancia que tenga las propiedades FirstField y SecondField. Si FieldNames es una enumeración (en cuyo caso debe ser singular, no plural), esto significa que la función espera uno de los valores de FieldNamesa saber "Field One" o "Field Two".

Uso muy diferente.

  • Pero puede lograr ese comportamiento simplemente usando interfaces y/o clases.

    – Florian Leitgeb

    17 de noviembre de 2017 a las 13:11

  • ¿Cómo se define fácilmente una interfaz o clase que dice “uno de estos valores”?

    – deceze

    17 de noviembre de 2017 a las 13:12

  • ¿Una clase abstracta con propiedades estáticas FieldName? O algo así.

    – Florian Leitgeb

    17 de noviembre de 2017 a las 13:14

  • Una enumeración como sugerencia de tipo dice “la variable puede tomar uno de los valores en esta lista”. Una enumeración como objeto hace que esos valores sean fácilmente accesibles por algo como constantes (por ejemplo, FieldName.FirstField); puede cambiar el valor subyacente sin necesidad de volver a escribir todo el código que lo usa. – Todo eso es muy diferente de las clases/objetos, en los que puede instanciar un objeto de una clase y pasar ese objeto y escribir sugerencias contra el tipo de objeto.

    – deceze

    17 de noviembre de 2017 a las 13:20

  • Tu puedes hacer function (foo: keyof FieldNames) { } en cambio

    – Daniel Kucal

    03/02/2018 a las 18:30

En el manual del lenguaje TypeScript, tiene una sección dedicada que habla de eso: Objetos vs enumeraciones.

Personalmente, cuando necesito un tipo con un conjunto de opciones, prefiero usar la enumeración Typescript, porque es más fácil de usar. Con la definición de enumeración, tiene el tipo y también la forma de acceder a las opciones. Para implementar el mismo enfoque con un objeto, debe definir el objeto as const y también definir un tipo adicional basado en él.

esta debería ser la razón principal … puede usar enum como un tipo para una de las siguientes opciones, pero no puede definir el objeto cosnt como un tipo, tendrá todas las opciones en un obj 🙂

también puedes hacer esto

type FieldNames = "Field One" | "Field Two";

pero si la lista es larga, la enumeración es mucho mejor, en ES6 la enumeración es puramente inútil, solo use obejct pero en mecanografiado es un tipo y es un beneficio principal en mi opinión

¿Ha sido útil esta solución?