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. 【Java 8】Stream API

    转自 Java 8 Stream Java8的两个重大改变,一个是Lambda表达式,另一个就是本节要讲的Stream API表达式.Stream 是Java8中处理集合的关键抽象概念,它可以对集合进 ...

  2. 【Matlab】find函数用法

    find(A):返回向量中非零元素的位置 注意返回的是位置的脚标 //类似python,还是很好用的 如果是二维矩阵,是先横行后列的 b=find(a),a是一个矩阵,查询非零元素的位置 如果X是一个 ...

  3. 07-Spring5 WebFlux响应式编程

    SpringWebFlux介绍 简介 SpringWebFlux是Spring5添加的新模块,用于Web开发,功能和SpringMvc类似的,WebFlux使用当前一种比较流行的响应式编程框架 使用传 ...

  4. DevOps的分与合

    一.抽象的 DevOps DevOps 是使软件开发和 IT 团队之间的流程自动化的一组实践,以便他们可以更快,更可靠地构建,测试和发布软件.DevOps 的概念建立在建立团队之间协作文化的基础上,这 ...

  5. TCP链接请求的10种状态

    一.状态显示 SYN_SENT:这个状态与SYN_RCVD遥相呼应,当客户端SOCKET执行CONNECT连接时,它首先发送SYN报文,随即进入到了SYN_SENT状态,并等待服务端的发送三次握手中的 ...

  6. centos部署配置gogs代码仓库

    目录 一.简介 二.部署 三.网页配置 一.简介 Gogs的目标是打造一个最简单.最快速和最轻松的方式搭建自助Git服务.使用Go语言开发使得Gogs能够通过独立的二进制分发,并且支持Go语言支持的 ...

  7. pipeline parameters指令

    目录 一.简介 二.类型 参数类型 多参数 一.简介 参数化pipeline是指通过传参来决定pipeline的行为.参数化让写pipeline就像写函数,而函数意味着可重用.更抽象.所以,通常使用参 ...

  8. inode节点

    目录 一.简介 二.信息 inode的内容 inode的大小 3.inode号码 三.目录文件 四.硬连接 五.软链接 六.inode的特殊作用 一.简介 理解inode,要从文件储存说起. 文件储存 ...

  9. Linux下安装gbd

    目录 一.简介 二.部署 一.简介 gdb是Linux环境下的代码调试工具 二.部署 1.首先检查系统中有没有安装过,有的话用一下命令卸载gdb旧版本 2.安装依赖 yum -y install gc ...

  10. Eclipse切换不同版本的jdk

    var会在java1.8中报错,安装10版本以上的jdk可以解决问题,但是安装后Eclipse无法正常工作,后来发现是Eclipse没有切换版本,在网上找了好多教程都是切换系统变量,后来我发现可以直接 ...