2024-01-16 11:21:05 +08:00
|
|
|
|
> ts最大的意义就是避免你错写,漏写,能基本上屏蔽掉你的第几错误。
|
|
|
|
|
>
|
|
|
|
|
> 应用场景:
|
|
|
|
|
>
|
|
|
|
|
> 1. 编写一些公用方法和全局配置对象,用于提醒使用者别传错参数。如:`API`请求参数对象`param`的类型声明,规范参数和响应结果`result`的类型限制。
|
|
|
|
|
> 2. 编写组件的时候用于提示使用者有没有写错`props`。
|
|
|
|
|
|
2023-11-17 10:54:23 +08:00
|
|
|
|
## 初识TypeScript
|
|
|
|
|
|
|
|
|
|
> Typed JavaScript at Any Scale,添加了类型系统的JavaScript,适用于任何规模的项目。
|
|
|
|
|
|
|
|
|
|
ts 是 js的超级,包含js的所有元素,能运行js代码,支持ES语法,是一种开元、跨平台的编程语言。
|
|
|
|
|
|
|
|
|
|
编译器编译为js代码,完全兼容js代码,主要提供了**类型系统**和**对 ES6 的支持**,相当于静态类型检查器。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TypeScript是**静态类型**
|
|
|
|
|
|
|
|
|
|
类型系统按照【类型检查的时机】来分类:
|
|
|
|
|
|
|
|
|
|
- 动态类型是指在运行时才会进行类型检查
|
2024-01-16 11:21:05 +08:00
|
|
|
|
- **静态类型是指编译阶段就能确定每个变量的类型**
|
2023-11-17 10:54:23 +08:00
|
|
|
|
|
|
|
|
|
> 类型检查,当检查到调用的是不属于该对象的方法时就会报错,如:1.split()
|
|
|
|
|
|
|
|
|
|
类型推论,当变量没有声明类型时,也能在变量初始化时自动推论出它的类型。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TypeScript是弱类型
|
|
|
|
|
|
|
|
|
|
类型系统按照【是否允许隐式类型转换】来区分,可以分为强类型和弱类型。
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
// 运行时数字1会被隐式类型转换为字符串’1‘,加号被是别为字符串拼接
|
|
|
|
|
console.log(1+'1');
|
|
|
|
|
```
|
|
|
|
|
|
2024-01-16 11:21:05 +08:00
|
|
|
|
TypeScript 是完全兼容 JavaScript 的,它不会修改 JavaScript 运行时的特性,所以**它们都是弱类型**。
|
2023-11-17 10:54:23 +08:00
|
|
|
|
|
|
|
|
|
## 安装TypeScript
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
// 安装
|
|
|
|
|
npm install -g typescript
|
|
|
|
|
// 查看版本
|
|
|
|
|
tsc -v
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
安装完后,可以在任何地方执行`tsc`命令。
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
// 手动编译,xxx.ts文件
|
|
|
|
|
tsc xxx.ts
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
VS Code自动编译
|
|
|
|
|
|
|
|
|
|
1. `tsc --init`生成`tsconfig.json`配置文件;
|
|
|
|
|
2. 修改配置文件:`target`、`outDir`、`strict`
|
|
|
|
|
3. 启动监视任务:终端=》允许任务=》监视`tsconfig.json`
|
|
|
|
|
|
|
|
|
|
## 基础
|
|
|
|
|
|
2024-01-16 11:21:05 +08:00
|
|
|
|
**类型声明** : 在定义变量时,用`:` 加类型的形式。**变量只能存储指定类型的值。**
|
2023-11-17 10:54:23 +08:00
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
let num:number = 11;
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
----
|
|
|
|
|
|
2024-01-16 11:21:05 +08:00
|
|
|
|
### 原始数据类型
|
|
|
|
|
|
2023-11-17 10:54:23 +08:00
|
|
|
|
原始数据类型:number、string、boolean、null、undefined、Symbol(ES6)、BigInt(ES10)
|
|
|
|
|
|
|
|
|
|
> undefined/null可以作为其他类型的子类型赋值给其他类型,可以理解成面向对象的多态,向上转型:
|
|
|
|
|
>
|
|
|
|
|
> let num:number = null; ==> let 变量名:父类 = 子类型的值
|
|
|
|
|
|
2024-01-16 11:21:05 +08:00
|
|
|
|
### 任意值
|
|
|
|
|
|
2023-11-17 10:54:23 +08:00
|
|
|
|
任意值:any,当变量定义的时候只有声明没有赋值的情况。
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
let abc; ==> let abc:any;
|
|
|
|
|
```
|
|
|
|
|
|
2024-01-16 11:21:05 +08:00
|
|
|
|
### 空类型
|
2023-11-17 10:54:23 +08:00
|
|
|
|
|
|
|
|
|
空类型:void,表示没有任何返回值的函数。
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
function fun1():void{
|
|
|
|
|
console.log(123);
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2024-01-16 11:21:05 +08:00
|
|
|
|
### 类型推论
|
2023-11-17 10:54:23 +08:00
|
|
|
|
|
|
|
|
|
类型推论(Type Inference):没有明确的指定类型,有赋值。
|
|
|
|
|
|
|
|
|
|
```javascript
|
2024-01-16 11:21:05 +08:00
|
|
|
|
// 定义变量时,直接赋值,则定义类型为对应的类型,会根据赋值的类型推断变量的类型
|
2023-11-17 10:54:23 +08:00
|
|
|
|
let ac = 123;
|
|
|
|
|
// ac = 'w';//报错
|
|
|
|
|
```
|
|
|
|
|
|
2024-01-16 11:21:05 +08:00
|
|
|
|
### 联合类型
|
2023-11-17 10:54:23 +08:00
|
|
|
|
|
|
|
|
|
联合类型(Union Types):标识取值可以为多种类型中的一种。使用`|`分隔每种类型。
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
let f:boolean|number|string = true;
|
|
|
|
|
f=123;//再次赋值,走类型推断,给变量定义一个类型,就可以只用对应类型的属性和方法。
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
> **访问联合类型的属性或方法只能访问共有的属性和方法。**
|
|
|
|
|
|
2024-01-16 11:21:05 +08:00
|
|
|
|
### 对象的类型
|
2023-11-17 10:54:23 +08:00
|
|
|
|
|
|
|
|
|
对象的类型-接口:接口(interfaces)定义了对象的`形状`,是对象行为的抽象,具体的行为有类(classes)去实现(implement)。可以理解成一中约束。
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
// -----------对象类型-------------
|
|
|
|
|
// object 表示非原始类型,除了number、string、boolean之外的类型
|
|
|
|
|
let obj:object={};
|
|
|
|
|
// obj = 123;//报错
|
|
|
|
|
// obj = '';//报错
|
|
|
|
|
obj = null;
|
|
|
|
|
obj = undefined;
|
|
|
|
|
obj = [];
|
|
|
|
|
obj = new String();//不通过字面量的方式,采用new的方式定义。
|
|
|
|
|
obj = String
|
|
|
|
|
|
|
|
|
|
// -------------接口--------------
|
|
|
|
|
interface Person{
|
|
|
|
|
name:string,
|
|
|
|
|
age:number
|
|
|
|
|
}
|
|
|
|
|
// 定义对象属性不能多也不能少。赋值的时候,变量的形状必须和接口的形状保持一致。
|
|
|
|
|
let tom:Person ={
|
|
|
|
|
name:'',
|
|
|
|
|
age:22
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 可选属性,使用?。定义的对象可以不添加age
|
|
|
|
|
interface Person{
|
|
|
|
|
name:string;
|
|
|
|
|
age?:number;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 只读属性,使用readonly定义,只能在创建的时候被赋值
|
|
|
|
|
interface Person {
|
|
|
|
|
readonly id: number;
|
|
|
|
|
name: string;
|
|
|
|
|
age?: number;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 任意属性,使用 [propName: string] 定义了任意属性取 string 类型的值。
|
|
|
|
|
interface Person{
|
|
|
|
|
name:string;
|
|
|
|
|
age:number;
|
|
|
|
|
属性名([propName: string]): any;
|
|
|
|
|
}
|
|
|
|
|
// 一旦定义了任意属性,那么确定属性和可选属性的类型都必须是它的类型的子集
|
|
|
|
|
// 即:propName定义为string,那对象中的其他属性类型都必须是它的类型的子集(string/null/undefined)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
一个接口中只能定义**【一个】**任意属性。如果接口中有多个类型的属性,则可以在任意属性中使用联合类型:
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
interface Person {
|
|
|
|
|
name: string;
|
|
|
|
|
age?: number;
|
|
|
|
|
[propName: string]: string | number;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let tom: Person = {
|
|
|
|
|
name: 'Tom',
|
|
|
|
|
age: 25,
|
|
|
|
|
gender: 'male'
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
2024-01-16 11:21:05 +08:00
|
|
|
|
### 数组类型
|
2023-11-17 10:54:23 +08:00
|
|
|
|
|
|
|
|
|
数组类型:多种定义方式
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
//使用「类型 + 方括号」来表示数组,项中不允许出现其他的类型
|
|
|
|
|
let arr1:[]=[];
|
|
|
|
|
let arr2:number[]=[212,212,3];
|
|
|
|
|
let newArr:any[]=[1,2,3,'',true];//谨慎使用any
|
|
|
|
|
let fibonacci: number[] = [1, 1, 2, 3, 5];
|
|
|
|
|
|
|
|
|
|
//数组泛型(Array Generic):使用 Array<类型> 的方式。
|
|
|
|
|
let fibonacci: Array<number> = [1, 1, 2, 3, 5];
|
|
|
|
|
|
|
|
|
|
// 用接口表示数组(不常用),[1,2,3,4] arr[0]==>obj['name']
|
|
|
|
|
interface NumberArray {
|
|
|
|
|
[index: number]: number;//任意属性,index表示数组中的下标
|
|
|
|
|
}
|
|
|
|
|
let fibonacci: NumberArray = [1, 1, 2, 3, 5];
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
> 泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2024-01-16 11:21:05 +08:00
|
|
|
|
### 函数类型
|
2023-11-17 10:54:23 +08:00
|
|
|
|
|
2024-01-16 11:21:05 +08:00
|
|
|
|
- 函数声明
|
2023-11-17 10:54:23 +08:00
|
|
|
|
|
2024-01-16 11:21:05 +08:00
|
|
|
|
```javascript
|
|
|
|
|
// ts,函数声明,命名函数
|
|
|
|
|
function add(a:number,bnumber):number{
|
|
|
|
|
return a+b;
|
|
|
|
|
}
|
|
|
|
|
```
|
2023-11-17 10:54:23 +08:00
|
|
|
|
|
2024-01-16 11:21:05 +08:00
|
|
|
|
- 函数表达式
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
// ts,函数表达式,匿名函数
|
|
|
|
|
let sum = function(a:string,bstring):boolean{
|
|
|
|
|
return a.search(b) !== -1;
|
|
|
|
|
}
|
|
|
|
|
// ts,完整写法
|
|
|
|
|
// 在 TypeScript 的类型定义中,=> 用来表示函数的定义,左边是输入类型,需要用括号括起来,右边是输出类型。
|
|
|
|
|
let add:(a:number,b:number)=>number = function(a:number,b:number):number{
|
|
|
|
|
return a.search(b) !== -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
- 接口定义函数的形状
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
interface ISearchFunc{
|
|
|
|
|
// (参数:类型,...):返回值类型
|
|
|
|
|
(a;string,b:string):boolean;
|
|
|
|
|
}
|
|
|
|
|
const fun1:ISearchFunc = function(a:string,bstring):boolean{
|
|
|
|
|
return a.search(b) !== -1;
|
|
|
|
|
}
|
|
|
|
|
console.log(fun1('123','1'));
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
2023-11-17 10:54:23 +08:00
|
|
|
|
|
2024-01-16 11:21:05 +08:00
|
|
|
|
可选参数|默认参数|剩余参数
|
|
|
|
|
|
|
|
|
|
```javascript
|
2023-11-17 10:54:23 +08:00
|
|
|
|
|
|
|
|
|
// 可选参数
|
|
|
|
|
// 使用?放到参数前面,但可选参数的位置不能位于必选参数前
|
|
|
|
|
let getName = function(x:string,y?:string):string{
|
|
|
|
|
return x+y;
|
|
|
|
|
}
|
|
|
|
|
console.log(getName('hello '));
|
|
|
|
|
|
|
|
|
|
// 默认参数
|
|
|
|
|
// 直接在参数类型后面赋值
|
|
|
|
|
let getName = function(x:string='Hello ',y?:string):string{
|
|
|
|
|
return x+y;
|
|
|
|
|
}
|
|
|
|
|
console.log(getName('hello '));
|
|
|
|
|
|
|
|
|
|
//剩余参数
|
|
|
|
|
// 使用 ...rest 语法接受,下列示例:使用args数组接收
|
|
|
|
|
function fn(x:string,y:string,...agrs:number[]){
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
fn('','',1,2,3,4,5)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
函数重载
|
|
|
|
|
|
|
|
|
|
可以理解成:函数名相同,形参不同的多个函数
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2024-01-16 11:21:05 +08:00
|
|
|
|
### 类型断言
|
2023-11-17 10:54:23 +08:00
|
|
|
|
|
|
|
|
|
类型断言,可以手动指定一种类型。
|
|
|
|
|
|
|
|
|
|
应用场景:
|
|
|
|
|
|
|
|
|
|
1. 使用联合类型时
|
|
|
|
|
2. window上挂载变量时
|
|
|
|
|
3. 将any类型断言为一个具体的类型
|
|
|
|
|
|
|
|
|
|
两种方式:
|
|
|
|
|
|
|
|
|
|
- 变量 as 类型
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
function getLength(x:string|number):number{
|
|
|
|
|
if((x as string).length){
|
|
|
|
|
return (x as string).length;
|
|
|
|
|
}else{
|
|
|
|
|
return x.toString().length
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
- <类型> 变量
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
function getLength(x:string|number):number{
|
|
|
|
|
if((<string>x).length){
|
|
|
|
|
return (<string>x).length;
|
|
|
|
|
}else{
|
|
|
|
|
return x.toString().length
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
在window上添加全局变量
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
// 将任何一个类型断言为any,any类型是访问任何属性和方法的
|
|
|
|
|
(window as any).a = 11;
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
> 它(any)极有可能掩盖了真正的类型错误,所以如果不是非常确定就不要使用 `as any`
|
|
|
|
|
|
|
|
|
|
将any类型断言为一个具体的类型
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
function abc(x:any,y:any):any{
|
|
|
|
|
return x+y;
|
|
|
|
|
}
|
|
|
|
|
let a = abc(1,2) as number;//a-->数值类型
|
|
|
|
|
```
|
|
|
|
|
|
2024-01-16 11:21:05 +08:00
|
|
|
|
类型断言的特性:
|
2023-11-17 10:54:23 +08:00
|
|
|
|
|
2024-01-16 11:21:05 +08:00
|
|
|
|
- 联合类型可以被断言为其中一个类型
|
|
|
|
|
- 父类可以被断言为子类
|
|
|
|
|
- 任何类型都可以被断言为any
|
|
|
|
|
- any可以被断言为任何类型
|
2023-11-17 10:54:23 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|