为什么要用 ts,ts 的好处?
TypeScript
是JavaScript
的加强版,它给JavaScript
添加了可选的静态类型和基于类的面向对象编程,它拓展了JavaScript
的语法。所以ts
的功能比js
只多不少.Typescript
是纯面向对象的编程语言,包含类和接口的概念.TS
在开发时就能给出编译错误, 而JS
错误则需要在运行时才能暴露。- 作为强类型语言,你可以明确知道数据的类型。代码可读性极强,几乎每个人都能理解。
ts
中有很多很方便的特性, 比如可选链.
基础
- 类型: boolean、number、bigint、string、Array、Tuple、enum、unknown、any、void、null、undefined、never、object
基础类型的具体定义可以看这里->基础类型
类型断言
类型断言有两种语法,一种是尖括号
,一种是as
:
1 |
|
这两种方式是等价的,但是在JSX
中只有as
是被允许的。
泛型
泛型是指在定义函数、接⼝或类的时候,不预先指定具体的类型,使⽤时再去指定类型的⼀种特性。
可以把泛型理解为代表类型的参数,假如我们现在有这么一个函数,函数接收的参数是什么类型,就返回什么类型。单一的基础类型也满足不了要求啊,怎么办呢?要不用 any?
1 |
|
看着好像没问题,但是用any
要是函数中间经过了什么处理,改变了arg
传入的类型怎么办?这个时候我们就可以用到泛型
。
1 |
|
type 和 interface 的异同
一般情况下,我们用interface
描述数据结构,用type
描述数据类型
都可以描述一个对象或者函数
1 |
|
都允许扩展(extends)
interface
和type
都可以扩展,并且interface
可以 extendstype
,type
可以 extendsinterface
,只不过语法略有区别。
1 |
|
只有 type 可以做的
type
可以声明基础类型、联合类型、元组类型
1 |
|
进阶
联合类型 |
联合类型表示一个值可以是几种类型之一,可以看上面的Pet
例子
交叉类型 &
交叉类型是将多个类型合并为一个类型。
typeof
typeof
操作符可以用来获取一个变量声明或对象的类型。
1 |
|
keyof
keyof
操作符可以用来一个对象中的所有 key 值。
1 |
|
in
in 用来遍历枚举类型:
1 |
|
extends
有时候我们定义的泛型不想过于灵活或者说想继承某些类等,可以通过 extends
关键字添加泛型约束。
1 |
|
Partial
Partial<T>
的作用就是将某个类型里的属性全部变为可选项 ?
。
Required
Required<T>
的作用就是将某个类型里的属性全部变为必选项。
Readonly
Readonly<T>
的作用是将某个类型所有属性变为只读属性,也就意味着这些属性不能被重新赋值。
Record
Record<K extends keyof any, T>
的作用是将 K
中所有的属性的值转化为 T
类型。
1 |
|
Exclude
Exclude<T, U>
的作用是将某个类型中属于另一个的类型移除掉。
1 |
|
Extract
Extract<T, U>
的作用是从 T
中提取出 U
(交集)。
1 |
|
如何基于一个已有类型, 扩展出一个大部分内容相似, 但是有部分区别的类型?
1 |
|
原理
-
Scanner 扫描器 (scanner.ts)
扫描器的作用就是将源代码生成 token 流
-
Parser 解析器 (parser.ts)
-
Binder 绑定器 (binder.ts)
符号将 AST 中的声明节点与其它声明连接到相同的实体上。符号是语义系统的基本构造块。
1 |
|
SymbolFlags 符号标志是个标志枚举,用于识别额外的符号类别(例如:变量作用域标志 FunctionScopedVariable 或 BlockScopedVariable 等)。
- Checker 检查器 (checker.ts)
根据我们生成 AST 节点的声明起始节点位置,对传进来的字符串做位置类型语法等的校验与异常的抛出。
- Emitter 发射器 (emitter.ts)
TypeScript 编译器提供了两个发射器:
emitter.ts: 它是 TS -> JavaScript 的发射器 declarationEmitter.ts: 用于为 TypeScript 源文件(.ts) 创建声明文件
附 tsconfig
1 |
|