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)); // 36
    
    const 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);// success
    
    currentStatus = null;
    console.log(currentStatus); // null
    
    currentStatus = 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; // 只有这一项有readonly
        age: 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;
    }
    

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Discuz! X3.5精品模板下载网站模板utf-8

适合做模板下载网站&#xff0c;模板涵盖广告设计/电商设计/海报/名片/字体/展板/X展架,下载即用,精品优质,海量免费模板网下载下载,专业模板素材网站,让设计变得更简单! 下载地址&#xff1a;Discuz! X3.5精品模板下载网站模板.zip 截图&#xff1a;

基于ESTAR指数平滑转换自回归模型的CPI数据统计分析matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 4.1 ESTAR模型概述 4.2 WNL值&#xff0c;P值&#xff0c; Q值&#xff0c;12阶ARCH值 4.3ADF检验 5.完整程序 1.程序功能描述 基于ESTAR指数平滑转换自回归模型的CPI数据统计分析matlab仿…

拼多多根据关键词取商品列表 API 返回值说明

一、应用场景 拼多多根据关键词取商品列表的API应用场景非常广泛&#xff0c;主要集中在电商领域&#xff0c;包括但不限于以下几个方面&#xff1a; 1、商品搜索与推荐&#xff1a;商家可以通过API接口&#xff0c;根据用户输入的关键词&#xff0c;实时获取拼多多平台上的相…

力扣hot100:34. 在排序数组中查找元素的第一个和最后一个位置(二分查找的理解)

我们知道使用二分查找能找到值所在的位置。假如我们在找到值后仍然不断的更新指针会发生什么&#xff1f;我们可以利用这一点来找到最左边的以及最右边的值。 如果当nums[mid]target时&#xff0c;使得 rightmid-1&#xff0c;那么最终会使得target在right的右边。 如果当nums[…

MacBook使用——彻底卸载并删除软件:NTFS for Mac

问题 之前因MacBook读写NTFS格式移动硬盘&#xff0c;我安装并使用了 Paragon NTFS for Mac &#xff0c;试用期结束后将其从【应用程序】中卸载移除了。但之后每次开机启动时&#xff0c;系统还是会弹出【激活】通知&#xff0c;如下图 解决 Step1、在用户目录下的 Library 目…

C++笔记:从零开始一步步手撕红黑树

文章目录 红黑树概念红黑树的性质红黑树 VS AVL树红黑树的结点与树的描述——定义类红黑树的插入操作步骤一&#xff1a;按照二叉搜索树的规则插入新结点步骤二&#xff1a;检测新节点插入后&#xff0c;红黑树的性质是否造到破坏情况一&#xff1a;uncle存在且为红情况二&…

外包干了9天,技术退步明显。。。。。

先说一下自己的情况&#xff0c;本科生&#xff0c;2018年我通过校招踏入了南京一家软件公司&#xff0c;开始了我的职业生涯。那时的我&#xff0c;满怀热血和憧憬&#xff0c;期待着在这个行业中闯出一片天地。然而&#xff0c;随着时间的推移&#xff0c;我发现自己逐渐陷入…

【微服务】分布式调度框架PowerJob使用详解

目录 一、前言 二、定时任务调度框架概述 2.1 为什么需要定时任务调度框架 2.2 定时任务调度使用场景 三、PowerJob 介绍 3.1 PowerJob 概述 3.2 PowerJob 功能特性 3.3 PowerJob 应用场景 3.4 PowerJob 与其他同类产品对比 四、PowerJob 部署 4.1 PowerJob 架构 4.…

【linux】进程(一)

先看预备知识&#xff0c;对本篇文章更有帮助。 目录 进程概念&#xff1a;了解动态运行的概念&#xff1a;进程的本身内部属性&#xff1a;启动进程&#xff1a;关闭进程&#xff1a; 如何创建进程&#xff1a;进程状态&#xff1a;直接看进程状态&#xff1a;僵尸进程与孤儿…

工智能的迷惑是技术发展的产物

简述&#xff1a; 随着ChatGPT在全球科技舞台上掀起一股热潮&#xff0c;人工智能再次成为了人们关注的焦点。各大公司纷纷紧跟潮流&#xff0c;推出了自己的AI大模型&#xff0c;如&#xff1a;文心一言、通义千问、讯飞星火、混元助手等等&#xff0c;意图在人工智能领域占据…

