可以使用枚举来限制值吗?
Possible to use enums to restrict values?
我们可以使用如下文字类型轻松限制支持的值
type GenderConfig = {
gender: 1 | 0
}
const obj: GenderConfig = {
gender: 100 // throw error because value is not 1 or 0
}
现在我想尽可能避免幻数 1
& 0
所以我尝试为此定义一个枚举
enum Gender {
MALE= 1,
FEMALE=0,
}
type GenderConfig = {
gender: Gender
}
const obj: GenderConfig = {
gender: 100 // This doesn't throw error anymore?
}
令人惊讶的是,gender: 100
不再抛出错误,我不明白这背后的原理?
我不再经常使用枚举了,因为它们有点复杂。也许这在某种程度上是可能的,但您可以改用这样的字符串:
type Gender = 'female' | 'male';
type GenderConfig = {
gender: Gender
}
当然,如果您在某些时候确实需要数字表示,您可能需要添加一些映射。
您在这里创建的是一个数字枚举。生成的 JavaScript 如下所示:
var Gender;
(function (Gender) {
Gender[Gender["MALE"] = 1] = "MALE";
Gender[Gender["FEMALE"] = 0] = "FEMALE";
})(Gender || (Gender = {}));
在控制台中,此对象如下所示:
Object
0: "FEMALE"
1: "MALE"
FEMALE: 0
MALE: 1
在幕后,枚举实际上只是一个具有属性的 JavaScript 对象。它具有您定义的命名属性,
并为它们分配了一个数字,表示它们在枚举中的位置(FEMALE 为 0,MALE 为 1),但是
该对象还具有数字键,其字符串值表示命名常量。
因此,您可以将数字传递给需要枚举的函数。枚举本身既是数字又是定义的常量。
这似乎破坏了 TypeScript 的类型安全方面,因为您可以将任意数字传递给需要此枚举的函数。
不过,这有两个有用的原因:
- 当您收到数字数据时(例如,在来自某些服务的 JSON 负载中),您可以将其转换为枚举。
- 由于枚举成员具有数值,您也可以将它们用作位标志(尽管您可以设置数值
对于每个枚举成员,正如您在此处所做的那样,这可能会或可能不会很好地工作)。
关于第 (1) 点:如果您声明一个没有数值的枚举,例如这个:
enum Gender {
MALE = "Male",
FEMALE = "Female"
}
那你就不能再这样做了:
const gender: Gender = "Male";
您必须进行显式转换:
const gender = "Male" as Gender;
const MALE = 1;
const FEMALE = 0;
type Gender = typeof MALE | typeof FEMALE;
type GenderConfig = {
gender: Gender
}
const obj: GenderConfig = {
gender: 100 // This is now throwing error
}
我没有使用 enums
,而是将其更改为 type
并且通过使用 const
和 typeof
的组合,我可以避免幻数并提高可读性和一致性,感谢其他人的解释
我们可以使用如下文字类型轻松限制支持的值
type GenderConfig = {
gender: 1 | 0
}
const obj: GenderConfig = {
gender: 100 // throw error because value is not 1 or 0
}
现在我想尽可能避免幻数 1
& 0
所以我尝试为此定义一个枚举
enum Gender {
MALE= 1,
FEMALE=0,
}
type GenderConfig = {
gender: Gender
}
const obj: GenderConfig = {
gender: 100 // This doesn't throw error anymore?
}
令人惊讶的是,gender: 100
不再抛出错误,我不明白这背后的原理?
我不再经常使用枚举了,因为它们有点复杂。也许这在某种程度上是可能的,但您可以改用这样的字符串:
type Gender = 'female' | 'male';
type GenderConfig = {
gender: Gender
}
当然,如果您在某些时候确实需要数字表示,您可能需要添加一些映射。
您在这里创建的是一个数字枚举。生成的 JavaScript 如下所示:
var Gender;
(function (Gender) {
Gender[Gender["MALE"] = 1] = "MALE";
Gender[Gender["FEMALE"] = 0] = "FEMALE";
})(Gender || (Gender = {}));
在控制台中,此对象如下所示:
Object
0: "FEMALE"
1: "MALE"
FEMALE: 0
MALE: 1
在幕后,枚举实际上只是一个具有属性的 JavaScript 对象。它具有您定义的命名属性, 并为它们分配了一个数字,表示它们在枚举中的位置(FEMALE 为 0,MALE 为 1),但是 该对象还具有数字键,其字符串值表示命名常量。
因此,您可以将数字传递给需要枚举的函数。枚举本身既是数字又是定义的常量。
这似乎破坏了 TypeScript 的类型安全方面,因为您可以将任意数字传递给需要此枚举的函数。 不过,这有两个有用的原因:
- 当您收到数字数据时(例如,在来自某些服务的 JSON 负载中),您可以将其转换为枚举。
- 由于枚举成员具有数值,您也可以将它们用作位标志(尽管您可以设置数值 对于每个枚举成员,正如您在此处所做的那样,这可能会或可能不会很好地工作)。
关于第 (1) 点:如果您声明一个没有数值的枚举,例如这个:
enum Gender {
MALE = "Male",
FEMALE = "Female"
}
那你就不能再这样做了:
const gender: Gender = "Male";
您必须进行显式转换:
const gender = "Male" as Gender;
const MALE = 1;
const FEMALE = 0;
type Gender = typeof MALE | typeof FEMALE;
type GenderConfig = {
gender: Gender
}
const obj: GenderConfig = {
gender: 100 // This is now throwing error
}
我没有使用 enums
,而是将其更改为 type
并且通过使用 const
和 typeof
的组合,我可以避免幻数并提高可读性和一致性,感谢其他人的解释