打字稿中的枚举和对象有什么区别

Flo*_*geb 22 javascript enums object typescript

我试图通过枚举访问地图的值,并为其中的所有字符串创建一个翻译就绪的应用程序.两个问题都重叠,我必须决定使用枚举还是只使用JSON格式的对象.

那么枚举和对象之间的区别和用途到底是什么?

例如:

  • 我可以使用枚举来访问数组以及插入标签和其他东西

const enum FieldNames {
  FirstField: "Field One",
  SecondField: "Field Two"
};
    
someFieldArray[FieldNames.FirstField].label = FieldNames.FirstField;
someFieldArray[FieldNames.SecondField].label = FieldNames.SecondField;
Run Code Online (Sandbox Code Playgroud)

  • 或者我可以通过对象实现相同的行为

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

someFieldArray[FieldNames.FirstField].label = FieldNames.FirstField;
someFieldArray[FieldNames.SecondField].label = FieldNames.SecondField;
Run Code Online (Sandbox Code Playgroud)

我真的没有从简单对象中选择枚举的好处.在我看来,一个对象有更多的好处,没有任何缺点.

Fen*_*ton 25

枚举

如果您需要以下功能,enum可能会为您提供额外的好处:

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';
Run Code Online (Sandbox Code Playgroud)

重要的是,您不能将枚举成员和类型分配给枚举成员,而不是字符串.

另外,因为您const enum在示例中使用了a ,所以枚举在运行时不会存在,并且所有引用都将替换文字值(如果您使用了enum枚举,则枚举在运行时存在).

宾语

将此与对象示例进行比较:

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';
Run Code Online (Sandbox Code Playgroud)

联盟

如果您不需要完整的枚举,但想要限制值,则可以使用文字值的并集:

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

let x: FieldNames;

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

// Error - not allowed
x = "Field Three";
Run Code Online (Sandbox Code Playgroud)

  • 精彩的解释!!特别是与未分配枚举成员相关的问题。 (2认同)

小智 14

我不同意@Fenton。对象是类型安全的。

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';
Run Code Online (Sandbox Code Playgroud)

  • `as const` 是在 2019 年发布的 TS 3.4 中引入的。@Fenton 的原始答案于 2017 年发布。我认为这是一个有效的更新答案。事实上,TS 官方文档现在表示,大多数情况下“as const”可以用来替代 enum。 (6认同)
  • @EduRuiz https://www.typescriptlang.org/docs/handbook/enums.html#objects-vs-enums (3认同)
  • 我喜欢你的想法。将 y 设置为字符串并不是最好的方法。我认为非常好的答案。然而,它并没有回答整个问题。 (2认同)

dec*_*eze 6

function (foo: FieldNames) { }
Run Code Online (Sandbox Code Playgroud)

如果FieldNames是一个对象,这意味着该函数需要一个具有属性FirstField和的实例SecondField.如果FieldNames是枚举(在这种情况下它应该是单数,而不是复数),这意味着函数需要其中一个值FieldNames,即"Field One""Field Two".

用法差异很大.

  • 枚举作为类型提示表示“变量可能采用此列表中的值之一”。作为对象的枚举使这些值可以通过常量(例如`FieldName.FirstField`)之类的东西轻松访问;您可以更改基础值,而无需重写所有使用它的代码。– 这与类/对象完全不同,在类/对象中,您可以从类中实例化一个对象并传递该对象并针对对象类型进行类型提示。 (2认同)
  • 你可以做 `function (foo: keyof FieldNames) { }` 代替 (2认同)

Jos*_*igo 5

在 Typescript 语言手册中,有一个专门的部分讨论这一点:对象与枚举

就我个人而言,当我需要带有一组选项的类型时,我更喜欢使用 Typescript 枚举,因为它更易于使用。通过枚举定义,您可以获得类型以及访问选项的方式。要使用对象实现相同的方法,您需要定义该对象as const并基于它定义一个额外的类型。