Narrowing概念:字面意思是缩小,可以理解为细化或者您觉得更好的代名词。

TS官方在这里做了很详细的说明,文字较多,简单以图片概括:

typeof  type guards 类型防护过程,可以通过 typeof 检测出大部分类型并对比预设类型,如:

  • "string"
  • "number"
  • "boolean"
  • "symbol"
  • "undefined"
  • "object"
  • "function"

但是对于特殊的对象,比如 null ,typeof 就无能为力了,因为 typeof null === 'object'。看个例子:

function printAll(strs: string | string[] | null) {
  if (typeof strs === "object") {
    for (const s of strs) {   //for of 遍历数组中的元素

      //  Object is possibly 'null'.Object is possibly 'null'.

      console.log(s);
  }
  } else if (typeof strs === "string") {
    console.log(strs);
  } else {
    // do nothing
  }
}
 
布尔值运算
因为对下列这些对象进行布尔运算返回都是 false : 
  • 0
  • NaN
  • null
  • undefined
  • ""

所以上面的例子可以先对 null 进行判断然后执行后面的逻辑

function printAll(strs: string | string[] | null) {
  if (strs && typeof strs === "object") {
    for (const s of strs) {   //for of 遍历数组中的元素

      // strs 如果是null则跳过这个分支

      console.log(s);
  }
  } else if (typeof strs === "string") {
    console.log(strs);
  } 
}
 
思考以下两个方法有何不同?
 
function printAll(strs: string | string[] | null) {
  if (strs) {
    if (typeof strs === "object") {
      for (const s of strs) {
        console.log(s);
      }
    } else if (typeof strs === "string") {
      console.log(strs);
    }
  }
}
 
function anotherPrintAll(strs: string | string[] | null) {
  if (strs !== null) {
    if (typeof strs === "object") {
      for (const s of strs) {
        console.log(s);
      }
    } else if (typeof strs === "string") {
      console.log(strs);
    }
  }
}
 
  使用 in 操作符进行类型缩小
js中使用in操作符可以判单一个对象是否拥有某个属性,ts 也将in作为缩小类型判断的方式。
比如在一个联合类型中,可以这样判断 'value' in x,
x可能是 type Animal = Fish | Bird, value 表示 x 中的某一个字面量(可能是Fish或者Bird)
 
type Fish = { swim: () => void };
type Bird = { fly: () => void };
function move(animal: Fish | Bird) {
  if ("swim" in animal) {
    return animal.swim();
  }
  return animal.fly();
}
 
使用类型谓词
有时候我们希望从更多角度控制类型的检测,定义一个自定义的类型防护,即定义一个返回类型的方法就是一个类型谓词。
例如:
function isFish(pet: Fish | Bird): pet is Fish {
  return (pet as Fish).swim !== undefined;
}
pet is Fish 就是一个类型谓词。定义一个类型谓词的方式:参数名称 is 类型名称,参数名称必须是当前方法的一个参数。
任何时候,只要isFish携带参数调用了,如果原始类型兼容,TypeScript会将该变量缩小到该特定类型。
例如:
 
let pet = getSmallPet();
if(isFish(pet)) {
  pet.swim();
} else {
  pet.fly();
}
 
ts可以在if分支处得知pet是一条能游的Fish,当然了在else分支处pet被当作一只能飞的Bird。
当然了,你可以使用isFish这个类型防护去过滤一个包含了飞鸟与鱼的数组,最后得到一个尽是鱼的数组。
例如:
 
const zoo: (Fish | Bird)[] = [getSmallPet(), getSmallPet(), getSmallPet()];
const underWater: Fish[] = zoo.filter(isFish)

