TypeScript中如何限制对象键名的取值范围
当我们使⽤ TypeScript 时,我们想利⽤它提供的类型系统限制代码的⽅⽅⾯⾯,对象的键值,也不例外。
譬如我们有个对象存储每个年级的⼈名,类型⼤概长这样:
type Students = Record<string, string[]>;
理所当然地,数据就是长这样:
const students: Students = {
Freshman: ["David", "John"],
sophomore: [],
Junior: ["Lily"],
Senior: ["Tom"],
};
限制对象键名为枚举
上⾯数据类型的问题是,年级是有限的⼏种可值取,⽽该对象上可任意添加属性,这样显得数据不够纯粹。
所以我们新增枚举,列出可取的值:
export enum Grade {
Freshman,
sophomore,
Junior,
Senior,
}
现在,把对象的键名限制为上⾯枚举就⾏了。
- type Students = Record<string, string[]>;
+ type Students = Record<Grade, string[]>;
这样我们的数据可写成这样:
const students: Students = {
[Grade.Freshman]: ["David", "John"],
[Grade.sophomore]: [],
[Grade.Junior]: ["Lily"],
[Grade.Senior]: ["Tom"],
// Object literal may only specify known properties, and 'blah' does not exist in type 'Students'.ts(2322)
blah: ["some one"],
};
这样,限制住了对象⾝上键名的范围,可以看到如果添加⼀个枚举之外的键会报错。
更加语义化的枚举值
但上⾯的做法还是有不妥之处,因为枚举值默认是从 0 开始的数字,这样,作为键值就不够语义了,这点从访问对象的属性时体现了出来:
修正我们的枚举,⽤更加语义的⽂本作为其值:
export enum Grade {
Freshman = "Freshman",
sophomore = "sophomore",
Junior = "Junior",
Senior = "Senior",
}
此时再使⽤该枚举时,得到的就不是⽆意义的数字了。
如果你愿意,枚举值也可以是中⽂,
export enum Grade {
Freshman = "⼤⼀萌新",
sophomore = "⼤⼆学弟",
Junior = "⼤三学妹",
Senior = "⼤四⽼司机",
}
使⽤时也是没任何问题的:
键值可选
上⾯的类型定义还有个问题,即,它要求使⽤时对象包含枚举中所有值,⽐如sophomore这个年级中并没有⼈,可以不写,但会报错。
// Property 'sophomore' is missing in type '{ Freshman: string[]; Junior: string[]; Senior: string[]; }' but required in type 'Students'.ts(2741)typescript 字符串转数组
const students: Students = {
[Grade.Freshman]: ["David", "John"],
// [Grade.sophomore]: [],
[Grade.Junior]: ["Lily"],
[Grade.Senior]: ["Tom"],
};
所以,优化类型为可选:
type Students = Partial<Record<Grade, string[]>>;
假若可选的值不是通过枚举定义,⽽是来⾃⼀个数组,
const grades = ["Freshman", "sophomore", "Junior", "Senior"];
这意味着我们需要提取数组中的值形成⼀个联合类型。
⾸先利⽤const assertions把数组转元组(Tuple)类型,
const grades = <const>["Freshman", "sophomore", "Junior", "Senior"];
再利⽤typeof和Lookup Types得到最终的联合类型:
// 实际为 type Keys = "Freshman" | "sophomore" | "Junior" | "Senior"
type Keys = typeof grades[number];
最后数据类型和数据可写成:
type Students = Partial<Record<Keys, string[]>>;
const students: Students = {
Freshman: ["David", "John"],
Junior: ["Lily"],
Senior: ["Tom"],
};
须知这种形式下,对象的 key 与原数组中元素其实没有语法层⾯的关联,即,编辑器的「跳转定义」是不可⽤的。
尽量还是保持代码之间的关联才能体现出 TypeScript 的作⽤,所以像这种只有类型约束⽽⽆法建⽴关联的操作是不建议的。
相关资源
const assertions
keyof and Lookup Types
The text was updated successfully, but these errors were encountered:
以上就是TypeScript 中限制对象键名的取值范围的详细内容,更多关于TypeScript限制对象键名范围的资料请关注其它相关⽂章!
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论