持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第1天,点击查看活动详情
前言
上篇文章 够用的TypeScript(1)|能用 Javascript 写的东西,终将会用 TypeScript 书写~ 留了一个关于 TS 实用类型的坑~现在来填了~
大部分效果例子来自官网~
八种实用类型
官方的实用类型有很多~ 但我这里出于篇幅限制,这里只讲前八个比较常用的,以及他的实现~
至于实现的相关语法,会随着用到而进行说明~
Partial 可选
效果
将对象的所有属性值设置为可选——相加了 ?: 一样。
interface Todo {title: string;description: string;}function updateTodo(todo: Todo, fieldsToUpdate: Partial<Todo>) {return { ...todo, ...fieldsToUpdate };}const todo1 = {title: "organize desk",description: "clear clutter",};const todo2 = updateTodo(todo1, {description: "throw out trash",});
实现
可能是你没想到的简单
type Partial<T> = {[P in keyof T]?: T[P];};
主要用到TS中的类型映射。将所有的属性都转为?:的,也就是可选的~
类型映射语法
类型映射,大概就是这样~
{ [ P in K ] : T }
这里的in有点像JS的for..in,也就是遍历 K 中所有属性,再用:映射回到合适的属性值
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
‘.
实现
type Required<T> = {[P in keyof T]-?: T[P];};
相当于就是通过添加减号-前缀将原来有的?去掉了,让这些属性不是可选的,自然就是必选的~
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 Readonly<T> = {readonly [P in keyof T]: T[P];};
是的,除了添加减号前缀,你还可以直接添加修饰符~
当然,其实直接添加修饰符也就是默认前面使用了加号+
Record 记录
效果
接收两个参数——keys、values,使得对象中的key、value必须在keys、values里面。
interface CatInfo {age: number;breed: string;}type CatName = "miffy" | "boris" | "mordred";const cats: Record<CatName, CatInfo> = {miffy: { age: 10, breed: "Persian" },boris: { age: 5, breed: "Maine Coon" },mordred: { age: 16, breed: "British Shorthair" },};
实现
type Record<K extends keyof any, T> = {[P in K]: T;};
keyof
keyof操作符是在 TypeScript 2.1 版本引入的,该操作符可以用于获取某种类型的所有键,其返回类型是联合类型。
这句K extends keyof any好像有点无厘头,让我们看看这个得到的到底是啥
type KEY = keyof any //即 string | number | symbol
豁然开朗了,这个不就是说对象的keys类型可以取 string,number,symbol类型嘛~
比如这里的例子
type CatName = "miffy" | "boris" | "mordred";
就是keys用了string这个类型,主要还是因为对象的键只能取这些类型,而这些键具体长什么样,就看传入的K了
然后再映射到传入的T接口中~
Pick 选择
效果
从接口中选择一组属性值(通过key——属性值)
interface Todo {title: string;description: string;completed: boolean;}type TodoPreview = Pick<Todo, "title" | "completed">; //从 Todo 接口中选const todo: TodoPreview = {title: "Clean room",completed: false,};todo;
实现
type Pick<T, K extends keyof T> = {[P in K]: T[P];};
Omit 过滤
效果
通过key选择来过滤,差不多就是上一个的取反~
interface Todo {title: string;description: string;completed: boolean;createdAt: number;}type TodoPreview = Omit<Todo, "description">;const todo: TodoPreview = {title: "Clean room",completed: false,createdAt: 1615544252770,};
实现
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
还真是 对 Pick 进行取反~要用到下面要说的 Exclude
简单理解
Exclude就是数学集合中找出Type的“差集”,就是将类型A与B对比,返回A中独有的类型
Exclude 排除
效果
顾名思义,include包含的反义词,从一个类型(联合类型)中排除另一个类型。
type T0 = Exclude<"a" | "b" | "c", "a">; //"b"|"c"
实现
前面的 Omit 实现用到这个,那么这个是怎么实现的呢
type Exclude<T, U> = T extends U ? never : T;
?: 条件运算符
这里实际上就是一个?:条件运算符
好像很多语言都有这个东东呢,确实是非常好用~
判断 T 是否来自 U:
- 啊,真来自 U 啊,不要了,给你个 never
-
Extract 提炼
效果
从某个联合类型中,筛选出和另外一个联合类型相交的部分。
type T0 = Extract<"a" | "b" | "c", "a" | "f">; //"a"
实现
type MyExtract<T,U> = T extends U ? T : never ;
和上一个
Exclude很像哦
判断是不是来自 U 是,通过~
-
学习资源
-
总结
看完之后相信你对 TS 实用类型的效果、使用、实现都已经有所掌握了~
思维导图总结

文中措辞、知识点、格式如有疑问或建议,欢迎评论~你对我很重要~
🌊如果有所帮助,欢迎点赞关注,一起进步⛵这对我很重要~
