TypeScript 泛型使用2-常见的工具类型

hucheng91:TypeScript 泛型使用1​zhuanlan.zhihu.com

接上篇,这篇梳理下TypeScript 封装了很多常见的基于泛型类型工具,把常见的列举出来

Partial

这个类型“函数”的作用,在于给定一个输入的 object 类型 T,返回一个新的 object 类型,这个 object 类型的每一个属性都是可选的。 我们可以用基本的关键字来用自己的方式实现这个工具类型:

type MyPartial<T> = {[K in keyof T]?: T[K];
};
type PartialUser = MyPartial<User>;
// {name?: string, age?: number}
type TUserKeys = keyof User;
// 'name' | 'age'
type TName = User["name"];
// string
type TAge = User["age"];
// number
type TUserValue = User[TUserKeys];
// string | number

Required

这个类型“函数”的作用 是标记属性都是必须的,举个例子:

interface Props {a?: number;b?: string;
}const obj: Props = { a: 5 };const obj2: Required<Props> = { a: 5 };
// Property 'b' is missing in type '{ a: number; }' but required in type 'Required<Props>'.

Required 具体代码实现如下:

type MyRequired<T> = {[K in keyof T]-?: T[K];
};

Readonly

转换成只读

interface Todo {title: string;
}const todo: Readonly<Todo> = {title: "Delete inactive users",
};todo.title = "Hello";
// Cannot assign to 'title' because it is a read-only property.// 具体实现
type MyReadonly<T> = {readonly [K in keyof T]: T[K];
};

Mutable

把ReadOnly 转换成可编辑,一般不会用这种写法,因为定义了readonly,又去改变,会很流氓

type MyMutable<T> = {  -readonly [K in keyof T]: T[K];};interface User1 {readonly id: number;readonly name: string;
}
const user1: MyMutable<User1> = {id: 1,name: "test"
}
user1.id = 35

Record

Record 表示把 Type做成做key 对应值的类型,组成一个新的类型,这个非常实用,实际开发中,经常会遇到这种类型组装的问题,案例如下:

interface PageInfo {title: string;
}type Page = "home" | "about" | "contact";const nav: Record<Page, PageInfo> = {about: { title: "about" },contact: { title: "contact" },home: { title: "home" },
};
// 这里 nav 对应的类型就是一个重新组装的
nav.about;
// ^ = const nav: Record

对应实现如下:

type MyRecord<K extends keyof any, T> = {[P in K]: T;
};
type TKeyofAny = keyof any;
// string | number | symbol
type TKeys = "a" | "b" | 0;
type TKeysUser = MyRecord<TKeys, User>;
// {a: User, b: User, 0: User}

Pick<Type, Keys>

这个用的特别多,表示从一个类型里取出你需要用的类型,组成一个新类型,案例如下:

interface Todo {title: string;description: string;completed: boolean;
}type TodoPreview = Pick<Todo, "title" | "completed">;// 这里 todo类型就是 只有 title 和 completed 2个属性了
const todo: TodoPreview = {title: "Clean room",completed: false,
};

对应实现如下:

type MyPick<T, K extends keyof T> = {[P in K]: T[P];
};
type TNameKey = "id";
type TUserName = MyPick<User, TNameKey>;
// {id: number}

Exclude、Extract、NonNullable

这 3 个比较像,放到一起

Exclude

取排除 ExcludedUnion 的属性

type T0 = Exclude<"a" | "b" | "c", "a">;
//    ^ = type T0 = "b" | "c"
type T1 = Exclude<"a" | "b" | "c", "a" | "b">;
//    ^ = type T1 = "c"
type T2 = Exclude<string | number | (() => void), Function>;
//    ^ = type T2 = string | number

Extract

取 2 者相同的部分

type T0 = Extract<"a" | "b" | "c", "a" | "f">;
//    ^ = type T0 = "a"
type T1 = Extract<string | number | (() => void), Function>;
//    ^ = type T1 = () => void

NonNullable

取非 null,undefined 部分

type T0 = NonNullable<string | number | undefined>;
//    ^ = type T0 = string | number
type T1 = NonNullable<string[] | null | undefined>;
//    ^ = type T1 = string[]

三者对应实现

type MyExclude<T, U> = T extends U ? never : T;
type MyExtract<T, U> = T extends U ? T : never;
type MyNonNullable<T> = T extends null | undefined ? never : T;

Omit``<Type, Keys>

和 Pick 对应的,我们有时候一个 类型属性非常多,我可能是想排除某几个属性,把剩下的组成一个新类型,就需要 Omit 了,案例如下:

interface Todo {title: string;description: string;completed: boolean;
}
// 排除掉  description 属性,留下其他的
type TodoPreview = Omit<Todo, "description">;const todo: TodoPreview = {title: "Clean room",completed: false,
};

对应代码实现:

type MyOmit<T, K> = Pick<T, Exclude<keyof T, K>>;
type OmitUser = MyOmit<User, "age">;
// { name: string }

ConstructorParameters

取出 构造函数的参数类型,构造函数也就是我们常看到的 new (...args: any) => any,要取到 args,案例如下:

class User {constructor(id: string, name: number) {}}type Params = ConstructorParameters<typeof User>// [id: number, name: string]

这样 Params 就就是 class User 参数类型了,我们在往前走一步,把 User 改成一个抽象类,这个时候就会报错

因为 抽象类是没有 new (...args: any) => any) 这属性的,这个时候改变下

abstract class User {constructor(id: number, name: string) {}}
type ConstructorHelper<T> = (new (...args: any) => any) & T;
type ContructorParameters<T> = ConstructorParameters<ConstructorHelper<T>>;
type Params2 = MyConstructorParameters<typeof User>;
// [id: number, name: string]

