TypeScript内置工具类型怎么使用

工具使用   发布日期:2023年08月09日   浏览次数:605

这篇文章主要介绍“TypeScript内置工具类型怎么使用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“TypeScript内置工具类型怎么使用”文章能帮助大家解决问题。

    一、什么是ts内置工具类型

    TypeScript 附带了大量类型,可以帮助进行一些常见的类型操作,通常称为 Utility Types。

    二、使用示例

    1.Partial

    将必填参数变为可选参数

    1. namespace a {
    2. // 示例一:
    3. interface A {
    4. name: string,
    5. age: number,
    6. sex: string
    7. }
    8. // 接口A中的参数通过内置工具类型Partial变成了可选参数
    9. type PartialA = Partial<A>;
    10. let a: PartialA = {
    11. // 此处传参可以任意个数,但只能传已定义的参数
    12. name: '张三',
    13. age: 10
    14. }
    15. // 示例二:
    16. interface Company {
    17. id: number,
    18. name: string
    19. }
    20. interface Person {
    21. id: number,
    22. name: string,
    23. company: Company
    24. }
    25. // 实现DeepPartial,将参数深度转换成可选参数
    26. type DeepPartial<T> = {
    27. [U in keyof T]?: T[U] extends object ? DeepPartial<T[U]> : T[U];
    28. }
    29. type PartialPerson = DeepPartial<Person>;
    30. let p: PartialPerson = {
    31. // 此处的参数已经变为可选参数,可根据自己需要传递
    32. id: 10,
    33. name: '张三',
    34. company: {
    35. name: '美团'
    36. }
    37. }
    38. }

    Partial的实现源码

    1. namespace b {
    2. interface A {
    3. name: string,
    4. age: number,
    5. sex: string
    6. }
    7. type Partial<T> = {
    8. // 原理:
    9. // 1.通过keyof拿到T中的所有key
    10. // 2.迭代所有的key
    11. // 3.统一加上可选参数处理
    12. // 4.返回迭代值的类型
    13. [P in keyof T]?: T[P];
    14. }
    15. // 测试:
    16. type PartialA = Partial<A>;
    17. let a: PartialA = {
    18. name: '张三',
    19. age: 10
    20. }
    21. }

    2.Required

    将所有参数变为必填

    1. namespace b {
    2. interface Person {
    3. name: string,
    4. age?: number
    5. }
    6. // Required将可选参数变为必填
    7. type RequiredPerson = Required<Person>;
    8. let person: RequiredPerson = {
    9. name: '张三',
    10. age: 10
    11. }
    12. }

    Required 的实现源码

    1. namespace c {
    2. interface Person {
    3. name: string,
    4. age?: number
    5. }
    6. type Required<T> = {
    7. // 原理:
    8. // 1.通过keyof拿到T中所有的key
    9. // 2.迭代所有的key
    10. // 3.将可选的参数变为必填的参数
    11. // 4.返回迭代属性及类型
    12. // +?或者?: 代表的是可选,-?: 代表的是不可选
    13. [P in keyof T]-?: T[P];
    14. };
    15. // 测试
    16. type RequiredPerson = Required<Person>;
    17. let person: RequiredPerson = {
    18. name: '李四',
    19. age: 18
    20. }
    21. }

    3.ReadOnly

    将所有参数变为只读

    1. namespace d {
    2. interface Person {
    3. name: string,
    4. age?: number
    5. }
    6. type ReadonlyPerson = Readonly<Person>;
    7. let person: ReadonlyPerson = {
    8. name: '张三',
    9. age: 10
    10. }
    11. // 已经变为只读属性,因此此处赋值会报错
    12. // person.name = '李四'; // 无法分配到 "name" ,因为它是只读属性。ts(2540)
    13. // person.age = 20; // 无法分配到 "age" ,因为它是只读属性。ts(2540)
    14. }

    Readonly 的实现源码

    1. namespace e {
    2. interface Person {
    3. name: string,
    4. age?: number
    5. }
    6. type Readonly<T> = {
    7. // 原理:
    8. // 1.通过keyof拿到T中所有key
    9. // 2.迭代拿到的所有key
    10. // 3.通过readonly关键字将所有属性变为只读属性
    11. // 4.返回迭代属性及类型
    12. readonly [P in keyof T]: T[P]
    13. }
    14. // 测试
    15. type ReadonlyPerson = Readonly<Person>;
    16. let person: ReadonlyPerson = {
    17. name: '张三',
    18. age: 10
    19. }
    20. // person.name = '李四'; // 无法分配到 "name" ,因为它是只读属性。ts(2540)
    21. // person.age = 20; // 无法分配到 "age" ,因为它是只读属性。ts(2540)
    22. }

    4.Pick

    捡取符合条件的属性

    1. namespace g {
    2. interface Person {
    3. name: string,
    4. age: number,
    5. sex: string
    6. }
    7. // 参数一是一个对象,参数二是要筛选的属性
    8. type PickPerson = Pick<Person, 'name' | 'sex'>;
    9. let person: PickPerson = {
    10. name: '张三',
    11. // 由于通过Pick只捡取了name和sex属性,因此此时给sex赋值会报错
    12. // 不能将类型“{ name: string; age: number; sex: string; }”分配给类型“PickPerson”。
    13. // 对象文字可以只指定已知属性,并且“age”不在类型“PickPerson”中。ts(2322)
    14. // age: 10,
    15. sex: '男'
    16. }
    17. }

    Pick 的实现源码

    1. namespace h {
    2. interface Person {
    3. name: string,
    4. age: number,
    5. sex: string
    6. }
    7. // 原理:
    8. // 1.T表示传入的类型定义。此处指Person接口。
    9. // 2.K表示T的子类型,是一个联合类型。此处指'name' | 'age' | 'sex'的子类型
    10. // 3.通过keyof拿到T中的所有key
    11. // 3.迭代K,拿到所有传递进来的子类型
    12. // 4.返回迭代属性及类型
    13. // 简单理解:就是从一个对象中,提取一部分属性组成新的对象
    14. type Pick<T, K extends keyof T> = {
    15. [P in K]: T[P];
    16. }
    17. // 测试
    18. type PickPerson = Pick<Person, 'name' | 'age'>
    19. let person: PickPerson = {
    20. name: '张三',
    21. age: 10
    22. }
    23. }

    5.Record

    记录类型:将一个类型的所有属性值都映射到另一个属性上并创建新的类型

    1. namespace i {
    2. // 1.此处的K主要用来修饰obj对象的key,为string或者number
    3. // 2.此处的T用来修饰老的类型
    4. // 3.此处的U用来修饰新的类型
    5. function mapObj<K extends string | number, T, U>(obj: Record<K, T>, callable: (x: T) => U) {
    6. // 声明一个变量
    7. let result: Record<K, U> = <Record<K, U>>{};
    8. // 遍历传入的对象
    9. for (const key in obj) {
    10. // 通过callback函数处理result的属性值
    11. result[key] = callable(obj[key]);
    12. }
    13. // 返回result
    14. return result;
    15. }
    16. let obj = { num1: 1, num2: 2 };
    17. let callable = (x: number): string => x * 2 + '';
    18. let newObj = mapObj<string | number, number, string>(obj, callable);
    19. console.log(newObj); // { num1: '2', num2: '4' }
    20. }

    Record 的实现源码

    1. namespace j {
    2. type Record<K extends keyof any, T> = {
    3. // 原理:
    4. // 1.通过keyof拿到所有的K,是一个联合类型。string | number | symbol
    5. // 2.迭代K,拿到所有的属性
    6. // 3.返回迭代的属性及类型
    7. // 注意:此处不能写成 type Record<K, T> = {}; any代表所有key的联合类型。
    8. // 否则会报错:不能将类型“K”分配给类型“string | number | symbol”。ts(2322)
    9. [P in K]: T;
    10. };
    11. // 测试
    12. function mapObj<K extends string | number, T, U>(obj: Record<K, T>, callable: (x: T) => U) {
    13. // 声明一个变量
    14. let result: Record<K, U> = <Record<K, U>>{};
    15. // 遍历传入的对象
    16. for (const key in obj) {
    17. // 通过callback函数处理result的属性值
    18. result[key] = callable(obj[key]);
    19. }
    20. // 返回result
    21. return result;
    22. }
    23. let obj = { num1: 1, num2: 2 };
    24. let callable = (x: number): string => x * 2 + '';
    25. let newObj = mapObj<string | number, number, string>(obj, callable);
    26. console.log(newObj); // { num1: '2', num2: '4' }
    27. }

    以上就是TypeScript内置工具类型怎么使用的详细内容,更多关于TypeScript内置工具类型怎么使用的资料请关注九品源码其它相关文章!