ts学习记录

    技术2025-04-23  14

    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); } }
    Processed: 0.009, SQL: 9