TypeScript学习8:高级类型-交叉类型、联合类型

简介

此为高级类型的第一部分,学习交叉类型(Intersection Types)、联合类型(Union Types)以及在使用以上类型时如何区分具体类型。

交叉类型(Intersection Types)

交叉类型把几个类型的成员合并,形成一个拥有这几个类型所有成员的新类型。从字面上理解,可能会误认为是把取出几个类型交叉的(即交集)成员。

交叉类型的使用场景:Mixins、不适合用类来定义。

我感觉,交叉类型和Mixins有一点区别:交叉类型只是一个类型声明,用于类型约束;Mixins会给类增加成员,new对象时,对象会包含增加的成员属性。

我们看一看示例:

改自官方示例,官方示例有2个小问题:会提示不存在属性“hasOwnProperty”;另外,es6下prototype是不可以枚举的,无法通过枚举合并类属性。

interface IAnyObject {
    [prop: string]: any
  }

  function extend<First extends IAnyObject, Second extends IAnyObject>(first: First, second: Second): First & Second {
    const result: Partial<First & Second> = {};
    for (const prop in first) {
      if (first.hasOwnProperty(prop)) {
        (result as First)[prop] = first[prop];
      }
    }
    for (const prop in second) {
      if (second.hasOwnProperty(prop)) {
        (result as Second)[prop] = second[prop];
      }
    }
    return result as First & Second;
  }

  interface IPerson {
    name: string,
    age: number
  }

  interface IOrdered {
    serialNo: number,
    getSerialNo(): number
  }

  const personA: IPerson = {
    name: 'Jim',
    age: 20
  }

  const orderOne: IOrdered = {
    serialNo: 1,
    getSerialNo: function () { return this.serialNo }
  }

  const personAOrdered = extend<IPerson, IOrdered>(personA, orderOne);
  console.log(personAOrdered.getSerialNo());
  • 其中First & Second就是交叉类型的写法。
  • 通过扩展,可以合并两传入对象的成员属性,增强现有对象的能力。

联合类型(Union Types)

联合类型与交叉类型类似,都可以拥有多个类型的能力,区别是:联合类型一次只能一种类型;而交叉类型每次都是多个类型的合并类型。

联合类型在实际项目中,使用场景比交叉类型广泛得多。

  1. 字符串填充:
function padLeft(value: string, padding: number | string) {
    if (typeof padding === "number") {
      return Array(padding + 1).join(" ") + value;
    }
    if (typeof padding === "string") {
      return padding + value;
    }
    return value;
  }

  padLeft("Hello world", 4);
  1. 再举个常见的例子,常量的联合类型,五分制考试打分:
type Scores = 1 | 2 | 3 | 4 | 5;

  function rating(score: Scores) {
    console.log(`Set score ${score}`);
  }

  rating(3);
  // error
  // rating(6); 

枚举也可以实现,但是这样更简洁。

  1. 还可以用于可为null的参数:
function f(sn: string | null): string {
    if (typeof sn === null) {
        return 'default';
    } else {
        return sn;
    }
}
  1. 还可以使用类型别名定义联合类型(上面场景2中用过):
type Method = 'get' | 'post';

类型保护和类型区分

使用联合类型时,我们是无法知道编译时的具体类型的,所以在运行时必须要确定类型。所以代码中需要做类型保护和类型区分。

为什么叫类型保护?因为在运行时,必须知道明确类型,否则可能会访问一个不存在的成员属性,导致程序出错。

  • 自定义类型保护

    // 先判断是否存在成员属性
      if(pet.swim) {
    
      }
  • in操作符

    // 先判断是否存在成员属性
      if('swim' in pet) {
    
      }
  • typeof操作符

    function f(sn: string | number): string {
        if (typeof sn === 'number') {
            return sn.toString();
        } else {
            return sn;
        }
    }
  • instanceof操作符

    // 判断实例原型
    if(pet instanceof Fish) {
    
    }
  • 类型断言

    function f(sn: string | null): string {
        if (sn === null) {
            return "default";
        } else {
            return sn;
        }
    }

联合类型应用极广泛,可以多实践。

原文链接:segmentfault.com

上一篇:理解:before伪类搭配vertical-align:middle实现垂直居中的原理
下一篇:抓取县市地图json数据

相关推荐

  • 面试官问你基本类型时他想知道什么

    前言: 面试的时候我们经常会被问答js的数据类型。大部分情况我们会这样回答包括 1、基本类型(值类型或者原始类型): Number、Boolean、String、NULL、Undefined以及E...

    1 年前
  • 面向对象不是银弹,DDD 也不是,TypeScript 才是

    要解决的问题是什么? A problem wellstated is Halfsolved Fred Brooks 在著名的"No Silver Bullet Essence and Acci...

    10 个月前
  • 静态类型检测器—Flow入门

    介绍 一个 JAVASCRIPT 静态类型检测器 Flow 使用类型接口查找错误,甚至不需要任何类型声明。 它也能够准确地跟踪变量的类型,就像运行时那样 Flow 专为 JavaSc...

    2 年前
  • 静态类型检查—Flow入门

    介绍 一个 JAVASCRIPT 静态类型检测器 Flow 使用类型接口查找错误,甚至不需要任何类型声明。 它也能够准确地跟踪变量的类型,就像运行时那样 Flow 专为 JavaSc...

    2 年前
  • 重读《学习JavaScript数据结构与算法-第三版》-第2章 ECMAScript与TypeScript概述

    定场诗 八月中秋白露,路上行人凄凉; 小桥流水桂花香,日夜千思万想。 心中不得宁静,清早览罢文章, 十年寒苦在书房,方显才高志广。 前言 洛伊安妮·格罗纳女士所著的《学习JavaScr...

    10 个月前
  • 重温Javascript:数据类型

    数据类型.png(https://img.javascriptcn.com/c8e734a064b405495051da1ed89158ac "数据类型.png") 类型判断 Javascri...

    6 个月前
  • 重学JS:显示强制类型转换

    ToString ToString负责处理非字符串到字符串的强制类型转换,常用的字符串化方法String()、toString()。 基本类型值的字符串化规则: null转换为'null'...

    1 年前
  • 重学JS: 隐式强制类型转换

    隐式强制类型转换指的是那些隐藏的强制类型转换,副作用也不是很明显,事实上,只要自己觉得不够明显的强制类型转换都可以算作隐式强制类型转换,接下来,此文将会介绍几种常见的隐式类型转换。

    1 年前
  • 重学JS: 数据类型及类型检测

    数据类型 JavaScript七种内置类型: 空值(null) 未定义(undefined) 布尔值(boolean) 数字(number) 字符串(string)...

    1 年前
  • 那些鲜为人知的 TypeScript 功能

    原文地址: medium.com/articode/so… 译文地址:github.com/xiaoT/note… 本文版权归原作者所有,翻译仅用于学习。 过去的几年中,TypeScript 已...

    12 天前

官方社区

扫码加入 JavaScript 社区