实际上有三种不同的方法:
类型
允许您指定限制为给定值的类型。由于它们不生成任何代码,因此它们实际上就像在编译时存在但在运行时不存在的枚举。当您处理返回预定义值的 REST API 时,它们很有用;例如:
type Stage = "stage1" | "stage2";
function fnByType(value: Stage) {
}
fnByType("stage1"); // OK
fnByType("stage2"); // OK
fnByType("stage3"); // Not assignable!
枚举
允许您指定限制为给定值的枚举。它们确实生成代码,因此存在于编译时和运行时。因为它们存在于运行时,所以您可以枚举它们的所有键和值;例如:
enum Stage {
Stage1 = "stage1",
Stage2 = "stage2"
}
function fnByEnum(value: Stage) {
}
fnByEnum(Stage.Stage1); // OK
fnByEnum(Stage.Stage2); // OK
fnByEnum("stage1") // Not assignable!
fnByEnum("stage3") // Not assignable!
console.log(Object.keys(Stage)); // ["Stage1", "Stage2"]
console.log(Object.values(Stage)); // ["stage1", "stage2"]
常量
允许您定义一个新的常量(只读)变量。当您想避免诸如“魔术值”(读者实际上不知道其用途,但在您的代码中意味着某些东西的值)之类的事情时,这很有用,这意味着您可以更好地解释您的代码在做什么。此外,它支持 DRY(不要重复自己)原则,因为您可以引用 const 值,而不是在代码中重复“魔术值”。最后,这意味着如果您需要更新 const 值,您不必在代码中搜索该值的所有实例;您只需更新一次;例如:
const STAGE1: string = "stage1";
const STAGE2: string = "stage2";
function fnByString(value: string) {
}
fnByString(STAGE1); // OK
fnByString(STAGE2); // OK
fnByString("stage3"); // OK...but re-read the benefits of NOT using "magic values"
您可以互换使用所有三个概念,并相互补充;例如:
type Stage = "stage1" | "stage2";
const STAGE1: string = "stage1";
const STAGE2: string = "stage2";
function fnByType(value: Stage) {
}
fnByType(STAGE1); // OK
fnByType(STAGE2); // OK
fnByType("stage3"); // Not assignable!
最后,值得深思。如果您可以定义 const 值,然后使用它们来定义一种预定义值,那就太好了,但据我所知,以下是不可能的(目前):
const STAGE1: string = "stage1";
const STAGE2: string = "stage2";
type Stage = STAGE1 | STAGE2;
function fnByType(value: Stage) {
}
fnByType(STAGE1); // OK
fnByType(STAGE2); // OK
fnByType("stage3"); // Not assignable!