zoukankan      html  css  js  c++  java
  • 【TS】506- TypeScript 交叉类型

    一、简介

    TypeScript 交叉类型是将多个类型合并为一个类型。这让我们可以把现有的多种类型叠加到一起成为一种类型,它包含了所需的所有类型的特性。

    interface IPerson {
      id: string;
      age: number;
    }
    interface IWorker {
      companyId: string;
    }
    type IStaff = IPerson & IWorker;
    const staff: IStaff = {
      id: 'E1006',
      age: 33
    ,
      companyId: 'EXE'
    };
    console.dir(staff)
    

    在上面示例中,我们首先为 IPerson 和 IWorker 类型定义了不同的成员,然后通过 & 运算符定义了 IStaff 交叉类型,所以该类型同时拥有 IPerson 和 IWorker 这两种类型的成员。那么现在问题来了,假设在合并多个类型的过程中,刚好出现某些类型存在相同的成员,但对应的类型又不一致,比如:

    interface X {
      c: string;
      d: string;
    }
    interface Y {
      c: number;
      e: string
    }
    type XY = X & Y;
    type YX = Y & X;
    let p: XY;
    let q: YX;
    

    在上面的代码中,接口 X 和接口 Y 都含有一个相同的成员 c,但它们的类型不一致。对于这种情况,此时 XY 类型或 YX 类型中成员 c 的类型是不是可以是 stringnumber 类型呢?比如下面的例子:

    p = { c: 6, d: "d", e: "e" }; 
    

    q = { c: "c", d: "d", e: "e" }; 
    

    为什么接口 X 和接口 Y 混入后,成员 c 的类型会变成 never 呢?这是因为混入后成员 c 的类型为 string&number,即成员 c 的类型既是 string 类型又是number 类型。很明显这种类型是不存在的,所以混入后成员 c 的类型为 never

    在上面示例中,刚好接口 X 和接口 Y 中内部成员 c 的类型都是基本数据类型,那么如果是非基本数据类型的话,又会是什么情形。我们来看个具体的例子:

    interface D { d: boolean; }
    interface E { e: string; }
    interface F { f: number; }
    interface A { x: D; }
    interface B { x: E; }
    interface C { x: F; }
    type ABC = A & B & C;
    let abc: ABC = {
        x: {
          d: true,
          e: 'semlinker',
          f: 666
        }
    };
    console.log('abc:', abc);
    

    以上代码成功运行后,控制台会输出以下结果:

    由上图可知,在混入多个类型时,若存在相同的成员,且成员类型为非基本数据类型,那么是可以成功合并。前面我们已经介绍了 TypeScript 交叉类型相关的知识,最后我们再来举一个实际的使用示例。

    二、使用示例

    在实际项目开发过程中,我们经常需要开发一些功能函数,为了保证函数的灵活性和可复用性,这些函数往往会定义一些输入参数,而这些参数根据是否必填,又可分为必填参数和可选参数。当必填参数和可选参数有大部分参数是相同的情况下,我们就可以利用 TypeScript 交叉类型来解决复用问题。好了,废话不多说,直接看个示例:

    ArgBase 接口

    export interface ArgBase<T> {
      name?: string;
      description?: string;
      hidden?: boolean;
      parse: ParseFn<T>;
      default?: T | (() => T);
      input?: string;
      options?: string[];
    }
    

    RequiredArg 接口

    export type RequiredArg<T> = ArgBase<T> & {
      required: true;
      value: T;
    }
    

    OptionalArg 接口

    export type OptionalArg<T> = ArgBase<T> & {
      required: false;
      value?: T;
    }
    

    顾名思义,ArgBase 接口是基础参数接口,它是 RequiredArg 和 OptionalArg 接口的公共部分。示例代码中,RequiredArg 和 OptionalArg 的差异就是 required 字段和与之对应的 value 值。通过交叉类型,可以让我们更好地进行代码复用,并方便地实现把多种类型叠加到一起成为一种新的类型。

    三、参考资源

    • tslang-advanced-types

    • typescript-interp-types

    往期精彩回顾

    常用消息摘要算法简介

    一文读懂Base64编码

    TypeScript 设计模式之适配器模式

    布隆过滤器你值得拥有的开发利器

    在前端 Word 还能这样玩

    个人博客:http://www.pingan8787.com 微信公众号【前端自习课】和千万网友一起,每日清晨,享受一篇前端优秀文章。 目前已连续推送文章 600+ 天,愿每个人的初心都能一直坚持下去!
  • 相关阅读:
    vscode中golang插件配置
    好用的go开源模块汇总
    常用linux指令
    读大嘴生平咨询---->关于商业模式的思考
    photoprism 源码阅读
    C语言的算法
    C语言输出函数和输入函数
    C语言基本概念
    servlet(3)
    servlet(2)
  • 原文地址:https://www.cnblogs.com/pingan8787/p/13069491.html
Copyright © 2011-2022 走看看