通识
- TS为JS超集,如果采用 JS语法书写的TS文件(无TS语法),浏览器可以直接识别,不需要编译
- 编写/编译阶段即可检查错误
- TS静态类型-确定的类型不可变更;JS动态类型-可由赋值更改
- TS类型 强调大小写,小写为 基础类型,大写为 引用类型(对象)
tsc --init会生成初始配置文件tsconfig.json,此文件所在位置为整个 TS项目的根目录- 修改
tsconfig中的rootDir和outDir可以配置项目的 源代码目录和输出目录 - TS中的 any类型声明可以从编写阶段就跳过检查,同时此类型的数据没有提示信息,等效于JS
数据类型:
- boolean
- string
- number
- null,undefined,any,never,void
- 数组
- 元组
- 枚举
- object
交叉类型
交叉类型的实现
- 利用类型别名,接口都可实现
//type定义的交叉类型
type Atype = {
name: string
}
type Btype = {
age: number
}
type Ctype = Atype & Btype;
//interface的继承特性
interface Atype {
name: string;
}
interface Btype {
age: number;
}
interface Ctype extends Atype, Btype {}
- 联合类型组成的交叉类型:指代彼此的交集部分;对象结构类型组成的交叉类型,指代彼此的融合
type Atype = number | string;
type Btype = string | boolean;
type Ctype = Atype & Btype; // string
type Atype = {
name: string
}
type Btype = {
age: number
}
type Ctype = Atype & Btype; // {name:string, age:number}
类型守卫
类型守卫的作用
- 设置 校验类型
- 触发 条件逻辑
使用场景
由于TS是 编译时 语法,联合类型声明的变量 只有在运行时才能确定其 具体类型。因此需要 类型守卫 添加 校验逻辑, 帮助开发运行时不会出错的代码
类型守卫分类
typeof操作符:适用于基础类型
type Atype = number | string;
function add(a:Atype, b:Atype) {
if(typeof a === 'string' || typeof b === 'string') { //type guard
return a.toString() + b.toString()
}
return a + b
}
if...in语法结构:适用于对象类型
type Employee = {
name: string;
works: string[]
}
type Manager = {
name: string;
meetings: string[]
}
type EmployeeOrManager = Employee | Manager;
function printInformation(emp: EmployeeOrManager) {
if('works' in emp) { //js 运行时支持的类型守卫
console.log(emp.works)
}
}
instanceof操作符:适用于类
class Car {
drive() {
console.log('Driving...')
}
}
class Truck {
drive() {
console.log('Driving a truck...')
}
loadCargo(amount: number) {
console.log('Loading cargo ...' + amount)
}
}
type Vehicle = Car | Truck;
const v1 = new Car();
const v2 = new Truck();
function useVehicle(vehicle: Vehicle) {
vehicle.drive();
if(vehicle instanceof Truck) { //instanceof
vehicle.loadCargo(1000)
}
}
===,!==, ==, !=
- 适用于字面量类型的区分,null或undefined类型排除
可辨识联合类型
- 可辨识联合类型:不同类或接口中相同属性名,不同属性值的公共标识
- 作用:对于复杂的类型,如不同的类或接口之间进行 类型辨别,普通的类型守卫方式难以做到,采用 可辨识联合类型 可以轻松指示区分
interface Bird {
type: "bird";
flyingSpeed: number;
}
interface Horse {
type: "horse";
runningSpeed: number;
}
type Animal = Bird | Horse;
function moveAnimal(animal: Animal) {
switch (animal.type) {
case "bird":
console.log("Moving with speed: " + animal.flyingSpeed);
break;
case "horse":
console.log("Moving with speed: " + animal.runningSpeed);
}
}
类型断言
尖括号语法
const inputEle = <HTMLInputElement>document.getElementById('user-output')!;
as语法
const inputEle = document.getElementById('user-output')! as HTMLInputElement;
inputEle.value = 'Hi there';
可索引属性
- 允许结构扩展,但同时受到类型条件限制
- 可索引属性部分无类型提示
- 会对固定属性的类型有所限制
interface IndexFace {
[pros: string]: string;
name: string; //ok
id: number; //error
}
可选链
- 对象类型,存在某个属性为可选属性时,无法确保一定存在某属性的逻辑简写方式
console.log(fetchUserData.job?.title)
TS中函数指向问题:
- tsconfig.json配置项中将
noImplicitThis设置为true会开启隐式this提示,同时类型检查机制会导致对象方法中的this可能因指向不明确(如隐式any)报错 - 函数声明方式:this指向调用者,调用以后才确认,开启如上提示会报错
- 箭头函数能保存函数创建时this指向,而不是调用后,因此需要变化指向需要手动给函数this赋类型
interface Deck { suits: string[], cards: number[], createCardPicker: (this:Deck) => {} //this被手动指向了Deck对象类型 }
函数重载
作用场景
- 函数 返回值 是 联合类型时, 因为 TS类型推断 和 逻辑是不相关的,无法通过逻辑区分返回的具体类型。会导致在实际使用时无法正确使用对应类型的方法
type Atype = number | string; function add(a: Atype, b: Atype) { if (typeof a === "string" || typeof b === "string") { return a.toString() + b.toString(); } return a + b; } //TS会无视逻辑,仍然推断result为 number | string const result = add('a','b'); result.split(''). //error - 在上述场景下,函数重载 的作用 就是把 各种联合类型 的 传入和传出 情况区分声明,TS能依照对应声明关联输入输出的类型
- ⚠️函数的逻辑实现要在所有重载声明之后,才能融合所有类型 进行完整的 类型守卫
function add(a: string, b: Atype): string; function add(a: Atype, b: string): string; function add(a: number, b: number): number; function add(a: Atype, b: Atype) { if (typeof a === "string" || typeof b === "string") { return a.toString() + b.toString(); } return a + b; } const result = add("a", 1); //string
函数重载相关问题
- 重载只是让函数传参为多类型时,编写过程更清晰
- 区别于联合类型的传参方式,重载可以对函数输入输出的类型都有明确限制,如果函数需要针对不同类型参数有不同的处理和返回值,联合类型在写编写过程无法正确提示输出的具体类型
- 需要注意ts只是开发手段,重载类型被编译为js以后仍然是支持传入任意类型,因此也会存在输入输出为
undefined类型的值 -
匿名函数、箭头函数无法重载