TypeScript 学习笔记 – Handbook 1
前言
一转眼, 一年多没有写 TypeScript 了. 最近又要开始写了, 乘此机会打算系统学习一下, 顺便写一个学习笔记.
我接触 TypeScript 比较早, 那是 Angular 2 beta 的年代, 那时候 TypeScript 还不到 1.8 呢. 后来都是看 What's New 一个一个版本跟着学. 所以学的很零散.
而且早些年真的很可怜, 总是被迫写出 AnyScript. (你看 Angular 的 Reactive forms 就知道了). 2.8 和 4.x 版本后才有了质的飞跃.
我理解的 TypeScript
我以前是写 C# 和 JS 的, 2 个语言切换着用, 不是翻译哦, 是很自然的开发后端就写 C#, 开发前端就写 JS, 写 JS 完全没有感觉需要类型检查. 当然那年的 JS 还不复杂 (ES5 的年代)
所以啊, 我一开始接触 TypeScript 的时候, 我是把它当 C# 看待的, 就写类型嘛. 但写着写着发现还是不一样.
写 C# 你开 class 是 ok 的, 但 JS 你不会很想去开 class. 你会想直接写对象. 总之就是写的方式和习惯不同. 所以你不能把 JS 当 C# 来写, 别扭.
TypeScript 定义 JS 的类型, 和写 C# 的那种定义类型的方式是不一样的. 尤其是动态和推导类型. 你得把 TypeScript 当成一个语言来使用,
动态和推导类型都是有逻辑的, 需要用语言才能表达. 这也是为什么 TypeScript 需要 conditional, keyof, in, 递归, 泛型函数的原因.
我觉得 TypeScript 可以分 3 个等级来学.
第一级是把 TypeScript 当 C# 来写. 声明静态类型就好了.
第二级就是用一些动态编辑类型. 比如 conditional types, keyof 这类的冬冬. 它们很大程度的让你写出动态的 JavaScript 和减少许多的 method overload.
第三级就是善用一堆的高级技巧, 完全把 TypeScript 当一门语言来写. 能灵活运用递归, 遍历等等技巧. 有到这个 level 就很方便了.
希望这次我有精力上到 level 3 呗.
这篇开始会把官网的 Handbook 和 Reference 过一遍, 并记入一些重点, 然后在写一些黑魔法例子, 之后就等我实战以后在慢慢补上来呗.
如果你和我一样有 C# 或 Java 静态语言的基础, 那么会更容易理解我的角度.
The Basics
TypeScript 的好处
JavaScript 是动态类型, 类型检查在 runtime 发生.
动态类型的好处是灵活, 代价是无法提前发现错误. TypeScript 就是让它变成静态类型, 类型检查发生在 compile time, 这样就可以提早报错.
常见的类型错误, 比如 string variable 当 number variable 用, 拿 string 调用方法 .toFixed(). 这个是 number 的方法, string 调用在 runtime 就报错了.
除了避免这种直接的类型错误外, 语言声明了类型, 意味着添加了限制, 也代表着你的表达范围小了, 他人就更容易判断出你的意图.
所以 IDE 就可以给出适当的提示, 自动纠错, 更严格的语法检查之类的助攻了.
tsc compiler
TypeScript 最终会被 compile 或者叫 transpile 去 JavaScript. 因为游览器只能解析 JavaScript 嘛.
所有的类型定义都会在这个过程种被删掉. 变成 pure JS. 此外, 重点来了, 由于有了 compile 这个过程, TypeScript 可以做很多额外的事.
比如重新定义 JavaScript 语法. 当然 TypeSript 是有原则的, 它不会去做这种事, 它只是提前让你使用游览器还没有实现的语法.
比如游览器只支持 ES5, 但是 JS 语法已经去到 ES6 了, 那么 TypeScript 会允许你些 ES6 的语法, 它在 compile 的时候, 转换成 ES5 的语法去实现同样的功能. 术语叫 downleveling.
当然也不是所有语法都可以 down level, 通常语法糖都是可以的. 这样就已经很甜了, 不是吗.
Everyday Types
JS 数据类型
TypeScript 除了有 JS 的数据类型, 还有一些额外的类型. 我们先来看看普通的
string, number, boolean, null, undefined, object, bigint, symbol
其中 symbot 需要 target ES2019, bigint ES2020 才能用哦.
Type Annotations 声明类型
和写 C# 类似, 在下面这 3 个地方会需要定义类似
1. variables
let stringValue: string = 'my value';
let numberValue: number = 100;
let obj: object = { };
TypeScript 的类型是写在 variable 后面的, 这个和 C# 不一样哦.
上面这种是比较传(guo)统(shi)的写法. 一般上面对直接赋值的 variables 是不声明类型的. 类似 C# 中使用 var 一样

