AI智能
改变未来

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)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限制对象键名范围的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:

  • Vue 中使用 typescript的方法详解
  • vue框架中props的typescript用法详解
  • Vue-cli3项目引入Typescript的实现方法
  • vue + typescript + video.js实现 流媒体播放 视频监控功能
  • Typescript 中的 interface 和 type 到底有什么区别详解
  • vue中typescript装饰器的使用方法超实用教程
  • 手把手教你使用TypeScript开发Node.js应用
赞(0) 打赏
未经允许不得转载:爱站程序员基地 » TypeScript 中如何限制对象键名的取值范围