TypeScript(五)交叉类型,联合类型,映射类型

交叉类型

交叉类型是将多个类型合并为一个类型。可以把现有的多种类型叠加到一起成为一种类型,它包含了所需的所有类型的特性。使用符号 & 表示。交叉类型 A & B 表示,任何一个新类型必须同时属于 A 和 B,才属于交叉类型 A & B

  1. 基础介绍
    type Dog = { breed: string; run(): void };
    type Bird = { wingspan: number; fly(): void };type DogAndBird = Dog & Bird;const animal: DogAndBird = {breed: "Labrador",run() {console.log("Dog is running.");},wingspan: 20,fly() {console.log("Bird is flying.");},
    };
    console.log(animal.breed); // Labrador
    animal.run(); // 执行方法打印 Dog is running.
    animal.fly(); // 执行方法打印 Bird is flying.
    // animal 同时具有Dog 和 Bird 的特性
    
  2. 函数中的应用
    通过 extend 把两个对象合并成一个对象,看一下如何通过函数参数类型交叉实现。
    function extend<T, U>(first: T, second: U): T & U {const result = {} as T & U;console.log(first, second); // { name: '迪西', className: '三年级' }  { age: 9, className: '二年级' }for (const key in first) {(result as T)[key] = first[key];}for (const key in second) {if (!result.hasOwnProperty(key)) { // 检查result是否包含second中的key(result as U)[key] = second[key];}}return result;
    }const extendedObject = extend({ name: '迪西', className: '三年级' }, { age: 9, className: '二年级' });
    console.log(extendedObject); // {name: '迪西', className: '三年级', age: 9}
    
  3. 对象合并
    type Car = { brand: string; speed: number };
    type Boat = { color: string; sails: number };type Vehicle = Car & Boat;const hybridVehicle: Vehicle = {brand: "cat",speed: 120,color: "Blue",sails: 2,
    };
    
  4. 可选属性的处理
    交叉之后创建的新类型,同样包含原类型中的可选属性
    type Car = { brand: string; speed?: number };
    type Boat = { color: string; sails?: number };
    type Vehicle = Car & Boat;
    const hybridVehicle: Vehicle = {brand: "cat",speed: 120,color: "Blue",
    };
    
  5. 函数重载
    函数重载是 TypeScript 中处理不同参数组合的一种方式
    function merge<T, U>(arg1: T, arg2: U): T & U;
    function merge<T, U, V>(arg1: T, arg2: U, arg3: V): T & U & V;
    function merge(...args: any[]): any {return Object.assign({}, ...args);
    }const mergedObject = merge({ A: 1 }, { B: 2 }, { C: 3 });
    console.log(mergedObject); // {A: 1, B: 2, C: 3}
    
  6. 类型守卫与交叉类型
    通过 in 关键字使用类型守卫检查对象的属性
    type Car = { brand: string; speed: number };
    type Flying = { altitude: number };
    function moveVehicle(vehicle: Car & Flying) {if ("speed" in vehicle) {console.log(`speed: ${vehicle.speed}`); // speed: 120}if ("altitude" in vehicle) {console.log(`Flying: ${vehicle.altitude}`); // Flying: 5000}
    }
    // 使用交叉类型的函数
    let flyingCar: Car & Flying = { brand: "SkyCar", speed: 120, altitude: 5000 };
    moveVehicle(flyingCar);
    

联合类型

联合类型是 TypeScript 中非常灵活的一部分,它允许一个值属于多个类型之一
联合类型允许一个值可以是多种类型之一,使用符号 | 表示。

let userName: string | number;
userName = "迪西";
console.log(userName.length); // 2
userName = 9;
console.log(userName, userName.length); // 报错

在这里插入图片描述

  1. 函数返回值
    联合类型在函数参数中,允许参数接受多种类型的值,处理不同类型的返回值。
    function getRandomValue(): string | number {const random = Math.random();return random > 0.5 ? "Hello" : 42;
    }const resultNum = getRandomValue();
    console.log(resultNum);
    
  2. 对象的联合类型
    在 TypeScript 中,可以使用联合类型表示具有不同属性的对象。
    type Square = { kind: "square"; width: number };
    type Circle = { kind: "circle"; radius: number };type Shape = Square | Circle;function area(shape: Shape): number {if (shape.kind === "square") {return shape.width ** 2;} else {return Math.PI * shape.radius ** 2;}
    }const square: Square = { kind: "square", width: 6 };
    console.log(area(square)); // 36const circle: Circle = { kind: "circle", radius: 4 };
    console.log(area(circle)); // 50.26548245743669
    
  3. null 与 undefined
    联合类型经常与 null 或 undefined 结合使用,以表示变量可能具有空值。
    type Status = "success" | "error" | "pending" | null | undefined;
    // Status 可以是 success,error,pending, null,undefined
    let currentStatus: Status = "success";
    console.log(currentStatus);// successcurrentStatus = null;
    console.log(currentStatus); // nullcurrentStatus = undefined;
    console.log(currentStatus); // undefined
    
  4. 类型守卫
    联合类型与类型守卫结合使用,可以更安全地操作对象。
    function printMessage(message: string | string[] | null) {if (message instanceof Array) {console.log(message.join(","));} else if (message === null) {console.log("No message");} else {console.log(message);}
    }printMessage("Hello, TypeScript!");
    printMessage(["TypeScript", "is", "awesome"]);
    printMessage(null);
    // 打印结果
    // Hello, TypeScript!
    // TypeScript,is,awesome
    // No message
    
  5. 可辨识联合
    可辨识联合是一种特殊的联合类型,结合了具有共同字段的对象。
    type SuccessResponse = { status: "1"; data: string };
    type ErrorResponse = { status: "2"; error: string };type ApiResponse = SuccessResponse | ErrorResponse;function handleApiResponse(response: ApiResponse) {switch (response.status) {case "1":console.log(response.data);break;case "2":console.log(response.error);break;}
    }const successResponse: SuccessResponse = { status: "1", data: "Success" };
    const errorResponse: ErrorResponse = { status: "2", error: "Error" };handleApiResponse(successResponse);
    handleApiResponse(errorResponse);
    // 打印结果
    // Success
    // Error
    

映射类型

映射类型:从旧类型中创建新类型的一种方式 。 在映射类型里,新类型以相同的形式去转换旧类型里每个属性。
它的语法与索引签名的语法类型,内部使用了 for … in。 具有三个部分:

type Keys = 'option1' | 'option2';
type Flags = { [K in Keys]: boolean };

等同于

type Flags = {option1: boolean;option2: boolean;
}

类型变量 K,它会依次绑定到每个属性。
字符串字面量联合的 Keys,它包含了要迭代的属性名的集合。
属性的结果类型。
keyof和索引访问类型

type Nullable<T> = { [P in keyof T]: T[P] | null }
type Partial<T> = { [P in keyof T]?: T[P] }
// 属性列表是 keyof T且结果类型是 T[P]的变体。

因为这类转换是 同态的,映射只作用于 T的属性而没有其它的

  1. Extract 映射类型
    Extract 映射类型允许我们从联合类型中提取符合指定条件的子集。 一般用于处理联合类型

    // Extract<T, U> -- 提取T中可以赋值给U的类型。
    // Extract实现源码 原理很简单
    type Extract<T, U> = T extends U ? T : never;
    
    type Test1 = '1' | '2' | '3'
    const obj: Extract<Test1, '1' | '2'> = '1';
    console.log(obj) // 1
    const obj2: Extract<Test1, '1' | '2'> = '2';
    console.log(obj2) // 2
    const obj3: Extract<Test1, '1' | '2'> = '3'; // 1,2 OK 赋值3就会error
    

    在这里插入图片描述

  2. Exclude 映射类型
    Exclude 映射类型允许我们从联合类型中排除符合指定条件的子集
    和 Extract 正好相反,也是用于处理联合类型

    // Exclude源码
    type Exclude<T, U> = T extends U ? never : T;
    
    type Test1 = '1' | '2' | '3'
    const obj: Exclude<Test1, '1' | '2'> = '3'; // 1,2 OK 赋值3就会error
    console.log(obj) // 3
    // const obj1: Exclude<Test1, '1' | '2'> = '1';
    // console.log(obj1) // 1
    

    在这里插入图片描述

  3. Pick 映射类型
    Pick 映射类型允许我们从现有类型中挑选出指定的属性。
    可以采集 已定义对象中 自己需要的一部分形成新的定义类型。

    // Pick 的源码
    type Pick<T, K extends keyof T> = {[P in K]: T[P];
    };
    
    interface UserObj {readonly name: string;age: number;id: number;sex: 0 | 1;address: string;weight: number;
    }// 采集需要的
    type Person = Pick<UserObj, "name" | "id">;
    // 此时Person 等同于 Person1
    //interface Person1 {
    // readonly name: string;
    //  id: number;
    //}
    const obj: Person = {name: '迪西', 'id': 1};
    // const obj: Person = {name: '迪西', 'id': 1, sex: 0}; // sex字段报错
    

    在这里插入图片描述

  4. Omit 映射类型
    可以剔除 已定义对象中 自己不需要的一部分形成新的定义类型。

    // Omit 的源码
    type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
    
    interface UserObj {readonly name: string; // readonly 只读属性 只能初始化定义 不能二次赋值age: number;id: number;sex: 0 | 1;address: string;weight: number;
    }// 剔除省略自己不需要的
    type Person = Omit<UserObj, "age" | "sex"  | "address" | "weight">;// 此时Person 等同于 Person1
    // interface Person1 {
    //   readonly name: string;
    //   id: number;
    // }
    let obj:Person = {name: '迪西', 'id': 1}
    // let obj:Person = {name: '迪西', 'id': 1, sex: 0}
    

    在这里插入图片描述

  5. NonNullable 映射类型
    NonNullable 映射类型允许我们从类型中排除 null 和 undefined。

    // 源码
    /*** Exclude null and undefined from T*/
    type NonNullable<T> = T & {}; // 源码的这一句写的很有意思,泛型参数T和{}的交集就默认排除了`null` 和 `undefined`
    
    type MaybeString = string | null | undefined;  
    let string = 'hello 迪西!'
    const value: MaybeString = getSomeStringValue(string); // 假设这个函数可能返回一个字符串、null 或 undefined  
    console.log(value);
    // 使用 NonNullable 确保 value 不会是 null 或 undefined  
    const nonNullableValue: NonNullable<MaybeString> = value!; // 使用 ! 断言操作符,或者通过其他方式确保值不为 null 或 undefined  // 现在,nonNullableValue 的类型是 string,因为我们已经排除了 null 和 undefined  
    console.log(nonNullableValue.length); // 9 // 其实就是某些场景绝对为了排除null,undefined的类型才用的
    function getSomeStringValue(str) {return str
    }
    
  6. ReturnType 映射类型 (函数的类型推导返回)
    ReturnType 映射类型允许我们获取函数类型的返回值类型。

    // ReturnType源码
    /*** Obtain the return type of a function type*/
    type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;
    
    const myFun = () => ({name: 'zhangsan',age: 233,sex: '1',tel: 123456789,fun: () => {return 233;},arr: [1,2,3,4,5,6]
    });
    type Test2 = ReturnType<typeof myFun>; 
    // 错误用法
    // const someValue = 42;  
    // type InvalidReturnType = ReturnType<typeof someValue>; // error错误!someValue 不是一个函数。
    

    在这里插入图片描述

  7. Partial
    可把定义好的对象(包含 必选+可选项)类型全部转化为可选项

    // Partial源码
    type Partial<T> = {[P in keyof T]?: T[P];
    };
    
    interface Person {name: string;age: number;id: number;sex: 0 | 1;address: string;weight: number;
    }// 使用方法
    const newObj: Partial<Person> = {name: '迪西' // 假如只需要一项 Partial的便捷性 可以不需要从新定义类型
    };// Partial<Person>等同于 NewPerson
    interface NewPerson {name?: string;age?: number;id?: number;sex?: 0 | 1;address?: string;weight?: number;
    }
    
  8. Partial
    Required 和 Partial刚好相反,可把定义好的对象(包含 必选+可选项)类型全部转化为 必选项

    // Partial  “-?” 意思是移除可选属性
    /*** Make all properties in T required*/
    type Required<T> = {[P in keyof T]-?: T[P];
    };
    
    // 已有定义类型Person
    interface Person {name: string;age: number;id?: number;sex?: 0 | 1;
    }// 使用方法
    const newObj: Required<Person> = {name: '迪西',age: 9,id: 1,sex: 1
    };// Required<Person>等同于 NewPerson
    interface NewPerson {name: string;age: number;id: number;sex: 0 | 1;
    }
    
  9. Readonly (转化只读)
    Readonly 就是为类型对象每一项添加前缀 Readonly

    // Readonly 源码
    /*** Make all properties in T readonly*/
    type Readonly<T> = {readonly [P in keyof T]: T[P];
    };
    
    interface Person {readonly name: string; // 只有这一项有readonlyage: number;id?: number;
    }// 使用方法
    const newObj: Readonly<Person> = {name: '迪西',age: 9,id: 1
    };
    // newObj.name = '李四'; // 异常 因为有readonly只读属性,只能初始化声明,不能赋值。// Readonly<Person> 等同于 NewPerson
    interface NewPerson {readonly name: string;readonly age: number;readonly id?: number;
    }
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/535715.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

金和OA jc6 viewConTemplate.action RCE漏洞复现

0x01 产品简介 金和OA协同办公管理系统软件&#xff08;简称金和OA&#xff09;&#xff0c;本着简单、适用、高效的原则&#xff0c;贴合企事业单位的实际需求&#xff0c;实行通用化、标准化、智能化、人性化的产品设计&#xff0c;充分体现企事业单位规范管理、提高办公效率…

【Linux/OS学习】基础文件控制/IO——内存文件

文章目录 一、 基础文件控制1.1 系统接口open函数1.2 Linux中文件描述符1.2 C语言FILE中的文件描述符 二、重定向1. 输出重定向2. 追加重定向3. 输入重定向 tips:fd的分配规则 一个文件要有一个唯一的文件标识&#xff0c;以便用户识别和引用。 文件名包含3部分&#xff1a;文件…

基于springboot+vue的电子商务系统(源码+论文)

目录 前言 一、功能设计 二、功能实现 三、库表设计 四、论文 前言 各种购物网站现在已经成了生活中不可缺少的调味品,比如比较全面的淘宝网,还有可以进行交流问答的小红书APP,还有电脑爱好者者们的天堂京东商城等等。拥有一个功能丰富、操作方便的电子商务销售网站,可以汇…

十二:多线程服务端实现

1 理解线程 1.1 引入线程背景 多进程模型有如下缺陷&#xff1a; 创建进程的过程会带来一定的开销。为了完成进程间的数据交换&#xff0c;需要特殊的IPC技术每秒少则数十次&#xff0c;多则数千次的‘上下文切换’是创建进程时最大的开销 运行程序前需要将相应进程信息读入…

Python实战:采集全国5A景点名单

本文将以采集全国 5A 景点名单为例&#xff0c;详细介绍如何使用 Python 进行数据采集。 本文采集到全国340家5A景区的名单&#xff0c;包括景区名称、地区、 A级、评定年份这些字段。 一、分析数据源 为了获取权威数据&#xff0c;我们来到主管部门的官方网站&#xff0c;在右…

学生打架校园防霸凌系统可以监测到吗

随着社会的进步和教育的发展&#xff0c;校园安全问题日益受到社会各界的关注。其中&#xff0c;学生打架和校园霸凌问题尤为突出&#xff0c;不仅影响了学生的身心健康&#xff0c;也破坏了校园的和谐氛围。为了有效预防和应对这些问题&#xff0c;许多学校开始引入校园防霸凌…

origin修改图例为显示”长名称/单位/注释/自定义“等

背景 由于在origin作图时希望修改自动显示的图例&#xff0c;但每次手动更新又比较繁琐&#xff08;特别是在数据量较多的情况下&#xff09;&#xff0c;为了一劳永逸 步骤 1. 在数据工作表中设置好需要修改后的名称&#xff08;我写到长名称里了&#xff09; 2. 修改图例的…

【原创】[新增]ARCGIS之土地报备Txt、征地Xls格式批量导出Por旗舰版

一、软件简介 2024年新增旗舰版软件&#xff0c;本软件全新界面开发&#xff0c;保留原有软件功能及一些使用习惯&#xff0c;并集成了现已有的所有定制格式的支持&#xff0c;并增加自定义格式的导出&#xff1b;做到1N2&#xff08;即为1种通用版本N种定制格式导出txt、Xls&a…

C++ 作业 24/3/13

1、设计一个Per类&#xff0c;类中包含私有成员:姓名、年龄、指针成员身高、体重&#xff0c;再设计一个Stu类&#xff0c;类中包含私有成员:成绩、Per类对象p1&#xff0c;设计这两个类的构造函数、析构函数和拷贝构造函数。 #include <iostream>using namespace std;c…

IU5070E线性单节锂电池充电管理IC

IU5070E是一款具有太阳能板最大功率点跟踪MPPT功能&#xff0c;单节锂离子电池线性充电器&#xff0c;最高支持1.5A的充电电流&#xff0c;支持非稳压适配器。同时输入电流限制精度和启动序列使得这款芯片能够符合USB-IF涌入电流规范。 IU5070E具有动态电源路径管理(DPPM)功能&…

数据库管理-第160期 Oracle Vector DB AI-11(20240312)

数据库管理160期 2024-03-12 数据库管理-第160期 Oracle Vector DB & AI-11&#xff08;20240312&#xff09;1 向量的函数操作to_vector()将vector转换为标准值vector_norm()vector_dimension_count()vector_dimension_format() 2 将向量转换为字符串或CLOBvector_seriali…

用友U8 Cloud base64 SQL注入漏洞复现

0x01 产品简介 用友U8 Cloud是用友推出的新一代云ERP&#xff0c;主要聚焦成长型、创新型企业&#xff0c;提供企业级云ERP整体解决方案。 0x02 漏洞概述 用友U8 Cloud base64接口处存在SQL注入漏洞&#xff0c;未授权的攻击者可通过此漏洞获取数据库权限&#xff0c;从而盗…