使用as const
比enum
有什么优缺点?比如轻微的性能优势等。
enum Links {
Link1 = 'test1',
Link2 = 'test2',
}
const Links = {
Link1: 'test1',
Link2: 'test2',
} as const;
让我们将字符串enum
s 与具有字符串文本属性值的const
断言对象文本进行比较!
总结:
- 性能是一样的
enum
带来了命名值、命名类型和命名命名空间的存在,如果您希望在没有enum
的情况下单独完成。- 字符串
enum
是string
的名义子类型,不能与其字符串文本值互换。
我们可以先放弃性能。 几乎可以肯定,它们之间没有有意义的性能差异。 两个版本在运行时的行为相同:您只有一个名为Links
的对象,其中包含两个属性。 而且我也从未注意到编译器有什么不同;无论哪种方式都很快。 如果性能是一个问题,那么您的enum
太大或您有太多。
现在有一些实际明显的差异。 请注意,这种差异在一种情况下可以被视为优点,但在另一种情况下可被视为劣势。 这实际上取决于用例。 因此,让我们看一下字符串enum
,看看在不使用enum
的情况下我们可以多么接近它:
enum Links {
Link1 = 'test1',
Link2 = 'test2',
}
将Links
声明为enum
会将一些事项纳入范围:
- 一个名为
Links
的值;一个在运行时存在并具有字符串值属性的对象Links.Link1
可分配给"test1"
Links.Link2
可分配给"test2"
的对象。 - 名为
Links
的类型;Links
对象的可能值的并集。作为一种类型,它只存在于编译时。 例如,您可以编写interface Foo { link: Links }
来表示Foo
必须具有Links.Link1
或Links.Link2
的link
属性。 - 名为
Links
的命名空间,导出的类型名为Links.Link1
和Links.Link2
,它们分别对应于名为Links.Link1
和Links.Link2
的值的类型。 例如,您可以编写interface Bar extends Foo { link: Links.Link1 }
来表示Bar
必须具有正好Links.Link1
的link
属性。 这种事情对于建立歧视性的工会很方便。
你可以自己模拟每一个,而无需声明enum
,并获得在运行时和编译时的行为与字符串枚举非常相似(但不完全相同)的东西:
const Links = {
Link1: 'test1',
Link2: 'test2',
} as const;
type Links = (typeof Links)[keyof typeof Links];
namespace Links {
export type Link1 = typeof Links.Link1;
export type Link2 = typeof Links.Link2;
}
因此,enum
语法的一个可能的优点是:如果你想将Links
用作值、类型和命名空间,这会自动发生;而要在没有enum
的情况下获得相同的效果需要相当多的样板代码。 另一方面,如果你不关心类型或命名空间,你可以写const Links = {...}
,而不是把这些不需要的东西变成存在。
如果上述const
+type
+namespace
与enum
不相同,有什么区别?
编译器将enum
视为类似于string
的特殊名义子类型。 对于enum
,Links.Link1
的类型可分配给字符串文字"test1
",但不能从字符串文字">中分配:
const to: "test1" = Links.Link1; // okay either way
const from: Links.Link1 = "test1"; // error for enum, okay for const
因此,如果您希望Links.Link1
与字符串文字"test1
"完全互换,那么您应该远离enum
。 另一方面,如果要强制要求获取该"test1"
值的唯一方法是写出Links.Link1
,则应使用enum
。
这意味着字符串enum
的理想用法是将值大多视为不透明。如果enum
的用户实际上关心其特定的字符串文本值,则表明您可能并不真正想要enum
。 例如,假设我将Links
定义更改为:
enum Links {
Link1 = '454353',
Link2 = 'xxxyyyzzz',
}
如果我的其余代码对该更改感到满意,那是因为我只通过索引到Links
来引用枚举值。 任何直接提及"test2"
的代码都会中断,但提及Links.Links2
的代码将继续工作。
不知道性能取决于你如何在某些条件下像气泡排序一样使用它,在其他条件下插入排序。您应该使用数据相互关联的枚举,例如用于登录的用户类型是
enum typeOfUser{
owner='ower',
employee='employee',
admin='admin'
}
其中 as const 可用于不需要更改的值,如果您想应用与上面提到的枚举相同的代码,您可以执行类似操作。
export const typeOfUsers = ['employee', 'owner', 'admin'] as const;
export type typeOfUser = typeof typeOfUsers[number];
枚举将您限制为必要的输入集,而常量字符串允许您使用不属于逻辑的字符串。这可确保在输入数据时输入不在域中的内容不会出错,并且还可以提高代码的可读性。