export const AnatomyQuantityValues = [
"optional",
"exactly_one",
"one_or_more",
"zero_or_more",
] as const; AnatomyQuantityValues 是个值吗
是的,AnatomyQuantityValues 是一个运行时真实存在的值,具体来说是一个数组:
export const AnatomyQuantityValues = [
"optional",
"exactly_one",
"one_or_more",
"zero_or_more",
] as const;
你可以直接在代码运行时使用它:
console.log(AnatomyQuantityValues);
AnatomyQuantityValues.map((value) => {
console.log(value);
});
它的值就是:
[
"optional",
"exactly_one",
"one_or_more",
"zero_or_more",
]
as const 做了什么
如果不加 as const:
const values = ["optional", "exactly_one"];
TypeScript 通常会把它推断成:
string[]
也就是说,它只知道这是一个字符串数组,不关心里面具体有哪些字符串。
加上 as const:
const values = ["optional", "exactly_one"] as const;
TypeScript 会把它推断得非常精确:
readonly ["optional", "exactly_one"]
这表示:
- 数组内容是只读的;
- 第一个元素只能是
"optional"; - 第二个元素只能是
"exactly_one"。
因此下面这些操作会报错:
AnatomyQuantityValues.push("other");
// 报错:只读数组不能 push
AnatomyQuantityValues[0] = "other";
// 报错:不能修改只读元素
它既可以当值,也可以用来生成类型
你之前看到的:
(typeof AnatomyQuantityValues)[number]
就是从这个数组值中提取元素类型。
先看:
typeof AnatomyQuantityValues
得到的是这个值对应的类型:
readonly [
"optional",
"exactly_one",
"one_or_more",
"zero_or_more"
]
再加 [number]:
(typeof AnatomyQuantityValues)[number]
表示取这个数组所有数字索引位置可能出现的类型,最终得到:
"optional"
| "exactly_one"
| "one_or_more"
| "zero_or_more"
因此:
quantity?: (typeof AnatomyQuantityValues)[number]
等价于:
quantity?:
| "optional"
| "exactly_one"
| "one_or_more"
| "zero_or_more";
为什么要这样写
因为可以让“运行时值”和“TypeScript 类型”共用一份数据。
例如运行时可以用它生成下拉选项:
<select>
{AnatomyQuantityValues.map((value) => (
<option key={value} value={value}>
{value}
</option>
))}
</select>
同时又能得到对应的类型:
export type AnatomyQuantity =
(typeof AnatomyQuantityValues)[number];
然后使用:
const quantity: AnatomyQuantity = "optional"; // 正确
const quantity2: AnatomyQuantity = "many";
// 报错
这样就不用把相同内容写两遍:
// 不推荐:值和类型需要分别维护
type AnatomyQuantity =
| "optional"
| "exactly_one"
| "one_or_more"
| "zero_or_more";
const AnatomyQuantityValues = [
"optional",
"exactly_one",
"one_or_more",
"zero_or_more",
];
否则以后增加一个值时,可能只改了数组,却忘了修改类型。
可以记成:
AnatomyQuantityValues
是值;
typeof AnatomyQuantityValues
是这个值的类型;
(typeof AnatomyQuantityValues)[number]
是数组中所有元素组成的联合类型。