TS 会依据变量值反向推导出类型.
2. function / method parameters & return
函数和方法的参数和返回值也是经常需要定义类型的地方.
function myFunction(arg1: string, arg2: boolean) : number {
return 100;
}
元括弧后面是函数返回值的类型. 总之和 C# 反着来就是了...
和 C# 不同, TS 的函数返回类型也具有推导功能哦

虽然如此, 但我个人还是推荐手动声明返回类型.
好处一是方便看, 推导需要 hover 才看得见.
好处二是可以检测代码写错, 变量的实现很短, 不太可能会写错. 函数就不同了, 实现逻辑可能比较长, 手动定义类型多一份检测.
3. class properties
class MyClass {
prop = 'stringValue';
method(arg: string) : string {
return ''
}
}
TS 数据类型
除了 JS 数据类型, TS 也扩展了一些类型
array
let stringArray : Array<string> = [];
let numberArray : number[] = [];
2 种写法是等价的, 我个人喜欢第 2 种 number[]
function
let method: (name: string, age: number) => string;
object types
let obj: { name: string };
obj = {
name : 'Derrick'
}
C# 只能通过 Class 声明对象类型, 这样很麻烦. TS 则有对象类型.
它很适合用在参数上
function fn(config: { name: string }): void {}
fn({ name: 'Derrick' });
TODO: 和 object Object types 的区别
union types
这个非常牛逼. 它可以把多个类型以 "或者" 的形式 combine 起来
let stringOrNumberValue: string | number;
stringOrNumberValue = 'stringValue';
stringOrNumberValue = 11;
如果是 C#, 那只能搞一个超级抽象的 object 类型, 而 TS 这个 union 就很方便.
使用方式:
function method(stringOrNumber: string | number) {
const value = stringOrNumber.toString(); // 只能调用 string 和 number 共同拥有的属性和方法
if(typeof stringOrNumber === 'string') {
const value = stringOrNumber.charAt(0); // 能调用 string 的属性和方法
}
else {
const value = stringOrNumber.toFixed(2); // 能调用 number 的属性和方法
}
}
在还没有经过类型判断 (typeof) 前, 只能使用 union 中每个类型都有的特性.
在经过判断以后, 就可以使用类型具体的特性. 上面可以看出 TS 的类型推导是非常聪明的.
TODO: intersection types
any
臭名远扬的 AnyScript 由来就是这个 any 了. any 类似 C# 的 object. 万物皆对象.
any 表示任何类型都 ok. 也就相等于没有声明类型了. 通常会用这个是为了 by pass 类型检查. 有时候 TS 的表达力不够, 或者需要很复杂的语法才能通过类型检查.
sometime 会有点得不偿失. 这时就可以 by pass 它. 海因里希法则 说过, 300 个隐患才会出大事故, 所以适当的 by pass 是 ok 的.
literal types

注意看, 它两的类型是不一样的.
第一个变量使用了 immutable 的 const, 推导出来的类型是 "Pending" 而不是 string. 这个类型就叫 literal types (文字类型)
第二个用了 mutable 的 let, 推导出来的类型是 string.
literal types 非常适合用来实现 string enum. 如下:

