持续创作,加速成长!这是我参与「掘金日新计划 · 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 实用类型的效果、使用、实现都已经有所掌握了~
思维导图总结
文中措辞、知识点、格式如有疑问或建议,欢迎评论~你对我很重要~
🌊如果有所帮助,欢迎点赞关注,一起进步⛵这对我很重要~