TypeScript 中文教程之缩小----部分翻译自TS官方的更多相关文章

  1. TYPESCRIPT中文教程基础部分下----翻译自TS官方

    type 别名 我们已经使用过 object 和 联合的方式 直接声明类型.但是某个类型在使用多次的情况下就要用到别名了. 别名的语法就像是在定义一个具名的对象一样: type Point = { x ...

  2. TypeScript中文教程基础部分上----翻译自TS官方

    为什么使用TS? js中每一个值在不同的操作运行中表现出一系列不同的行为,比如说下面这个例子: message.toLowerCase();message(); 逐行看下,第一行调用了message的 ...

  3. 【翻译】在TypeScript中,Extends和Implements一个抽象类有什么不同

    我们知道在TypeScript中一个类既可以被implement也可以被extends,有一些C#或java基础的同学可能会对此感到困惑,因为在上述两个面向对象的语言里面只有接口可以被implemen ...

  4. Intellij IDEA 2017 详细图文教程之概述

    天天编码 , 版权所有丨本文标题:Intellij IDEA 2017 详细图文教程之概述 转载请保留页面地址:http://www.tiantianbianma.com/intellij-idea- ...

  5. TypeScript Handbook 1——基本类型(翻译)

    原文出处: http://www.typescriptlang.org/Handbook 基于对web开发的需要和对安神的崇拜,打算学习一下typescript. 能力有限,基本属于在自己认识的基础上 ...

  6. 5种在TypeScript中使用的类型保护

    摘要:在本文中,回顾了TypeScript中几个最有用的类型保护,并通过几个例子来了解它们的实际应用. 本文分享自华为云社区<如何在TypeScript中使用类型保护>,作者:Ocean2 ...

  7. 【TypeScript】如何在TypeScript中使用async/await,让你的代码更像C#。

    [TypeScript]如何在TypeScript中使用async/await,让你的代码更像C#. async/await 提到这个东西,大家应该都很熟悉.最出名的可能就是C#中的,但也有其它语言也 ...

  8. TypeScript中的怪语法

    TypeScript中的怪语法 如何处理undefined 和 null undefined的含义是:一个变量没有初始化. null的含义是:一个变量的值是空. undefined 和 null 的最 ...

  9. JavaScript 和 TypeScript 中的 class

    对于一个前端开发者来说,很少用到 class ,因为在 JavaScript 中更多的是 函数式 编程,抬手就是一个 function,几乎不见 class 或 new 的踪影.所以 设计模式 也是大 ...

随机推荐

  1. SpringIOC原理

    IOC(DI):其实这个Spring架构核心的概念没有这么复杂,更不像有些书上描述的那样晦涩.java程序员都知道:java程序中的每个业务逻辑至少需要两个或以上的对象来协作完成,通常,每个对象在使用 ...

  2. Spring Boot with H2 Database

    Learn to configure H2 database with Spring boot to create and use an in-memory database in runtime, ...

  3. js - 日期、时间 Date对象方法

    Date 是 JS 内置的日期构造函数 var d = new Date();  // 这个是系统当前时间的日期实例 d.getYear(); // 返回 d 实例年份 - 1900 d.getFul ...

  4. 用户信息查询系统_daoImpl

    package com.hopetesting.dao.impl;import com.hopetesting.dao.UserDao;import com.hopetesting.domain.Us ...

  5. [MySQL实战-Mysql基础篇]-mysql架构

    1.基本组成 下面是mysql的基本架构示意图  图一 图二 我们可以从图上看出,mysql大体分为两个部分,一个是server层,另一个是引擎层. server层中包含了连接器.查询缓存.分析器.优 ...

  6. 为什么企业全面云化需要IT战略支撑和驱动?

    引子:为什么传统企业全面云化一直磨磨唧唧举步维艰? 笔者将企业上云大体上分为几个阶段: 第一个阶段是基础设施虚拟化.即将应用从物理机搬到(lift and shift migration)虚拟机上.基 ...

  7. 阿里云RDS备份 恢复到本地

    目录 一.恢复准备 二.具体操作 一.恢复准备 阿里云RDS默认配置了全备份+binlog,可以精准恢复到某个时间点上. 可以下载备份的包到本地,进行本地恢复,要预留好本地的数据库容量和cpu等规格, ...

  8. 如何查看Python中所有关键字

    一.保留字即关键字,我们不能把它们用作任何标识符名称.Python的标准库提供了一个keyword模块,可以输出当前版本的所有关键字 import keyword print(keyword.kwli ...

  9. Memcached 状态机分析

    worker线程拿到了这个连接之后,就应该是分配给这个连接一个结构体,包括这个连接所有的状态,都写buf等,这个结构体就是conn,然后这个worker线程会在它自己的event_base加入对这个新 ...

  10. mysql的事务详解

    事务及其ACID属性 事务是由一组SQL语句组成的逻辑处理单元,事务具有以下4个属性,通常简称为事务的ACID属性. 原子性(Atomicity) :事务是一个原子操作单元,其对数据的修改,要么全都执 ...