> 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 = [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((x).length){ return (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-->数值类型 ``` 类型断言的特性: - 联合类型可以被断言为其中一个类型 - 父类可以被断言为子类 - 任何类型都可以被断言为any - any可以被断言为任何类型