控制流分析(Control Flow Analysis)

描述:

CFA 几乎总是采用联合,基于代码逻辑去减少联合里面的类型数量。
大多数时候,CFA 在自然的JavaScript布尔逻辑中工作,但是有一些方法可以定义你自己的函数,这些函数会影响 TypeScript 缩小类型的方式。

简单说就是:根据代码上下文可以推断出当前变量类型。

if 语法(If Statements)

大多数窄化来自 if 语句,用不同类型操作符,在新作用域内进行窄化
typeof (用来判断原始类型)
const input = getUserInput()
input // string | number
if (typeof input === "string") {
input // string
}
instanceof (判断构造函数)
const input = getUserInput()
input // string | number[]
if (input instanceof Array) {
input // number[]
}
in (判断属性是否属于对象)
const input = getUserInput()
input // string | {error: ...}
if ("error" in input) {
input // {error: ...}
}
Array.isArray (判断是否为数组)
const input = getUserInput()
input // number | number[]
if (Array.isArray(input)) {
input // number[]
}

表达式(Expressions)

当进行布尔运算时,窄化也发生在代码的同一行
const input = getUserInput()
input // string | number
const inputLength = (typeof input === "string" && input.length) || input
                           //&& input: string

识别联合(Discriminated Unions )

type JSONResponse = {status: 200, data: any}
| {status: 300, to: string}
| {status: 400, error: Error}
所有联合成员都有相同属性名称,CFA(Control Flow Analysis) 能识别对待
const response = getResponse()
response // JSONResponse switch(response.status) {
case 200: response.data
case 400: redirect(response.to)
case 500: response.error
}

类型保护(Type Guards)类型谓词(type predicates)

定义用户定义的类型的守卫,只需要定义一个函数返回类型为类型谓词
下面例子中,isFish 就是类型守卫
type Fish = { name: string; swim: () => string };
type Bird = { name: string; fly: () => string };
const fish: Fish = { name: "sharkey", swim: () => 'asd' }
const bird: Bird = { name: "noob", fly: () => 'asd' } // 未使用类型谓词
function isFish(pet: Fish | Bird) {
return (pet as Fish).swim !== undefined;
}
const foo: Fish | Bird = Math.random() ? fish : bird;
if (isFish(foo)) {
// foo: Fish | Bird
foo.swim() // 不能调用,不确定是 Fish 类型
}
// 使用类型谓词
function isFish(pet: Fish | Bird): pet is Fish {
return (pet as Fish).swim !== undefined;
}
const foo: Fish | Bird = Math.random() ? fish : bird;
if (isFish(foo)) {
// foo: Fish
foo.swim() // ok
}
// 必须是当前函数签名中参数的名称(pet)。
// 如果特定类型与原始类型兼容(Fish 与 Fish | Bird),TypeScript 会将该变量缩小为该特定类型,不兼容会报错
可以使用类型守卫,过滤一个 Fish | Bird 类型数组,并获得一个 Fish 类型数组:
const zoo: (Fish | Bird)[] = [getSmallPet(), getSmallPet(), getSmallPet()];
const underWater1: Fish[] = zoo.filter(isFish);
// 相当于
const underWater2: Fish[] = zoo.filter(isFish) as Fish[]; // 复杂的例子,谓词需要重复
const underWater3: Fish[] = zoo.filter((pet): pet is Fish => {
if (pet.name === "sharkey") return false;
return isFish(pet);
});

断言函数(Assertion Functions)

谓词是,函数返回 true,然后根据代码逻辑在新作用域中表示特定类型
断言函数是抛出,而不是返回 false,然后改变当前作用域表示特定类型
type SuccessResponse = {data: string}
type ErrorResponse = {msg: string}
class JSONResponse implements SuccessResponse {
constructor(public data: string) { }
}
function assertResponse(obj: SuccessResponse | ErrorResponse): asserts obj is ErrorResponse {
if (!(obj instanceof JSONResponse)) {
throw new Error("Not a success!")
}
}
const res = getResponse();
res // SuccessResponse | ErrorResponse
assertResponse(res) // 断言函数更改当前作用域
res // ErrorResponse

赋值(Assignment)

使用 "as const" 缩小类型
对象中的属性被视为可变的,在赋值过程中,类型将被“拓宽”为非字面量类型。前缀“as const”将所有类型锁定为它们的字面量类型。
const data1 = { name: "Zagreus" }
const data2 = { name: "Zagreus" } as const
// data1: {name: string}
// data2: { readonly name: "Zagreus"}
跟踪相关变量
class SuccessResponse { }
const response = getResponse()
const isSuccessResponse = response instanceof SuccessResponse
if (isSuccessResponse) {
response // SuccessResponse
}
重新赋值更新类型
let data: string | number = Math.random() ? "asd" : 123
data // string | number
data = "hello"
data // string
 
 
 
 

