这篇文章主要介绍“TypeScript内置工具类型怎么使用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“TypeScript内置工具类型怎么使用”文章能帮助大家解决问题。
一、什么是ts内置工具类型
TypeScript 附带了大量类型,可以帮助进行一些常见的类型操作,通常称为 Utility Types。
二、使用示例
1.Partial
将必填参数变为可选参数
namespace a { // 示例一: interface A { name: string, age: number, sex: string } // 接口A中的参数通过内置工具类型Partial变成了可选参数 type PartialA = Partial<A>; let a: PartialA = { // 此处传参可以任意个数,但只能传已定义的参数 name: '张三', age: 10 } // 示例二: interface Company { id: number, name: string } interface Person { id: number, name: string, company: Company } // 实现DeepPartial,将参数深度转换成可选参数 type DeepPartial<T> = { [U in keyof T]?: T[U] extends object ? DeepPartial<T[U]> : T[U]; } type PartialPerson = DeepPartial<Person>; let p: PartialPerson = { // 此处的参数已经变为可选参数,可根据自己需要传递 id: 10, name: '张三', company: { name: '美团' } }}
Partial的实现源码
namespace b { interface A { name: string, age: number, sex: string } type Partial<T> = { // 原理: // 1.通过keyof拿到T中的所有key // 2.迭代所有的key // 3.统一加上可选参数处理 // 4.返回迭代值的类型 [P in keyof T]?: T[P]; } // 测试: type PartialA = Partial<A>; let a: PartialA = { name: '张三', age: 10 }}
2.Required
将所有参数变为必填
namespace b { interface Person { name: string, age?: number } // Required将可选参数变为必填 type RequiredPerson = Required<Person>; let person: RequiredPerson = { name: '张三', age: 10 }}
Required 的实现源码
namespace c { interface Person { name: string, age?: number } type Required<T> = { // 原理: // 1.通过keyof拿到T中所有的key // 2.迭代所有的key // 3.将可选的参数变为必填的参数 // 4.返回迭代属性及类型 // +?或者?: 代表的是可选,-?: 代表的是不可选 [P in keyof T]-?: T[P]; }; // 测试 type RequiredPerson = Required<Person>; let person: RequiredPerson = { name: '李四', age: 18 }}
3.ReadOnly
将所有参数变为只读
namespace d { interface Person { name: string, age?: number } type ReadonlyPerson = Readonly<Person>; let person: ReadonlyPerson = { name: '张三', age: 10 } // 已经变为只读属性,因此此处赋值会报错 // person.name = '李四'; // 无法分配到 "name" ,因为它是只读属性。ts(2540) // person.age = 20; // 无法分配到 "age" ,因为它是只读属性。ts(2540)}
Readonly 的实现源码
namespace e { interface Person { name: string, age?: number } type Readonly<T> = { // 原理: // 1.通过keyof拿到T中所有key // 2.迭代拿到的所有key // 3.通过readonly关键字将所有属性变为只读属性 // 4.返回迭代属性及类型 readonly [P in keyof T]: T[P] } // 测试 type ReadonlyPerson = Readonly<Person>; let person: ReadonlyPerson = { name: '张三', age: 10 } // person.name = '李四'; // 无法分配到 "name" ,因为它是只读属性。ts(2540) // person.age = 20; // 无法分配到 "age" ,因为它是只读属性。ts(2540)}
4.Pick
捡取符合条件的属性
namespace g { interface Person { name: string, age: number, sex: string } // 参数一是一个对象,参数二是要筛选的属性 type PickPerson = Pick<Person, 'name' | 'sex'>; let person: PickPerson = { name: '张三', // 由于通过Pick只捡取了name和sex属性,因此此时给sex赋值会报错 // 不能将类型“{ name: string; age: number; sex: string; }”分配给类型“PickPerson”。 // 对象文字可以只指定已知属性,并且“age”不在类型“PickPerson”中。ts(2322) // age: 10, sex: '男' }}
Pick 的实现源码
namespace h { interface Person { name: string, age: number, sex: string } // 原理: // 1.T表示传入的类型定义。此处指Person接口。 // 2.K表示T的子类型,是一个联合类型。此处指'name' | 'age' | 'sex'的子类型 // 3.通过keyof拿到T中的所有key // 3.迭代K,拿到所有传递进来的子类型 // 4.返回迭代属性及类型 // 简单理解:就是从一个对象中,提取一部分属性组成新的对象 type Pick<T, K extends keyof T> = { [P in K]: T[P]; } // 测试 type PickPerson = Pick<Person, 'name' | 'age'> let person: PickPerson = { name: '张三', age: 10 }}
5.Record
记录类型:将一个类型的所有属性值都映射到另一个属性上并创建新的类型
namespace i { // 1.此处的K主要用来修饰obj对象的key,为string或者number // 2.此处的T用来修饰老的类型 // 3.此处的U用来修饰新的类型 function mapObj<K extends string | number, T, U>(obj: Record<K, T>, callable: (x: T) => U) { // 声明一个变量 let result: Record<K, U> = <Record<K, U>>{}; // 遍历传入的对象 for (const key in obj) { // 通过callback函数处理result的属性值 result[key] = callable(obj[key]); } // 返回result return result; } let obj = { num1: 1, num2: 2 }; let callable = (x: number): string => x * 2 + ''; let newObj = mapObj<string | number, number, string>(obj, callable); console.log(newObj); // { num1: '2', num2: '4' }}
Record 的实现源码
namespace j { type Record<K extends keyof any, T> = { // 原理: // 1.通过keyof拿到所有的K,是一个联合类型。string | number | symbol // 2.迭代K,拿到所有的属性 // 3.返回迭代的属性及类型 // 注意:此处不能写成 type Record<K, T> = {}; any代表所有key的联合类型。 // 否则会报错:不能将类型“K”分配给类型“string | number | symbol”。ts(2322) [P in K]: T; }; // 测试 function mapObj<K extends string | number, T, U>(obj: Record<K, T>, callable: (x: T) => U) { // 声明一个变量 let result: Record<K, U> = <Record<K, U>>{}; // 遍历传入的对象 for (const key in obj) { // 通过callback函数处理result的属性值 result[key] = callable(obj[key]); } // 返回result return result; } let obj = { num1: 1, num2: 2 }; let callable = (x: number): string => x * 2 + ''; let newObj = mapObj<string | number, number, string>(obj, callable); console.log(newObj); // { num1: '2', num2: '4' }}
关于“TypeScript内置工具类型怎么使用”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注编程网行业资讯频道,小编每天都会为大家更新不同的知识点。