函数的参数只能输入 string "Pending" 或者 "Completed". 而不是任意的 string.
TODO: template literal types
enum
enum MyEnum {
Pending,
Completed,
WaitingForRework = 'Waiting for Rework'
}
let value: MyEnum;
value = MyEnum.Pending;
value = MyEnum.Completed;
console.log(value); // number: 1
value = MyEnum.WaitingForRework;
console.log(value) // string: Waiting for Rework
和 C# 的用法类型, 也支持 flags, 但官方不推荐使用. Enum 会增加复杂性, 如果只是想单纯的使用限定的 string value. 使用 union + literal types 会更合适.
interface
interface 的用法和 C# 类型. 使用关键字 interface 和 implement
interface CanFly {
fly() : void;
}
class Bird implements CanFly {
fly() {}
}
interface 有一个神奇的功能叫 add new fields to a existing interface
interface CanFly {
fly() : void;
}
interface CanFly {
walk(): void;
}
class Bird implements CanFly {
fly() {}
walk() {}
}
取相同名字, 就可以加入新的属性了.
另外 interface 还可以继承, 和 class 一样使用关键字 extends
interface CanFly {
fly() : void;
}
interface CanTurboFly extends CanFly {
turboFly(): void;
}
class Bird implements CanTurboFly {
fly() {};
turboFly() {}
}
TypeScript 学习笔记 – Handbook 1的更多相关文章
- Typescript 学习笔记七:泛型
中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...
- Typescript 学习笔记六:接口
中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...
- Typescript 学习笔记五:类
中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...
- Typescript 学习笔记四:回忆ES5 中的类
中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...
- Typescript 学习笔记二:数据类型
中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...
- Typescript 学习笔记三:函数
中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...
- Typescript 学习笔记一:介绍、安装、编译
前言 整理了一下 Typescript 的学习笔记,方便后期遗忘某个知识点的时候,快速回忆. 为了避免凌乱,用 gitbook 结合 marketdown 整理的. github地址是:ts-gitb ...
- TypeScript学习笔记(八):1.5版本之后的模块和命名空间
我之前有写过TS1.5版本之前的“模块”的笔记:TypeScript学习笔记(七):模块 但是TS这里的模块和在ECMAScript 2015里的模块(即JS原生支持了模块的概念)概率出现了混淆,所以 ...
- typescript学习笔记(三)---接口
关于第二章的学习笔记是变量声明. 接口:TypeScript的核心原则之一是对值所具有的结构进行类型检查. 它有时被称做“鸭式辨型法”或“结构性子类型化”. 在TypeScript里,接口的作用就是为 ...
- typescript学习笔记(一)---基础变量类型
作为一个前端开发者,学习新技术跟紧大趋势是必不可少的.随着2019年TS的大火,我打算利用一个月的时间学习这门语言.接下来的几篇文章是我学习TS的学习笔记,其中也会掺杂一些学习心得.话不多说,先从基础 ...
随机推荐
- 在Django中,多数据操作,你可以编写测试来查询另一个数据库服务器中的数据,并将结果导入当前Django项目的数据库表中
在Django中,你可以编写测试来查询另一个数据库服务器中的数据,并将结果导入当前Django项目的数据库表中.下面是一个简单的示例: 假设你有一个Django应用程序,名为myapp,并且你希望从另 ...
- [oeasy]python0068_ 字体样式_正常_加亮_变暗_控制序列
字体样式 回忆上次内容 上次了解了一个新的转义模式 \33 逃逸控制字符 esc esc 让输出 退出标准输出流 进行控制信息的设置 可以清屏 也可以设置光标输出的位置 还能做什么呢? 可以设置字符的 ...
- PyQt 右键菜单的实现(Qt.CustomContextMenu方式)
从Qt文档Qt::ContextMenuPolicy的值可以看出,实现右键菜单的方式有三种,这对于所有继承于QWidget的类都是通用的,在用每一种方式实现之前都要调用QWidget::setCont ...
- 深入理解Spring Boot:Bean管理、原理解析与Maven高级应用
深入理解Spring Boot:Bean管理.原理解析与Maven高级应用 前言 大家好,今天我们来聊聊Spring Boot的核心内容,包括Bean管理.Spring Boot的工作原理以及Mave ...
- 【Java】JDBC Part2 工具类封装实现
JDBC 工具类封装实现 - 注册和配置都放在静态代码块完成 - 静态方法获取连接,和释放资源 - 本类不产生实例 - 5版本 + 已经可以实现无驱动注册,所以驱动部分注释了 package cn.d ...
- 【RabbitMQ】09 深入部分P2 消费限流 & TTL
1.消费限流设置 就是设置项的2个调整,当然还有前面的手动确认的监听改动处理 https://www.bilibili.com/video/BV15k4y1k7Ep?p=26 2.消息过时设置 TTL ...
- 【SpringBoot】01 快速上手
环境搭建: JDK8 + IDEA 2018 + SpringBoot + Maven 3.0 + 创建Boot项目 2020.6.1更新补充: 最近才发现SpringBoot用IDEA构建项目会发生 ...
- 人形机器人(humanoid)的摔倒实验/撞击实验
motivation: 人形机器人的实体比较昂贵,但是实验过程中机器人的摔倒和撞击时十分常见的事情,这就会导致机器人的元器件被损坏,造成较大的经济损失,为此我们在设计机器人的机械结构和电子元器件布局时 ...
- 推荐一款好用的PDF转换工具,可以拆分、合并,亲测好用!!!
推荐一款好用的PDF转换工具,可以拆分.合并,等等操作,亲测好用. PS. 因为经常会遇到PDF的拆分需要,以前在网上的都是免费的,后来的也都变成付费的无水印的了,再然后就变成全都要收费了.尴尬的是, ...
- 人工智能、机器学习等科技领域论文中常见的词汇SOTA到底是什么意思,具体的用法是什么???
如题,经常可以在文章中看到这个SOTA的词汇,也就是state of the art,这个词汇我是看着感觉十分的不懂,这个词汇有时候被用作名词有时候又被用作形容词,但是不管用作形容词还是名词大多数人的 ...