HarmonyOS NEXT应用开发—状态栏显隐变化

介绍 本示例介绍使用Scroll组件的滚动事件 onScroll 实现状态栏显隐变化。该场景多用于各种软件的首页、我的等页面中。 效果预览图 使用说明 加载完成后显示状态栏显隐变化页面&#xff0c;上下拖动屏幕&#xff0c;顶端状态栏出现显隐变化。 实现思路 在置顶位置使用sta…

三维坐标系之间的转换

一、概括 这个完全是抄别人的&#xff0c;给我自己看的&#xff0c;后期会吧代码更新上去。 彻底搞懂“旋转矩阵/欧拉角/四元数”&#xff0c;让你体会三维旋转之美_欧拉角判断动作-CSDN博客 在不同的坐标系中物体的位姿是相对的&#xff0c;任何的坐标系都是相对来说的&…

sql查询语句中提取【】里面的值

在实际工作中&#xff0c;有时候会遇到提取sql查询出来的字段中括号里面的码值&#xff0c;比如&#xff1a; 我现在要提取student表的sname中括号里面的字段 解决方法如下&#xff1a; select sname,replace(substr(sname, instr(sname, [,1)1),],) from student;成功提取&am…

BIG-Bench Hard 数据集分享

来源: AINLPer公众号&#xff08;每日干货分享&#xff01;&#xff01;&#xff09; 编辑: ShuYini 校稿: ShuYini 时间: 2024-3-17 该数据集由Google、斯坦福等研究人员开发&#xff0c;BBH的全称是BIG-Bench Hard&#xff0c;它是BIG-Bench数据集的一个子集&#xff0c;它专…

说JS作用域,就不得不说说自执行函数

一个兜兜转转&#xff0c;从“北深”回到三线城市的小码农&#xff0c;热爱生活&#xff0c;热爱技术&#xff0c;在这里和大家分享一个技术人员的点点滴滴。欢迎大家关注我的微信公众号&#xff1a;果冻想 前言 不得不吐槽&#xff0c;学个JS&#xff0c;这个概念也太多了&am…

Java Web项目—餐饮管理系统Day06-套餐管理(一)

文章目录 1. 需求分析与实体类准备2. 依据菜品分类或者名字进行查询的请求(需求B)3. 新增套餐 1. 需求分析与实体类准备 如上图为新增套餐的界面, 它包含了套餐的一些基本信息, 例如名称、价格等, 同时还有套餐分类(因此这里需要一个查询所有套餐分类的请求处理方法, 需求A). 以…

Twincat实现电机控制

不仅是控制系统的核心部分&#xff0c;而且能够将任何基于PC的系统转换为一个带有PLC、NC、CNC和机器人实时操作系统的实时控制系统。TwinCAT软件在工业自动化领域具有广泛的应用&#xff0c;特别是在机器人关节电机控制方面!!! 在机器人关节电机控制方面&#xff0c;TwinCAT通…

Go——运算符,变量和常量,基本类型

一.运算符 Go语言内置的运算符有&#xff1a; 算术运算符 关系运算符 逻辑运算符 位运算符 赋值运算符 1.1 算术运算符 注意&#xff1a;(自增)和--(自减)在go语言中是单独的语句&#xff0c;并不是运算符。 1.2 关系运算符 1.3 逻辑运算符 1.4 位运算符 位运算符对整数在内存…

UnityShader:IBL

效果&#xff1a; 实现&#xff1a; Shader "MyShader/IBL" {Properties{_CubeMap ("环境贴图", Cube) "white" {}_Exposure("曝光",float)1.0_Color("颜色",color)(1,1,1,1)_NormalMap("法线贴图",2d)"bu…

鸿蒙开发(五)-应用签名相关

鸿蒙开发(五)-应用签名相关 本篇文章主要介绍下鸿蒙应用下的应用签名的创建与配置。 根据之前的介绍&#xff0c;我们知道&#xff0c;在DevEco Studio默认创建的应用程序&#xff0c;是没有sign配置的。 默认输出的应用文件如下&#xff1a; build->default->output…