TypeScript笔记

这篇笔记详细介绍了TypeScript中的关键特性,包括继承、多态、抽象类和接口的使用。通过示例展示了如何创建和使用这些特性,如定义类的继承关系、实现多态行为、创建抽象类和接口以及它们的应用场景。此外,还涵盖了泛型的概念,解释了泛型在函数、类和接口中的应用,以及泛型在提高代码复用性和灵活性方面的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

TypeScript笔记

1.继承

 Person{
  name:string;
  constructor(name:string){
    this.name = name
  }
  run ():string{
    return '${this.name}在运动'
  }
}
class Daliy extends Person{
  time:string;
  constructor(name:string,time:string){
    super(name)
    this.time = time
  }
  info ():string{
    return <code>${this.time}${this.name }还在工作</code>// <code></code>,模板字符串&quot; ` &quot;是tab键上面那个按钮,不是单引号!!!
  }
  static print(){
    alert(&#39;这是静态方法&#39;)
  }
}
var w = new Daliy(&#39;浩浩&#39;,new Date().toLocaleTimeString())
alert(w.info())

2.多态

父类定义一个方法不去实现,让继承他的子类去实现,且子类有不同的表现

class Animal{
    name:string;
    constructor(name:string){
        this.name = name
    }
    eat(){ //具体吃什么不知道,由继承他的子类来实现,每一个子类表现不同
        console.log('我是吃的方法')
    }
}
class Cat extends Animal{
    constructor(name:string){
        super(name)
    }
    eat(){
        return `${this.name}吃鱼`
    }
}
class Dog extends Animal{
    constructor(name:string){
        super(name)
    }
    eat(){
        return `${this.name}吃肉`
    }
}
var c = new Cat('猫')
alert(c.eat())

3.抽象类

(1)它是提供其他类继承的基类,不能直接被实例化

(2)用abstract关键字定义抽象类和抽象方法

(3)抽象类中的抽象方法不包含具体实现并且必须在派生类中实现。

(4)abstract抽象方法只能放在抽象类里面

//抽象类和抽象方法用来定义标准,标准:Animal 这个类要求它的子类必须包含eat方法

abstract class Pet{
    name:string
    constructor(name:string){
        this.name = name
    }
    abstract eat():any;//不包含具体实现,abstract eat():any代表有返回值,abstract eat():void代表没有返回值
}
// var pet = new Pet('狗')  错误写法,抽象类不能直接实例
class Dog extends Pet{
    constructor(name:string){
        super(name)
    }
    eat(){
        return `${this.name}吃肉`
    }
}
var dog = new Dog('狗')
console.log('抽象类:'+dog.eat())

4.接口

(1)接口的作用:在面向对象的编程中,接口是一种规范的定义,它定义了行为和动作的规范,在程序设计里面,接口起到一种限制和规范的作用。

(2)接口定义了某一批类所需要遵守的规范,接口不关心这些类的内部状态数据,也不关心这些类里方法的实现细节,它只规定这批类里必须提供某些方法,提供这些方法的类就可以满足实际需要。

(3)typescrip中的接口类似于java, 同时还增加了更灵活的接口类型,包括属性、函数、可索引和类等。

4.1属性接口(对传入对象的约束)

interface AllName{
    firstName:string;
    lastName:string
}
function pName(name:AllName){
//必须传入对象{ firstName,lastName}
    console.log('接口:' + name.firstName +'-------------'+ name.lastName)
}
let obj = { //必须包含接口中定义的属性
    age:20,
    firstName:'张',
    lastName:'三'
}
pName(obj)

4.2ts封装一个ajax请求

interface ajaxConfig{
    dataType:string;
    data?:string;//代表data是可选的
    type:string;
    url:string
}
function ajax(config:ajaxConfig){
    var xhr =new  XMLHttpRequest();
    xhr.open(config.type,config.url,true)//true代表异步,表示在send()之后执行,而不用等待服务器响应
    xhr.withCredentials = true;
    xhr.send(config.data)
    xhr.onreadystatechange = function(){
        if(xhr.readyState == 4 && xhr.status == 200){
            if(config.dataType === 'jsonp'){
                console.log('ts封装ajax:   ' + JSON.parse(xhr.responseText))
                console.log(JSON.parse(xhr.responseText))
                // let aaa =document.getElementById('text')?.innerHTML
                // if(aaa){
                //     aaa= JSON.parse(xhr.responseText).showapi_res_body.data
                // }
            }else{
                console.log(xhr.responseText)
            }
        }
    }
}
let obj2 ={
    url:'接口的url
    ,type:'get'
    ,dataType:'jsonp'
    ,data:'success'

}
ajax(obj2)

4.3.函数类型接口(对方法传入的参数以及返回值进行约束)

interface encrypt{
    (key:string,value:string):string
}
var md5:encrypt = function(key:string,value:string):string{
    key = 'key是:' + key,
    value = 'vlue是:' + value
    return `${key},${value}`
}
console.log('函数类型接口:' + md5('键','值'))

4.4类类型接口,通过implements关键字来实现父接口

interface Animal2{
    name: string;
    eat(str: string): void;
 }
  
 class Dogs implements Animal2{
     name: string;                // 属性
     constructor(name: string){   // 构造函数  接收实例化的参数
         this.name = name;
     }
     eat(){
         console.log('类类型接口:' + this.name + '吃骨头')
     }
 }
 var d= new Dogs('小狗子');
 d.eat();

4.5接口扩展:接口可以继承接口

// WorkerPerson 接口
interface WorkerPerson{
    name: string;
    eat(str: string): void;
}
 
// ProWorker 接口 继承 WorkerPerson 接口
interface ProWorker extends WorkerPerson{
    work(): void;
}
 
//  实现ProWorker接口
class Man implements ProWorker{
    public name: string;
    constructor(name:string){
        this.name = name
    }
 
    eat(){
        console.log('接口的扩展:' + this.name + '吃米饭')
    }
 
    work(params: string='改bug'){
        console.log('接口的扩展:' + this.name + params)
    }
}
 
var m = new Man('程序员');
m.eat();
m.work();

5.泛型:解决类、接口、方法的复用性,以及对不特定数据类型的支持

泛型可以支持不特定的类型,要求:传入参数和返回参数一致

T代表泛型,具体是什么类型由调用这个方法时决定

5.1泛型函数

function getData<T>(value:T):T{
    return value;
}
console.log('泛型函数:' + getData('字符串类型'))
console.log('泛型函数:' + getData(12356))//数值类型

5.2泛型类

例:有一最小堆算法,需支持同时返回字符串和数字两种类型,通过类的泛型来实现

class Minclass<T>{
        public list:T[] = []
        add(value:T){
            this.list.push(value)
        }
        min():T{ 
            let dataMin = this.list[0]
            for(let i=1;i<this.list.length;i++){
                if(dataMin > this.list[i]){
                    dataMin = this.list[i]
                }
            }
            return dataMin
        }
}
let minn = new Minclass<number>()//实例化类,并指定T的类型为number
minn.add(5)
minn.add(3)
minn.add(1)
console.log('泛型类:最小值为----' + minn.min() + '(number类型)')//1

let minn2 = new Minclass<string>()//实例化类,并指定T的类型为string,字符串按ASCII编码排序
minn2.add('a')
minn2.add('r')
minn2.add('g')
console.log('泛型类:最小值为----' + minn2.min() + '(string类型)')//a

例:定义一个User类,这个类的作用就是映射数据库字段;定义一个MySqlDB类用于操作数据库,然后把User类当作参数传入到MySqlDB中(把类当作参数来约束数据传入的类型)

-----------------一般写法-----------------
class MySqlDB{
    add(user:User):boolean{//引入User类作为参数,返回值为true或false(即boolean)
        console.log('类为参数:User如下')
        console.log(user)
        return true
	}	
}
//User类
class User{
    name:String | undefined //省略了public
    password:String | undefined//省略了public
}
let u = new User()
u.name='root',
u.password='123456'
let NewMysql = new MySqlDB()
NewMysql.add(u)

//ArticleCate类
class ArticleCate{
    title:string | undefined
    price:number | undefined
    sale?:boolean | undefined//可选参数
constructor(params:{title:string | undefined,price:number | undefined,sale?:boolean | undefined})
    {
        this.title = params.title
        this.price = params.price
        this.sale = params.sale
    }
}
let objA = {
    title:'java基础',
    price:35.00,
    sale:true
}
let Art = new ArticleCate(objA)
let NewMyArt = new MySqlDB<ArticleCate>()
NewMyArt.add(Art)
-----------------泛型类写法-----------------
class MySqlDB<T>{
    add(user:T):boolean{//引入User类作为参数,返回值为true或false(即boolean)
        console.log('泛型类--类为参数:User如下:')
        console.log(user)
        return true
    }
}
class User{
    name:String | undefined //省略了public
    password:String | undefined//省略了public
    status:number | undefined
}
// add()添加方法
let u = new User()
u.name='root',
u.password='123456'
u.status = 1
let NewMysql = new MySqlDB<User>()
NewMysql.add(u)

// update()修改方法
let objA = {
    title:'java基础',
    price:35.00,
    sale:true
}
let Art = new ArticleCate(objA)
let NewMyArt = new MySqlDB<ArticleCate>()
NewMyArt.update(Art,2)

5.3泛型接口

5.3.1写法1
interface Demo {
	<T>(value:T):T
}
var getDemo:Demo = function<T>(value:T):T{
	return value
}
console.log('泛型接口1:'+getDemo<number>(12)+'-----'+typeof(getDemo(12)))//泛型接口1:12-----number
console.log('泛型接口1:'+ getDemo<string>('a')+'-----'+typeof(getDemo('a')))//泛型接口1:a-----string
5.3.2写法2
interface Demo2<T>{
	(value:T):T
}
function getDemo2<T>(value:T):T{
	return value
}
let myGetDemo2:Demo2<number> = getDemo2
console.log('泛型接口2:'+myGetDemo2(123)+'-----'+typeof(myGetDemo2(123)))//泛型接口2:123-----number

let myGetDemo:Demo2<string> = getDemo2
console.log('泛型接口2:'+myGetDemo('abc')+'-----'+typeof(myGetDemo('abc')))//泛型接口2:abc-----string

6.TypeScript类型、接口、类、泛型的综合使用

功能:定义一个操作数据库的库 支持 Mysql Mssql MongoDb

要求1:Mysql MsSql MongoDb功能一样 都有 add update delete get方法

注意:约束统一的规范、以及代码重用

解决方案:需要约束规范所以要定义接口 ,需要代码重用所以用到泛型

1、接口:在面向对象的编程中,接口是一种规范的定义,它定义了行为和动作的规范

2、泛型 通俗理解:泛型就是解决 类 接口 方法的复用性、

//步骤1:定义一个数据库接口 DBI
interface DBI<T>{
    add(info:T):boolean
    update(info:T,id:number):boolean
    delete(id:number):boolean
    get(id:number):any[]
} 
// 步骤2:定义操作相应数据库的类 
//--------------------要实现一个泛型接口这个类也要是泛型类--------------------
    //定义一个操作Mysql数据库的类
        class MysqlDB<T> implements DBI<T>{
            constructor(){
                console.log('Mysql数据库建立连接')
            }
            add(info: T): boolean {
                console.log('操作Mysql数据库add方法:',info)
                return true
            }
            update(info: T, id: number): boolean {
                return true
            }
            delete(id: number): boolean {
                return true
            }
            
            get(id: number): any[] {
                let list = [
                    {
                        userName:'浩浩',
                        PassWord:'haohao'
                    },
                    {
                        userName:'苏苏',
                        PassWord:'susu'
                    },
                ]
                return list
            }

        }     
    // 定义一个操作MsSql数据库的类
    class MsSqlDB<T> implements DBI<T>{
        constructor(){
            console.log('MsSql数据库建立连接')
        }
        add(info: T): boolean {
            return true
        }
        update(info: T, id: number): boolean {
            console.log('操作msSql数据库update方法:',info,'id为:',id)
            return true
        }
        delete(id: number): boolean {
            return true
        }
        get(id: number): any[] {
            let list = [
                {
                    userName:'浩浩',
                    PassWord:'haohao'
                },
                {
                    userName:'苏苏',
                    PassWord:'susu'
                },
            ]
            return list
        }
    }
    //定义一个操作MongoDb数据库的类
    class MongoDB<T> implements DBI<T>{
        constructor(){
            console.log('MongoDB数据库建立连接')
        }
        add(info: T): boolean {
            return true
        }
        update(info: T, id: number): boolean {
            return true
        }
        delete(id: number): boolean {
            return true
        }
        get(id: number): any[] {
            let list = [
                {
                    userName:'浩浩',
                    PassWord:'haohao'
                },
                {
                    userName:'苏苏',
                    PassWord:'susu'
                },
            ]
            return list
        }
        
    }
    // 步骤3:操作用户表 定义一个Admin类和数据表做映射
    // 调用MysqlDb类
        class admin{
            UserName:string | undefined
            PassWord:String | undefined
        }
        let adm = new admin()
        adm.UserName = '浩浩'
        adm.PassWord = 'root'

        let OmySql = new MysqlDB<admin>()//类作为参数来约束传入数据的类型
        OmySql.add(adm)
        console.log('操作Mysql数据库get方法:',OmySql.get(2))
    //调用MsSqlDBl类
        class NewAdmin{
            UserName:string | undefined
            PassWord:String | undefined
        }
        let Nadm = new NewAdmin()
        Nadm.UserName = '浩浩'
        Nadm.PassWord = 'root'

        let OmsSql = new MsSqlDB<NewAdmin>()//类作为参数来约束传入数据的类型
        OmsSql.update(Nadm,2)
        console.log('操作msSql数据库get方法:',OmsSql.get(2))
        

7.命名空间和模块的区别

在代码量较大的情况下,为了避免各种变量命名相冲突,可将相似功能的函数、类、接口等放置到命名空间内。

同Java的包、.Net的命名空间一样,TypeScript的命名空间可以将代码包裹起来,只对外暴露需要在外部访问的对象。命名空间内的对象通过export关键字对外暴露。

7.1命名空间和模块的区别:

7.1.1命名空间:内部模块,主要用于组织代码,避免命名冲突。
7.1.2模块:ts的外部模块的简称,侧重代码的复用,一个模块里可能会有多个命名空间。

7.2模块及模块化封装

​ 我们可以把一些公共的功能抽离为一个单独文件作为一个模块,模块里的内容是私有的,若我们想在模块外使用则应先用export关键字将模块里的内容暴露,再在想使用的文件里用import关键字引入。(当前浏览器暂不支持export和require,可以讲代码用webpack打包。webpack打包教程链接:https://blog.youkuaiyun.com/qq_35617751/article/details/106635859)


    let dburl='xxxxxxxxxxx'

//导出方法1
    export function getDB():any[]{
        console.log('获取数据库的数据')
        let list = [
            {
                userName:'浩浩',
                PassWord:'haohao'
            },
            {
                userName:'苏苏',
                PassWord:'susu'
            },
        ]
        return list 
    }
    
    export function add():any{
        return `数据添加成功!!`
    }

//导出方法2
// export {getDB,add}

//导出方法3
// export default getDB --------------export default xxxx 只能使用一次----------

//引入方法1
import {getDB,add} from './modules/dbmodules';//表示调用模块里的方法
console.log('我是模块里的getDB方法:',getDB())
console.log('我是模块里的add方法:',add())

//引入方法2
// import {getDB as get,add} from './modules/dbmodules';//表示调用模块里的方法-------给getDB重命名
// console.log('我是模块里的getDB方法:',getDB())
// console.log('我是模块里的add方法:',add())

// 引入方法3
// import getDB from './modules/dbmodules';
// console.log('我是模块里的getDB方法:',getDB())

7.3命名空间

export namespace A{
    interface Animal{
        name: string;
        eat(str: string): void;
    }
    
    export class Dogs implements Animal{
        name: string;                // 属性
        constructor(name: string){   // 构造函数  接收实例化的参数
            this.name = name;
        }
           eat(){
            console.log('28、命名空间--类类型接口:' + this.name + '吃骨头')
       }
   }
}
export  namespace B{
        interface Animal{
            name: string;
            eat(str: string): void;
        }
        
        export class Dogs implements Animal{
            name: string;                // 属性
            constructor(name: string){   // 构造函数  接收实例化的参数
                this.name = name;
            }
               eat(){
                console.log('29、命名空间--类类型接口:' + this.name + '吃肉')
           }
       }
    }


//命名空间
import {A,B} from './modules/dbmodules'
    var d1= new A.Dogs('小狗子');
    d1.eat();
    var d2= new B.Dogs('星星');
    d2.eat();

8.装饰器

装饰器:装饰器是一种特殊类型的声明,它能够被附加到类声明,方法,属性或参数上,可以修改类的行为。

通俗的讲装饰器就是一个方法,可以注入到类、方法、属性参数上来扩展类、属性、方法、参数的功能。

常见的装饰器有:类装饰器、属性装饰器、方法装饰器、参数装饰器

装饰器的写法:普通装饰器(无法传参) 、 装饰器工厂(可传参)

8.1类装饰器:类装饰器在类声明之前被声明(紧靠着类声明)。

类装饰器应用于类构造函数,可以用来监视,修改或替换类定义。 传入一个参数

8.1.1 类装饰器:普通装饰器(无法传参)
function logClass(params:any){
    //params就是当前类
    params.prototype.ApiUrl = 'xxxxxxx'
    params.prototype.run =  function(){
        console.log('31、普通装饰器:我是run方法')
    }
}
@logClass
class HttpClient{
    constructor(){

    }
    getCoontent (){

    }
}

let httpp:any = new HttpClient()
console.log('30、普通装饰器(动态扩展的属性)',httpp.ApiUrl)
httpp.run()
8.1.2 类装饰器:类装饰器工厂(可传参)
function decoClass(params:any){
    return function(target:any){
        console.log('32、类装饰器工厂:我是target-----',target)
        console.log('33、类装饰器工厂:我是params-----',params)
        target.prototype.ApiUrl = params
    }
}
@decoClass('file:///G:/TypeScript/index.html')//给params赋值
//newHttp类为target内容
class newHttp{ 
    constructor(){

    }
    getCoontent (){

    }
}
let newhtpp:any = new newHttp()
console.log('34、类装饰器工厂:我是target的ApiUrl-----',newhtpp.ApiUrl)

8.1.3重载构造函数

类装饰器表达式会在运行时当作函数被调用,类的构造函数作为其唯一参数

若类装饰器返回一个值,它会使用提供的构造函数来替换类的声明

function oneLogClass(target:any){
    return class extends target{
        oneUrl:any = '我是修改后的url'
        getData(){
        this.oneUrl = '-----------' + this.oneUrl
           console.log('36、类装饰器:重载构造函数',this.oneUrl)
        }
    }
}

@oneLogClass
 class oneClass{
     public oneUrl:string | undefined;
     constructor(){
        this.oneUrl = '我是默认的url'
     }
     getData(){
        console.log('35、类装饰器:重载构造函数',this.oneUrl)
     }
 }
 let a =new oneClass()
 a.getData()

8.2属性装饰器:属性装饰器表达式在运行时被当作函数来调用

传入以下两个参数

(1)对于静态成员来说事类的构造函数,对于实例成员是类的原型对象

(2)成员的名字

//类装饰器
 function logClass1(params:any){
    return function(target:any){
        console.log('37、属性装饰器---类装饰器:我是target-----',target)
        console.log('38、属性装饰器---类装饰器:我是params-----',params)
        target.prototype.ApiUrl = params
    }
}

//属性装饰器
 function logProterty(params:any){
     return function(target:any,atrrName:any){
        target[atrrName] = params

     }

 }

@logClass1('https://www.baidu.com/')//给params赋值
//newHttp类为target内容
class httpClient{ 
    @logProterty('我是属性装饰器')
    public httpUrl:string | undefined //属性

    constructor(){

    }
    getCoontent (){
        console.log('40、属性装饰器:我是httpClient的httpUrl-----',this.httpUrl)
    }
}
let newHttpClient:any = new httpClient()
console.log('39、属性装饰器:我是target的ApiUrl-----',newHttpClient.ApiUrl)
newHttpClient.getCoontent()

8.3方法装饰器:被应用到方法的属性描述附上,可用来监视、修改或替换方法定义

​ 在运行时传入3个参数:

​ (1)对于静态成员来说是类的构造函数,对于实例成员来说是类的原型对象

​ (2)成员的名字

​ (3)成员的属性描述符

//方法装饰器
function methodLog(params:any){
    return function(target:any,methodName:string,describe:any){
        console.log('41、方法装饰器:原型对象----',target,',----当前方法名----',methodName,',----当前方法内容----',describe.value)
        target.httpUrl = params
        
        //修改装饰器的方法  把装饰器方法里面传入的参数都改为string类型
        /*
            步骤(1)保存当前方法
         */
            let nowMethod = describe.value
            describe.value = function(...args:any[]){//...args表示所有传入的参数
                args = args.map((value)=>{//在args.map的回调函数里把每一个参数都变为String类型
                     return String(value)  
                    
                })
                console.log('42、方法装饰器----方法装饰器输出----处理过的getCoontent方法的参数:',args)

                //以上代码可做替换方法使用

                //以下代码为修改方法(方法冒充)
                nowMethod.apply(this,args)//this指当前方法,args指处理过后的参数
                

            }
    }
}

class httpClientMethod{ 
    public httpUrl:string | undefined //属性

    constructor(){

    }
@methodLog('ssss')
    getCoontent(...args:any[]){
        console.log('43、方法装饰器----getCoontent方法输出----getCoontent方法的处理过的参数:',args)
        console.log('44、方法装饰器----getCoontent方法输出----httpClientMethod的httpUrl:',this.httpUrl)
    }
}

let hClientM:any = new httpClientMethod()
hClientM.getCoontent(11111,'dsfsgd',123)

8.4方法参数装饰器:参数装饰器表达式在运行时当作函数来调用,可使用参数装饰器为类的原型增加一些元素数据(使用较少)

传入以下3个参数

(1)对于静态成员来说是类的构造函数,对于实例成员来说是类的原型对象

(2)方法名称

(3)参数在函数参数列表里的索引

//方法参数装饰器
 function logParams(params:any){
     return function(target:any,MethodsName:any,paramsIndex:any){
        console.log('45、方法参数装饰器:原型对象----',target,',----当前方法名----',MethodsName,',----参数索引----',paramsIndex)
        target.methodsParams = params //为类的原型增加元素数据
     }
 }

class httpClientMethod2{ 
    public httpUrl:string | undefined //属性

    constructor(){

    }
    getCoontent(@logParams('id') id:any){
        console.log('46、我是方法参数装饰器的getCoontent方法')
      }
}
let MethodParams:any = new httpClientMethod2()
MethodParams.getCoontent('12321')
console.log('47、我是方法参数装饰器的参数methodsParams:',MethodParams.methodsParams)

装饰器的执行顺序:

属性装饰器 > 方法装饰器 > 方法参数装饰器 > 类装饰器

若有多个同类型装饰器则按从后往前的顺序执行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值