TS进阶之keyof

源码 2024-9-20 13:12:08 92 0 来自 中国
刷完了type-challenges的全部简单和中等难度的标题后,对TypeScript的范例操纵有了一些新的理解和认识。特此用几篇文章来记载下一些重要的知识点。
本系列文章必要您对TypeScript有根本的相识
根本用法

JavaScript通过Object.keys()获取对象的全下属性键值,而typescript重要关注的是范例操纵,通过 keyof 操纵符可以获取对象中的全部键范例构成的团结范例
为了具体相识keyof操纵符的作用,我们通过一些例子来表明下:
type Person = {  id: number;  name: string;  age: number;};type P1 = keyof Person; //'id' | 'name' | 'age'
keyof操纵符得到的是Person范例的全部键值范例即 'id','name'和'age' 三个字面量范例构成的团结范例'id' | 'name' | 'age'。
现实应用

接下来我会用一些例子解说keyof的应用。
获取对象全下属性的范例

type P2 = Person[keyof Person];  // number | string

  • Person['key'] 是查询范例(Lookup Types), 可以获取到对应属性范例的范例;
  • Person[keyof Person]本质上是实验 Person['id' | 'name' | 'age'];
  • 由于团结范例具有分布式的特性,Person['id' | 'name' | 'age'] 酿成了 Person['id'] | Person['name'] | Person['age'];
  • 末了得到的效果就是 number | string.
束缚范型参数的范围

type MyPick<T, K extends keyof T> = { [P in K]: T[P] };type P3 = MyPick<erson, 'id' | 'age'>

  • K extends keyof T对K举行了束缚,只能是'id','name','age'中的一个范例大概几个范例构成的团结范例;
  • 假如没有这个束缚,{ [P in K]: T[P] } 则会报错。
和映射范例组合实现某些功能


  • 给对象范例的全下属性加上readonly修饰符
type MyReadonly<T> = { readonly [P in keyof T]: T[P] };type P4 = MyReadonly<erson>;  // { readonly id: number; readonly name: string; readonly age: number; }

  • [P in keyof T]是对全下属性的键值范例举行遍历,案例中得到的P 分别是'id','name'和'age';
  • T[P]是查询范例,上面先容过了,Person['id'] 的效果是number,Person['name'] 的效果是string,Person['age'] 的效果是number。
  • 将每个属性范例添加readonly修饰符,末了的效果就是 { readonly id: number; readonly name: string; readonly age: number; }


  • 去掉对象范例的某些属性
微软官是通过Pick 和exclude组合来实现Omit逻辑的,我们可以通过以下的代码实现同样的功能。
type MyOmit<T, K> = { [P in keyof T as P extends K ? never : P]: T[P] };type P5 = MyOmit<erson, 'id' | 'name'> // {age: number;}
代码中的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<erson, 'address', string> // { address: string; id: number; name: string; age: number; }和条件范例组合实现功能


  • 两个对象范例归并成一个新的范例
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<erson, Skill>; // { id: number; name: string; age: number; run: () => void; }
案例中P extends keyof S ? X : Y 的部分叫做 条件范例(背面也会单独先容)。代码中的含义就是假如 P是F的属性范例,则取F[P],假如P是S的属性范例,则取S[P]。
小结

颠末前面的先容,应该对keyof的利用有一些感觉了。下面我列一些代码,各人可以感受下:
type _DeepPartial<T> = { [K in keyof T]?: _DeepPartial<T[K]> }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;};
这个实现逻辑涉及到了其他的知识点有点复杂,没完全看懂没关系,背面会先容。
您需要登录后才可以回帖 登录 | 立即注册

Powered by CangBaoKu v1.0 小黑屋藏宝库It社区( 冀ICP备14008649号 )

GMT+8, 2024-10-18 20:19, Processed in 0.114659 second(s), 32 queries.© 2003-2025 cbk Team.

快速回复 返回顶部 返回列表