知名网站建设定制TS进阶之keyof

知名网站建设定制刷完了的所有简单和中知名网站建设定制等难度的题目后,对TypeScript知名网站建设定制的类型操作有了一些新知名网站建设定制的理解和认识。知名网站建设定制特此用几篇文章来记录下一些重要的知识点。

本系列文章需要您对TypeScript有基本的了解

基本用法

JavaScript通过 Object.keys()获取对象的所有属性键值,而typescript主要关注的是类型操作,通过 keyof 操作符可以获取对象中的所有键类型组成的联合类型

为了具体了解keyof操作符的作用,我们通过一些例子来解释下:

type Person = {  id: number;  name: string;  age: number;};type P1 = keyof Person; //'id' | 'name' | 'age'
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

keyof操作符得到的是Person类型的所有键值类型即 'id','name''age' 三个字面量类型组成的联合类型'id' | 'name' | 'age'

实际应用

接下来我会用一些例子讲解keyof的应用。

获取对象所有属性的类型
type P2 = Person[keyof Person];  // number | string
  • 1
  1. Person['key']查询类型(Lookup Types), 可以获取到对应属性类型的类型;
  2. Person[keyof Person]本质上是执行 Person['id' | 'name' | 'age']
  3. 由于联合类型具有分布式的特性,Person['id' | 'name' | 'age'] 变成了 Person['id'] | Person['name'] | Person['age']
  4. 最后得到的结果就是 number | string.
约束范型参数的范围
type MyPick<T, K extends keyof T> = { [P in K]: T[P] };type P3 = MyPick<Person, 'id' | 'age'>
  • 1
  • 2
  • 3
  1. K extends keyof TK进行了约束,只能是'id','name','age'中的一个类型或者几个类型组成的联合类型;
  2. 如果没有这个约束,{ [P in K]: T[P] } 则会报错。
和映射类型组合实现某些功能
  • 给对象类型的所有属性加上readonly修饰符
type MyReadonly<T> = { readonly [P in keyof T]: T[P] };type P4 = MyReadonly<Person>;  // { readonly id: number; readonly name: string; readonly age: number; }
  • 1
  • 2
  1. [P in keyof T]是对所有属性的键值类型进行遍历,案例中得到的P 分别是'id','name''age';
  2. T[P]是查询类型,上面介绍过了,Person['id'] 的结果是numberPerson['name'] 的结果是stringPerson['age'] 的结果是number
  3. 将每个属性类型添加readonly修饰符,最后的结果就是 { readonly id: number; readonly name: string; readonly age: number; }
  • 去掉对象类型的某些属性

微软官是通过Pickexclude组合来实现Omit逻辑的,我们可以通过以下的代码实现同样的功能。

type MyOmit<T, K> = { [P in keyof T as P extends K ? never : P]: T[P] };type P5 = MyOmit<Person, 'id' | 'name'> // {age: number;}
  • 1
  • 2

代码中的as P extends K ? never : P这部分代码叫做重映射 ,因为我们不一定需要的是P,有些情况下需要对P进行一些转换;案例中K 中包含的P键值类型则通过never忽略了,相反则保留。所以最后的结果是{age: number;}

  • 给对象类型添加新的属性
type AppendToObject<T, U extends keyof any, V> = {[P in keyof T | U]: P extends keyof T ? T[P] : V}type P6 = AppendToObject<Person, 'address', string> // { address: string; id: number; name: string; age: number; }
  • 1
  • 2
和条件类型组合实现功能
  • 两个对象类型合并成一个新的类型
type Merge<F extends Record<string, any>, S extends Record<string, any>> = {  [P in keyof F | keyof S]: P extends keyof S ? S[P] : P extends keyof F ? F[P] : never;};type Skill = {  run: () => void;}type P7 = Merge<Person, Skill>; // { id: number; name: string; age: number; run: () => void; }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

案例中P extends keyof S ? X : Y 的部分叫做 条件类型(后面也会单独介绍)。代码中的含义就是如果 PF的属性类型,则取F[P],如果PS的属性类型,则取S[P]

小结

经过前面的介绍,应该对keyof的使用有一些感觉了。下面我列一些代码,大家可以感受下:

type _DeepPartial<T> = { [K in keyof T]?: _DeepPartial<T[K]> }
  • 1
type Diff<T extends Record<string, any>, U extends Record<string, any>> = {  [P in keyof U | keyof T as P extends keyof U    ? P extends keyof T      ? never      : P    : P extends keyof T    ? P    : never]: P extends keyof U ? U[P] : P extends keyof T ? T[P] : never;};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

这个实现逻辑涉及到了其他的知识点有点复杂,没完全看懂没关系,后面会介绍。

网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发