《Effective TypeScript》条款22 - 类型收缩
本文主要记录书中关于TypeScript类型收缩的内容
本文主要内容如下
- 类型收缩的一些方法
- 条件判断
- 抛错误
- instanceof 和 in 属性检查
- “标签联合”或“可辨识联合”
- 类型收缩的失效示例
- 自定义类型保护
- 总结
类型收缩的方法
条件判断
const el = document.getElementById("foo");
if (el) {
el; // 类型是HTMLElement
} else {
el; // 类型是 null
}
如果 el 是 null,那么第一个分支的代码就不会执行,所以 TypeScript 能够在这个代码块中推断出一个更容易处理的类型。
抛错误
const el = document.getElementById("foo");
if(!el) throw new Error('未找到元素');
el.innerHTML = 'Hello World'; //HTMLElement
instanceof 和 in 属性检查
function contains (text:string,search:string|RegExp) {
if(search instanceof RegExp) {
// 类型是Regexp
return !!search.test(text);
}
// 类型是 string
return text.includes(search);
}
interface A {a:number}
interface A {a:number}
interface B {b:number}
function pickAB(ab:A|B) {
if('a' in ab) {
ab // 类型是A
} else {
ab // 类型是B
}
ab // 类型是A|B
}
ps:原文中提到一个示例如下:
function contains(text:string,terms:string|string[]) {
const termList = Array.isArray(terms) ? terms : [terms];
termList // 类型是 string[]
}
这是通过内置函数来完成类型收缩的
“标签联合”或“可辨识联合”
interface UploadEvent {type:'upload',filename:string;content:string}
interface DownloadEvent {type:'download',filename:string;}
type AppEvent = UploadEvent|DownloadEvent;
function handleEvent(e:AppEvent) {
switch(e.type) {
case "upload":
e // 类型是UploadEvent
break;
case 'download':
e // 类型是Download
break;
}
}
帮助检查器收缩范围的常见方法是给他们加上一个明确的“标签”,这种模式称为 “标签联合” 或 “可辨识联合”,它在TypeScript中很常见。
类型收缩的失效示例
const el = document.querySelector('#foo');
if(typeof el === 'object') {
el; // Element | null
}
在 JavaScript 中,typeof null 也是 "object",所以这个类型收缩是不成立的,类似的还有如下这样:
function foo(x?:number|string|null) {
if(!x) {
x // string | number | null | undefined
}
}
自定义类型保护
function isInputElement(el:HTMLElement): el is HTMLInputElement {
return 'value' in el;
}
function getElementContent(el:HTMLElement) {
if(isInputElement(el)) {
el // 类型是 HTMLInputElement;
return el.value;
}
return el.textContent; // 类型是 HTMLElement
}
这就是所谓的“自定义类型保护”,el is HTMLInputElement 作为返回值,如果函数返回true,它可以收缩类型的参数。
跨数组或对象的类型收缩
const students = ["小明", "小红", "小柔"]; // const people = ["小红", "小柔"].map((who) => students.find((n) => n === who)); //类型 (string | undefined)[] // 如果用filter过滤undefined,TypeScript 无法跟上filter的逻辑 // const people = ["小红", "小柔"]
// .map((who) => students.find((n) => n === who))
// .filter((who) => who != undefined);
// 类型仍然是 (string | undefined)[] // 但是使用类型保护就可以 function isDefined<T>(x:T|undefined):x is T {
return x != undefined;
} const people = ["小红", "小柔"]
.map((who) => students.find((n) => n === who))
.filter(isDefined);
// 类型是 string[]
总结
- 了解TypeScript如何根据条件和其他类型的控制流来收缩类型。
- 使用标记/可辨识类型或者自定义类型保护来收缩类型。
《Effective TypeScript》条款22 - 类型收缩的更多相关文章
- [More Effective C++]条款22有关返回值优化的验证结果
(这里的验证结果是针对返回值优化的,其实和条款22本身所说的,考虑以操作符复合形式(op=)取代其独身形式(op),关系不大.书生注) 在[More Effective C++]条款22的最后,在返回 ...
- Effective C++ -----条款22:将成员变量声明为private
切记将成员变量声明为private.这可赋予客户访问数据的一致性.可细微划分访问控制.允诺约束条件获得保证,并提供class作者以充分的实现弹性. protected并不比public更具有封装性.
- More Effective C++ 条款0,1
More Effective C++ 条款0,1 条款0 关于编译器 不同的编译器支持C++的特性能力不同.有些编译器不支持bool类型,此时可用 enum bool{false, true};枚举类 ...
- TypeScript完全解读(26课时)_11.TypeScript完全解读-类型推论和兼容性
11.TypeScript完全解读-类型推论和兼容性 在一些时候省略指令,ts会帮我们推断出省略的类型的地方适合的类型,通过学习ts的类型推论了解ts的推论规则 类型兼容性就是为了适应js灵活的特点, ...
- TypeScript Type Compatibility(类型兼容)
TypeScript中的类型兼容是基于结构归类的.在普通分类的相比之下,结构归类是一种纯粹用于将其成员的类型进行关联的方法.思考下面的代码: interface Named { name: strin ...
- TypeScript Type Innference(类型推断)
在这一节,我们将介绍TypeScript中的类型推断.我们将会讨论类型推断需要在何处用到以及如何推断. 基础 在TypeScript中,在几个没有明确指定类型注释的地方将会使用类型推断来提供类型信息. ...
- EC读书笔记系列之12:条款22、23、24
条款22 将成员变量声明为private 记住: ★切记将成员变量声明为private.这可赋予客户访问数据的一致性.可细微划分访问控制.允诺约束条件获得保证,并提供class作者以充分的实现弹性. ...
- TypeScript 之 基础类型、高级类型
基础类型:https://m.runoob.com/manual/gitbook/TypeScript/_book/doc/handbook/Basic%20Types.html 高级类型:https ...
- 聊聊 TypeScript 中的类型保护
聊聊 TypeScript 中的类型保护 在 TypeScript 中使用联合类型时,往往会碰到这种尴尬的情况: interface Bird { // 独有方法 fly(); // 共有方法 lay ...
随机推荐
- 【LeetCode】623. Add One Row to Tree 解题报告(Python)
[LeetCode]623. Add One Row to Tree 解题报告(Python) 标签(空格分隔): LeetCode 题目地址:https://leetcode.com/problem ...
- 【剑指Offer】序列化二叉树 解题报告(Python)
[剑指Offer]序列化二叉树 解题报告(Python) 标签(空格分隔): 剑指Offer 题目地址:https://www.nowcoder.com/ta/coding-interviews 题目 ...
- Python pyecharts绘制词云图
一.pyecharts绘制词云图WordCloud.add()方法简介 WordCloud.add()方法简介 add(name,attr,value, shape="circle" ...
- CapstoneCS5265|TYPEC转HDMI 4K60HZ转换方案设计|CS5265功能介绍
芯片简介描述:CS5265集成了一个DP1.4的转换器HDMI2.0转换.此外,CC控制器还用于CC通信,以实现DP Alt模式. CS5265是一种高度集成的单芯片,适用于多个细分市场和显示应用,如 ...
- MySQL高级查询与编程笔记 • 【目录】
章节 内容 实践练习 MySQL高级查询与编程作业目录(作业笔记) 第1章 MySQL高级查询与编程笔记 • [第1章 数据库设计原理与实战] 第2章 MySQL高级查询与编程笔记 • [第2章 数据 ...
- C#中的隐式转换
你是否考虑过这个问题:为什么不同类型之间的变量可以赋值,而不需要强制转换类型?如: int i = 1; long l = i; object obj = 1; Exception exception ...
- centos一步一步搭建tendermint
一.必要条件 1.安装go 请根据官方文档安装:https://golang.org/doc/install 要特别注意的是: /etc/profile 添加以下内容: export GOPATH=/ ...
- Appium服务器初始化参数(Capability)
原文:https://blog.csdn.net/lilongsy/article/details/83010101 appium官方说明:https://appium.io/docs/cn/writ ...
- Centos下查看cpu核数
1.概念物理CPU:实际Server中插槽上的CPU个数.物理cpu数量:可以数不重复的 physical id 有几个. 2.逻辑CPULinux用户对 /proc/cpuinfo 这个文件肯定不陌 ...
- Selenium_获取界面handle、title和url(7)
from selenium import webdriver driver = webdriver.Chrome() driver.maximize_window() driver.get(" ...