又可以愉快的玩耍了,所以 ConstructorParameters 的特点是记住需要有 new (...args: any) => any) 类型

InstanceType

InstanceType 是表示构造函数的类型,也就是 我们常说的 class 类型,案例如下:

class User {id: number;name: string;constructor(id: number, name: string) {}say() {}}
type Ins = InstanceType<typeof User>;
const mm: Ins = new User(1, '王二');

代码实现:

type MyInstanceType<T extends new (...args: any) => any> = T extends new (...args: any
) => infer R? R: any;

其他

以下几个类型,平常基本没有到,列举出来,具体看文档

  • ThisParameterType
  • OmitThisParameter
  • ThisType

实用typescript_TypeScript 泛型使用2-常见的工具类型相关推荐

  1. TaxonKit:小巧、高效、实用的NCBI分类学数据命令行工具

    TaxonKit: 小巧.高效.实用的NCBI分类学数据命令行工具集 宏基因组按:NCBI物种分类注释信息格式复杂,存在层级不整齐.缺失.名称变动等问题,在使用中存在一定困难.最近发现了一款分类信息查 ...

  2. (10)Java泛型-Map集合-集合框架工具类-可变参数-静态导入

    -- 部分1.5新特性Java泛型-Map集合-集合框架工具类 泛型 概述: JDK1.5版本以后出现的新特性,用于解决安全问题,是一个类型安全机制. 对于泛型可以这样理解: 没有使用泛型时,只要是对 ...

  3. 实用手册:11种常见滤镜及使用效果

    实用手册:11种常见滤镜及使用效果 2015-06-23 16:20   来源:新摄影网      如果你是才刚刚入坑的摄影新手,相信对市场上琳琅满目的滤镜产品产生过疑问,保护镜是什么?UV镜有什么效 ...

  4. Linux下四款常见远程工具比较

    摘要:Linux远程可不像Windows下那么方便,主要是连接的速度.显示的画质不能令人满意(延迟.撕裂).本文只是说一下我用过的四款远程工具.Anydesk官网:https://anydesk.co ...

  5. PS 的常见抠图工具

    PS 的常见抠图工具 1. 套索工具 2. 多边形套索工具 3. 磁性套索工具 4. 对象套索工具 5. 快速套索工具 6. 魔棒工具 7. 其他 1. 套索工具 能完成快速抠图, 缺点是不好控制. ...

  6. 黑客攻击入侵流程及常见攻击工具

    黑客攻击入侵流程及常见攻击工具 1. 踩点 (Footprinting) 踩点目的: 主动获取信息情报, 确定目标域名系统, 网络地址范围, 名字空间, 关键系统,如网关.邮件.服务器等设置 踩点相关 ...

  7. TypeScript 实用工具类型之 Pick 类型

    TypeScript 实用工具类型之 Pick 类型 TypeScript 实用工具类型之 Pick 类型 1. 什么是对象类型转换? 2. 什么是 TypeScript Pick? 2.1 用 Pi ...

  8. 【TS】1368- 秒懂 TypeScript 泛型工具类型!

    阿宝哥精心准备的<轻松学 TypeScript> 视频教程已经更新到第十九期了,合集播放量已达 14W+.通过形象生动的动画,让你轻松搞懂 TypeScript 的难点和核心知识点! 如果 ...

  9. 常见远程控制工具协议(MSRDP/VNC/TEAMVIEWER/PCANYWHERE/TELNET)检测

    前言: 最近因项目需求,简单研究了一下常见远程工具协议,编写了简单的suricata检测规则,在此做个小结,记录一下.

最新文章

  1. 深圳大学 c语言,深圳大学C语言实验(3页)-原创力文档
  2. ES6系列之小知识点
  3. Oracle 变量绑定与变量窥视合集系列三
  4. 【题意+解析】1041 Be Unique (20 分)_18行代码AC
  5. python爬虫登录网站_python爬虫19 | 遇到需要的登录的网站怎么办?用这3招轻松搞定!...
  6. php 支付宝小程序授权登陆验签_星巴克“啡快”登陆支付宝小程序,让你“飞快”取到咖啡...
  7. 一个基于WF的业务流程平台
  8. stm32f103c8t6 AD DMA连续采集8个通道
  9. 电商设计师抢着用的液态水滴素材到底有多酷!
  10. MongoDB-概述:跨平台的面向文档的高性能高可用性易扩展数据库
  11. js获取el表达式的值_Vue.js
  12. github使用_简单使用Git与github
  13. 奇迹s6ep3服务器修改技术,奇迹S6EP3服务端之让天鹰及装备不掉持久的
  14. 第一次登录域控服务器的账号,windows域登录与SSO服务器整合
  15. 农历阳历转换 java_Java编程实例:Java版农历和阳历转换源码
  16. 输入法:QQ五笔输入法在Excel2010首次输入时,会在单元格内容产生一个空格
  17. r library car_R语言实战之回归分析
  18. 并查集 浙师大oj1212
  19. Research Commentary on Recommendations with Side Information: A Survey and Research Directions
  20. TeamViewer被检测为商用

热门文章

  1. 浮动元素具有行内块元素特点(HTML、CSS)
  2. 案例-简介小米侧边栏(HTML、CSS)
  3. 心理阴影面积 (5 分)
  4. PTA—比较大小(C语言)
  5. opencv之划痕缺陷检测
  6. SpringCloud实战五:统一配置中心
  7. JavaScript之温故--(持续更新)
  8. 如何学习嵌入式开发必备技能
  9. 技术分享连载(八十六)
  10. python程序的扩展名是perl程序的扩展名是_Python 程序扩展名(py, pyc, pyw, pyo, pyd)及发布程序时的选择...