控制流分析(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. Ceph 有关知识简介

    Ceph 存储集群至少需要一个 Ceph Monitor 和两个 OSD 守护进程.而运行 Ceph 文件系统客户端时,则必须要有元数据服务器( Metadata Server ). Ceph OSD ...

  2. haproxy + keeplived

    两台主机: 192.168.2.163 192.168.2.165 # yum安装haproxy yum install haproxy # cat /etc/haproxy/haproxy.cfg ...

  3. 7M与N的数学运算

    m=eval(input()) n=eval(input()) a=m+n b=m*n c=m**n d=m%n e=max(m,n) print(a,b,c,d,e)

  4. Jquery封装的ajax的使用过程发生的问题

    Jquery封装的ajax的使用过程发生的问题 今天在做项目的时候使用到了ajax来完成项目前后端数据交互,在之后发现在前端没有数据显示,而后端数据确实存在,在多次检查代码之后,发现代码并不存在问题, ...

  5. TensorFlow搭建模型方式总结

    引言 TensorFlow提供了多种API,使得入门者和专家可以根据自己的需求选择不同的API搭建模型. 基于Keras Sequential API搭建模型 Sequential适用于线性堆叠的方式 ...

  6. uoj348【WC2018】州区划分

    题目链接 直接讲吨吨吨给的标准做法吧.记\(f(i,j)\)表示各个州(可以重叠)的城市数量之和为i,这些州的并集为j的方案数,反正若有两个州之间有交集最后的\(|j|\)会不等于\(i\).有 \( ...

  7. 微信小程序——悬浮按钮

    关键:    position: fixed; wxml: <navigator url="/pages/issue/index"><image class='i ...

  8. numpy常用知识点备忘(2)

    x.ravel() 和 x.flatten() : 将多为数组降维到1维.ravel()返回元素的引用(对象不一样,但是元素是引用),flatten()返回新的元素. np.meshgrid(x, y ...

  9. 基于python的数学建模---pulp库

    instance 代码: import pulp z = [2, 3, 1] a = [[1, 4, 2], [3, 2, 0]] b = [8, 6] aeq = [[1,2,4]] beq = [ ...

  10. Python中 or、and 的优先级

    上式可以看出  先看 and 输出才为 ture 因此  优先级 and>or