TypeScript 之 控制流分析(Control Flow Analysis)的更多相关文章

  1. 南大《软件分析》课程笔记——Data Flow Analysis

    南大<软件分析>--Data Flow Analysis @(静态分析) 目录 数据流分析概述 数据流分析应用 Reaching Definitions Analysis(may anal ...

  2. SSIS的 Data Flow 和 Control Flow

    Control Flow 和 Data Flow,是SSIS Design中主要用到的两个Tab,理解这两个Tab的作用,对设计更高效的package十分重要. 一,Control Flow 在Con ...

  3. Control Flow 如何处理 Error

    在Package的执行过程中,如果在Data Flow中出现Error,那么Data Flow component能够将错误行输出,只需要在组件的ErrorOutput中进行简单地配置,参考<D ...

  4. 关于Control flow

    1.一个package包含一个control flow并且一个或多个data flow. (这个项目叫做 Integration services project,提供了三种不同类型的control  ...

  5. Core Java Volume I — 3.8. Control Flow

    3.8. Control FlowJava, like any programming language, supports both conditional statements and loops ...

  6. SSIS ->> Control Flow And Data Flow

    In the Control Flow, the task is the smallest unit of work, and a task requires completion (success, ...

  7. Control Flow in Async Programs

    Control Flow in Async Programs You can write and maintain asynchronous programs more easily by using ...

  8. A swift Tour(2) Control Flow

    Control Flow 用 if 和 switch 来做条件语句,并且用for-in,for,while,和do-while做循环,条件和循环的括号是可以不写的,但是body外面的括号是必须写的 l ...

  9. [译]Stairway to Integration Services Level 9 - Control Flow Task Errors

    介绍 在本文中,我们会实验 MaximumErrorCount和ForceExecutioResult 故障容差属性,并且还要学习Control Flow task errors, event han ...

  10. 《CS:APP》 chapter 8 Exceptional Control Flow 注意事项

    Exceptional Control Flow The program counter assumes a sequence of values                            ...

随机推荐

  1. 第一个Django应用 - 第五部分:测试

    一.自动化测试概述 什么是自动化测试 测试是一种例行的.不可缺失的工作,用于检查你的程序是否符合预期. 测试可以划分为不同的级别.一些测试可能专注于小细节(比如某一个模型的方法是否会返回预期的值?), ...

  2. 0-mysql数据库下载及安装

    1 下载mysql源安装包 wget http://dev.mysql.com/get/mysql57-community-release-el7-8.noarch.rpm 2 安装mysql源 yu ...

  3. 打印 Logger 日志时,需不需要再封装一下工具类?

    在开发过程中,打印日志是必不可少的,因为日志关乎于应用的问题排查.应用监控等.现在打印日志一般都是使用 slf4j,因为使用日志门面,有助于打印方式统一,即使后面更换日志框架,也非常方便.在 < ...

  4. 数据火器库八卦系列之瑞士军刀随APP携带的SQLite

    来源:云数据库技术 数据库打工仔喃喃自语的八卦历史 1. 为导弹巡洋舰设计,用在手机上的数据库 2. Small and Simple, and Better 3. 如何看出是自己的娃:产品定位,特点 ...

  5. gin项目部署到服务器并后台启动

    前言 我们写好的gin项目想要部署在服务器上,我们应该怎么做呢,接下来我会详细的讲解一下部署教程. 1.首先我们要有一台虚拟机,虚拟机上安装好go框架. 2.将写好的项目上传到虚拟机上. 3.下载好项 ...

  6. 使用SqlDataReader对象从数据库中检索只读的数据。

    SqlDataReader对象每次从查询结果中读取一行到内存中,对于sql数据库,如果只需要顺序读取,可以优先选择SqlDataReader,其对数据库的读取速度非常快. 调用SqlDataReade ...

  7. aws-s3-国际global与国内CN的一些说明

    S3云存储国际版最近经常被墙,国内部分地区有时能正常上传下载,有时也会直接报错网络错误等信息, 所以建议S3使用国内AWS的.国内S3与国外S3在使用时需要注意以下几点: 1)URL不通用 国际版的S ...

  8. vue项目Eslint和prettier结合使用

    一.eslint介绍--代码语法检查工具 Eslint是一个代码检查工具,用来检查你的代码语法是否符合指定的规范,ECMAScript标准 二.prettier插件--代码格式化工具 prettier ...

  9. 【多服务场景化解决方案】AR虚拟技术助力智能家装

    ​ 1 .介绍 总览 本应用采用了华为图形引擎服务的AR虚拟技术,您可以在手机相机里摆放想要购置的家具家电,交互式体验让您可以轻松操控它们的3D图例,以此来确定这些家具家电是否适合摆放在您的家里. 特 ...

  10. nrf52——DFU升级OTA升级方式详解(基于SDK开发例程)

    在我们开始前,默认你已经安装好了一些基础工具,如nrfutil,如果你没有安装过请根据官方中文博客去安装好这些基础工具,连接如下:Nordic nRF5 SDK开发环境搭建(nRF51/nRF52芯片 ...