typescript
官网:https://www.tslang.cn/
1.介绍
TypeScript是js的超集,由微软开发和开源的。
通俗的理解为js的一个特殊版本,其语法规范严谨,适用于开发大型项目。
2.搭建环境
(1)安装
npm i typescript -g
(2)验证是否安装成功
tsc -v
(3)编译
①手动编译
创建一个index.ts,并在其中写一行普通的js代码
在命令行中进入指定的目录,执行tsc index.ts进行编译,在同级目录下会生成一个同名的js文件
②自动编译vscode
生成ts的配置文件
tsc --init
此时就会在指定的目录下生成一个tsconfig.json文件
修改配置文件
“outDir”:’./'注释接口
编写index.ts
vscode->终端->运行生成任务->tsc:监视
这样在index.ts文件,编写了内容,就会自动生成对应的ts文件
在根目录下创建一个index.html并引入生成的好的js文件
3.声明变量和数据类型
ts最大的特点就是进行了严谨的数据类型验证,要求我们在声明一个变量的时候,就定义好该变量的数据类型,且赋值的内容,必须和对应的数据类型保持一致
(1)声明变量
格式:
let 变量名:数据类型 = 内容;
let 变量名:数据类型;
错误用法:
let str:string;
str = 123;//此时会报错,数据类型不致
(2)数据类型
①字符串
let str:string="初始ts";//值必须为字符串
②数值
let num:number = 100;//值必须为数值
③布尔值
let isbol :boolean = true;//值必须为布尔值
④数组
原生
let arr = [];
let arr2 = new Array;
ts方式:ts定义数组,需要定义数组内元素数据类型
let arr3:string[]
arr = ['12']
let arr4:Array<number>= [11,22,33];
新增类型
①元组类型
元组类型是数组类型的子类型,表示一个已知元素数量和类型的数组,各元素类型可以不一样
let 变量名:[数据类型1,数据类型2,...] = [值1,值2,...]
let arr5:[string,number,boolean] = ['hello',1,true]
②any
any类型,表示任意类型,如果不确定我们的变量,就可以使用any类型
let obj:any = {
'name':'刘飞',
age:20
}
let arr6:any = [];
arr6[1] = "111";
③枚举类型
表示值是某些固定值中的一些
比如:性别,男、女;订单状态:已下单,已发货,已收货
格式:
enum 变量名 {
值1,
值2
}
④void
一般应用于函数,表示函数无返回值
⑤never
表示那些永远不存在的数据类型
function error(msg:string):never{
throw new Error(msg)
}
⑥object
object表示非原始类型,也就是除了number,string,boolean,array,null,undefined之外的类型
4.函数
ts中的函数知识和es6中的函数有很多相同之处
(1)函数定义
在ts中,定义一个函数需要定义函数的返回值类型,如果没有返回值则类型为void,如果有参数也要指定参数的数据类型
function 函数名([参数名:参数的数据类型]):函数返回值的数据类型
示例代码
function add(num:number):void{//函数无返回值
console.log(num);
}
//函数的返回值类型是数字
function add(num:number):number{
return num+=10
}
②可选参数
可选参数如果没有传递,在函数中仍然用到了这个参数,则它的值为undefined
function hello(str:string,txt?:string):string{
return str+txt;
}
console.log(hello('你好','ts'))
③剩余参数
替代传统函数中的arguments的作用
剩余参数需要是所有参数中的最后一位,不然就做不到剩余
function family(main:string,...child:string[]):string{
return '户主:'+main+',家庭成员:'+child.join(' ');
}
console.log(family('小王','王一','王二','王三'))
4.类
ts中相关类的知识和ES6中非常相似
class Person{
name:string;
constructor(username:string){
this.name = username;
}
speak(language:string,language2?:string):void{
console.log(`${this.name}会说${language}`)
}
}
(2)类的继承
使用extends关键词
class Chinese extends Person{
constructor(username:string){
super(username)
}
speak(language1:string,language2:string){
console.log(`${this.name}会说${language1},${language2}`)
}
}
let p1 = new Chinese('张飞');
p1.speak('汉语','应语')
(3)类的修饰符
public,共有属性[默认],在当前类里面,子类、类的外部都可以访问
protected,受保护的,当前类里,子类可以访问,在类的外部无法访问
class Teacher{
protected name:string;
constructor(name:string){
this.name=name;
}
teach():string{
return `${this.name}在讲课`
}
}
let t1 = new Teacher('李老师');
console.log(t1.teach());
// console.log(t1.name);//在类的外部无法直接访问一个受保护的属性
class WebTeacher extends Teacher{
constructor(name:string){
super(name)
}
teach():string{
return `${this.name}在讲课---子类`
}
}
let t2 = new WebTeacher('范老师');
console.log(t2.teach());
private,私有,只能在当前类里面访问,不能在子类、类外部访问
class Student{
private name:string;
constructor(name:string){
this.name = name;
}
study():string{
return `${this.name}在学习`//可以在当前类中调用私有属性
}
}
class MidStudent extends Student{
constructor(name:string){
super(name)
}
homework():void{
console.log(this.name+'在写作业');//报错,只能在Student里访问
}
}
(4)类的其他修饰符
①静态属性和方法
静态属性或静态方法,使用static修饰符,调用属性或方法时,不需要实例化类
通过类名.静态属性或者静态方法直接使用
// 静态属性和方法
class Util{
static desc:string = "工具类"
static getTime(time:number):string{
let d = new Date(time);
return d.toLocaleTimeString();
}
}
console.log(Util.desc)
// 调用类中静态方法
console.log(Util.getTime(new Date().getTime()))
②抽象类
抽象类一般作为其派生类的基类使用,它们一般被直接实例化,一般用来定义标准
abstract关键词,抽象类中必须有抽象方法,抽象方法不实现具体功能,它只做约束。非抽象方法必须自己实现功能
在子类中一旦继承了抽象类,抽象类中的抽象方法,就必须在子类中实现具体的功能。
abstract class Car {
abstract drive():any;
abstract stop():any;
run():void{
console.log('汽车在跑')
}
}
class BMW extends Car {
drive():void{
console.log('这辆宝马在路上驾驶')
}
stop():void{
console.log('这辆宝马在路上停止了')
}
}
let c1 = new BMW();
c1.drive();
5.接口
function tt(str:string):void{
console.log(str)
}
tt('1111');
在上述代码中,只能校验一个变量的数据类型
如果传递的参数数量比较多或者是一个对象,那么这个函数的参数就无法实现校验
接口(Interface)是类中的一个很重要的概念,他是对行为的抽象,而具体如何实现需要由类(class)实现(implements)
(1)接口定义
interface Personal{
name:string,
age:number
}
let pp1:Personal;
pp1 = {
name:'小芳',
age:18
}
(2)类的接口
interface Animal{
name:string;
eat(str:string):void;
}
class Horse implements Animal{
name:string;
constructor(str:string){
this.name=str;
}
eat():void{
console.log(this.name+'在吃粮草');
}
}
let hxbm = new Horse('汗血宝马')
6.装饰器
装饰器是一种特殊的类型声明,他可以被附加到类、方法、属性、参数上面,可以改变类的行为。
装饰器就是一个方法或者说是一个特殊的函数,可以被注入到类、方法、属性、参数上。
装饰器分类:类装饰器、方法装饰器、属性装饰器、参数装饰器
装饰器也是ES7里面的标志特性之一。
(1)类装饰器
类装饰器实在声明类之前(紧靠类的声明处),类装饰器应用于类的构造函数,可以用来监视、修改或替换类的定义
①普通装饰器
定义装饰器
//1.普通装饰器(无法传参数)
function logClass(params:any){
params.prototype.url="请求的连接地址";
params.prototype.run=function(){
console.log('run')
}
}
使用装饰器
@logClass
class HttpClient {
name:string;
constructor(n:string) {
this.name=n;
}
}
let http:any = new HttpClient('test');
console.log(http.url);
http.run()
②装饰器工厂(可以传递参数)
定义装饰器
function logClass(params:string){
return function(target:any){
console.log(target,111)
console.log(params,222)
target.prototype.url = "接口地址是"+params;
}
}
使用装饰器
@logClass('www.ujiuye.com')
class HttpClient {
name:string;
constructor(n:string) {
this.name=n;
}
}
let http:any = new HttpClient('test');
console.log(http.url);
(2)属性装饰器
定义属性装饰器
function logProperty(params: any) {
return function (target: any, attr: any) {
console.log(target, 3)//类对象
console.log(attr, 4)//属性装饰器修饰的属性名
console.log(params, 5)//调用属性装饰器时传递的参数
target[attr] = params
}
}
使用属性装饰器
class HttpClient {
@logProperty('张辽')//调用属性装饰器并传递参数
name: string | undefined;
}
let http: any = new HttpClient();
(3)方法装饰器
可以被运用到方法的属性描述上,可以用来监视、修改、替换方法定义
运行时,需要传递三个参数
(1)对应静态类成员来说就是类的构造函数,对于实力成员来说就是类的原型对象
(2)成员(属性)的名字
(3)成员的属性描述
定义方法装饰器
function logMethod(params:any){
return function(target:any,methodName:any,desc:any){
console.log(target,6)//类的原型
console.log(methodName,7)//方法名称
console.log(desc.value,8)//方法的描述
target.run = function(){
console.log('run')
}
}
}
使用方法装饰器
@logClass('www.ujiuye.com')
class HttpClient {
@logProperty('张辽')
name: string | undefined;
url:string | undefined;
constructor() {}
@logMethod('111')
getData(){
console.log(this.url);
}
}
let http: any = new HttpClient();
http.run()
(4)参数装饰器
运行时,会被当做函数调用,可以使用参数装饰器为类的原型增加一些元素数据,需要传递三个参数
(1)对应静态类成员来说就是类的构造函数,对于实力成员来说就是类的原型对象
(2)方法名称
(3)参数在函数列表中的索引
定义参数装饰器
function logParams(params:any){
return function(target:any,methodName:any,paramsId:any){
console.log(target,9)//类的原型
console.log(methodName,10)//方法名称
console.log(paramsId,11)//参数的索引位置
}
}
使用参数装饰器
class HttpClient {
@logProperty('张辽')
name: string | undefined;
url:string | undefined;
constructor() {}
@logMethod('111')
getData(@logParams('1111') str:any){
console.log(this.url);
}
}