TypeScript 快速入门
TS 是强类型语言,只涉及类型,不涉及值,所有和值相关的处理,都是由 JS 完成。通过编译,会将 TS 转为 JS 代码。
- 类型相关计算由 TS 负责
- 值相关的计算由 JS 负责
类型系统
基础类型
- 原始类型,它的值是最基本的,不可再分的。
- boolean
- string
- number
- bigint
- symbol, 通过
Symbol()
函数来生成,它的每个值都是独一无二的。
- object,包括对象,数组,函数。
- undefined,表示未定义,只有一个值
undefined
- null,表示空,只有一个值
null
特殊类型:
- any,类型不确定,可能是任意类型,可以赋予任意类型的值,并可以赋值给其他任何类型,导致类型污染,不安全,不推荐使用
- unknown,严格版 any,一般只有经过 type narrowing 之后才能使用
- never,表示不包含任何值,一般用于表达式运算的完整性。
1 | function fn(x: string | number) { |
在关闭编译设置 noImplicitAny
和 strictNullChecks
时,被赋值为 undefined
或 null
的变量,会被类型推断为 any
; 若开启,则是 undefined
或 null
类型。
字面量
指直接使用的固定值,而 字面量类型(Literal Types)则是对这些固定值的类型约束,用于限制变量或属性只能取特定的字面量值。
- 字符串字面量
- 数字字面量
- 布尔字面量
- 对象字面量
1 | // 字符串字面量 |
Function
函数参数:
- 可选参数用
<variable>?: <type>
来表示,它的类型为<type | undefined>
, 可选参数只能放在末尾处。 - 默认值
- rest 剩余参数,
...<variable>: <array/tuple>
对同一个函数参数,可选参数和默认值不能同时使用。
高阶函数 higher-order function
返回值是一个函数,用于对某个功能进行扩展和包装
构造函数
需要通过 new
命令来调用。
1 | class Animal {} |
Object
在 JS 中只有对象才有方法,而原始类型的值本身没有方法,需要通过对应的包装对象才能调用方法。而每一个原始类型都有对应的包装类,会在需要的时候自动转为包装对象。包装对象的类型为 object
. 一般情况下建议使用原始类型。
Object vs object:
- object 类型的值只包括对象,数组,函数。
- 只要能转成 object 类型的值,都是 Object 类型,包括原始类型的值和 object 的值,除了 undefined 和 null。常用空对象
{}
来表示 Object 类型。
对象解构,直接从对象中提取属性, 在对象解构里使用冒号 :
来对变量进行别名。
1 | type ObjType = { |
索引类型
用于不确定属性的多少的场景,可以用于以下的场景
- 属性名的索引类型
- 数组的索引类型
- symbol的索引类型
1 | // 属性名的索引类型 |
在 JS 中,如果存在字符串索引,要求其他索引类型不能与其冲突,并且单个属性的声明也必须符合索引类型的定义,否则会报错。所以建议谨慎使用索引类型。
1 | type MyObj = { |
结构类型原则 structural typing
只要对象 B 满足对象 A 的结构特征,TS 则认为对象 B 兼容对象 A 的类型,可以将 B 赋值给 A。
TS 检查某个值是否符合指定类型时,并不是检查这个值的类型(名义类型),而是检查这个值的结构是否符合要求,即结构类型是否符合。
如果对象直接使用字面量来表示,则会触发 TS 的**严格字面量检查(strict object literal checking)**。如果字面量的结构和类型定义不完全一样,则会报错。
1 | // 直接使用对象字面量 |
最小可选属性规则:如果某个类型的所有属性都是可选的,那么该类型的对象必须至少存在一个可选属性,不能都不存在。
1 | type Options { |
可以通过扩展操作符 ...
展开对象,用于合成新的对象。
1 | const p1 = {x:3} |
interface && type
数组类型
- array 数组,使用
<type>[]
表示 - tuple 元组,使用
[type1, type2, ...]
表示, 用于表示成员类型不同的数组,必须明确给出类型声明,否则类型推断为联合类型的数组。可选参数(用?
表示)只能用于尾部的成员,即只能放最后。
若数组没有声明类型并且初始值为空数组 []
时,则 TS 会在每次赋值时,自动更新类型推断,否则不会自动更新类型推断。
使用扩展运算符 ...
来表示不限成员数量的元组。
1 | type NamedNumsType = [string, ...number[]] |
只读数组 readonly <type>[]
,对数组成员的新增,修改,删除都会报错
特殊类型
- 值类型,单个值也可以作为一种类型,表示这个类型只有一个值,就是它本身。常见的情况是使用 const 声明变量时没有指定类型,则该变量的类型就是赋给它值的值类型。
- 联合类型,使用
|
分割的多个类型组成的新类型,它的值只需要属于其中任一一个类型即可。当需要它的值进行使用时,需要进行type narrowing
。 - 交叉类型,使用
&
分割的多个类型组成的新类型,它的值要符合所有类型才可以,若多个类型之间存在冲突,则类型为never
, 因为不存在这样类型的值。交叉类型主要用于对象的合成。
类型声明
类型声明的格式: <let/const> <variable/function>:<type> = <value>
1 | // 常量 |
在不声明类型时,TS 会根据值进行类型推断, 如果无法推断出来,则类型为 any
。
1 | // foo: string |
type,用来对类型进行别名,使类型的名字更有意义,增加代码可读性
typeof 的参数必须是编译时决定的值,有两种使用场景:
- 值运算,结果当作值来使用,在 JS 中使用 typeof 获取值的类型,只能返回 8 种基础类型的字符串。
- 类型运算,结果作为类型来使用,是 TS 扩展的功能,返回 TS 中的类型。
类型缩小 Type Narrowing
运算
常用的运算技巧
Falsy value
falsy values 指在 boolean
上下文中会被自动转换为 false 的值。
false
0
- 空字符串,
""
或者''
null
undefined
NaN
boolean
上下文:
- 条件判断
- 逻辑或
||
, 用于提供默认值 - 逻辑与
&&
, 用于条件执行 - 空值合并运算符
??
, 只用于判断非null/undefined
1 | // 空值合并运算符 `??` |
双重否定 !!
双重否定常用来将变量强制转换为 Boolean 来判断真假 !!<variable>
,
1 | const a = 0 // falsy value |