meface/docs/article/web/js/ts.md

349 lines
8.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

> ts最大的意义就是避免你错写漏写能基本上屏蔽掉你的第几错误。
>
> 应用场景:
>
> 1. 编写一些公用方法和全局配置对象,用于提醒使用者别传错参数。如:`API`请求参数对象`param`的类型声明,规范参数和响应结果`result`的类型限制。
> 2. 编写组件的时候用于提示使用者有没有写错`props`。
## 初识TypeScript
> Typed JavaScript at Any Scale添加了类型系统的JavaScript适用于任何规模的项目。
ts 是 js的超级包含js的所有元素能运行js代码支持ES语法是一种开元、跨平台的编程语言。
编译器编译为js代码完全兼容js代码主要提供了**类型系统**和**对 ES6 的支持**,相当于静态类型检查器。
TypeScript是**静态类型**
类型系统按照【类型检查的时机】来分类:
- 动态类型是指在运行时才会进行类型检查
- **静态类型是指编译阶段就能确定每个变量的类型**
> 类型检查,当检查到调用的是不属于该对象的方法时就会报错,如:1.split()
类型推论,当变量没有声明类型时,也能在变量初始化时自动推论出它的类型。
TypeScript是弱类型
类型系统按照【是否允许隐式类型转换】来区分,可以分为强类型和弱类型。
```javascript
// 运行时数字1会被隐式类型转换为字符串1加号被是别为字符串拼接
console.log(1+'1');
```
TypeScript 是完全兼容 JavaScript 的,它不会修改 JavaScript 运行时的特性,所以**它们都是弱类型**。
## 安装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`
## 基础
**类型声明** : 在定义变量时,用`:` 加类型的形式。**变量只能存储指定类型的值。**
```javascript
let num:number = 11;
```
----
### 原始数据类型
原始数据类型number、string、boolean、null、undefined、Symbol(ES6)、BigInt(ES10)
> undefined/null可以作为其他类型的子类型赋值给其他类型可以理解成面向对象的多态向上转型
>
> let num:number = null; ==> let 变量名:父类 = 子类型的值
### 任意值
任意值any当变量定义的时候只有声明没有赋值的情况。
```javascript
let abc; ==> let abc:any;
```
### 空类型
空类型void表示没有任何返回值的函数。
```javascript
function fun1():void{
console.log(123);
}
```
### 类型推论
类型推论Type Inference没有明确的指定类型有赋值。
```javascript
// 定义变量时,直接赋值,则定义类型为对应的类型,会根据赋值的类型推断变量的类型
let ac = 123;
// ac = 'w';//报错
```
### 联合类型
联合类型Union Types标识取值可以为多种类型中的一种。使用`|`分隔每种类型。
```javascript
let f:boolean|number|string = true;
f=123;//再次赋值,走类型推断,给变量定义一个类型,就可以只用对应类型的属性和方法。
```
> **访问联合类型的属性或方法只能访问共有的属性和方法。**
### 对象的类型
对象的类型-接口接口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'
};
```
### 数组类型
数组类型:多种定义方式
```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是指在定义函数、接口或类的时候不预先指定具体的类型而在使用的时候再指定类型的一种特性。
### 函数类型
- 函数声明
```javascript
// ts,函数声明,命名函数
function add(a:number,bnumber):number{
return a+b;
}
```
- 函数表达式
```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'));
```
可选参数|默认参数|剩余参数
```javascript
// 可选参数
// 使用?放到参数前面,但可选参数的位置不能位于必选参数前
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)
```
函数重载
可以理解成:函数名相同,形参不同的多个函数
---
### 类型断言
类型断言,可以手动指定一种类型。
应用场景:
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
// 将任何一个类型断言为anyany类型是访问任何属性和方法的
(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-->数值类型
```
类型断言的特性:
- 联合类型可以被断言为其中一个类型
- 父类可以被断言为子类
- 任何类型都可以被断言为any
- any可以被断言为任何类型