美文网首页
TS 泛型+装饰器

TS 泛型+装饰器

作者: kevin5979 | 来源:发表于2021-02-02 10:17 被阅读0次

    typescript 中的泛型

    1. 泛型的定义
    2. 泛型函数
    3. 泛型类
    4. 泛型接口

    • 泛型:软件工程中,我们不仅要创建一致的定义良好的API,同时也要考虑可重用性。组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统是为你提供了十分灵活的功能

    • 在像 C# 和 java 这样的语言中,可以使用泛型来创建可重用的组件,一个组件可以支持多种类型的数据。这样用户就可以以自己的数据类型来使用组件

    • 通俗的讲:泛型就是解决 类 接口 方法 的复用性、以及对不特定数据类型的支持


    泛型的定义
    // 只能返回 string 类型的数据
    function getData(value:string):string{
        return value
    }
    
    // 传入什么类型,就返回什么类型
    // 泛型: 可以支持不特定的数据类型
    // T 表示泛型,具体什么类型是调用方法是决定的
    function getData<T>(value:T):T{
        return value
    }
    getData<number>('123')  // ×
    getData<number>(123)    // √
    
    
    泛型类
    // 泛型类: 比如有个最小堆算法,需要同时支持返回数字和字符串两种类型,通过类的泛型来实现
    class MinClass{
        public list:number[] = []
        add(num:number){
            this.list.push(num)
        }
        min():number{
            let minNum = this.list[0]
            for(let i = 0; i < this.list.length; i++){
                if(minNum > this.list[i]){
                    minNum = this.list[i]
                }
            }
            return minNum
        }
    }
    
    let m = new MinClass()
    m.add(2)
    m.add(3)
    m.add(1)
    alert(m.min())
    
    
    类的泛型
    // 类的泛型
    class MinClass<T>{
        public list:T[] = []
        add(value:T):void{
            this.list.push(value)
        }
        min():T{
            let minNum = this.list[0]
            for(let i = 0; i < this.list.length; i++){
                if(minNum > this.list[i]){
                    minNum = this.list[i]
                }
            }
            return minNum
        }
    }
    
    let m = new MinClass<number>()
    m.add(2)
    m.add(3)
    m.add(1)
    alert(m.min())
    
    
    函数类型接口
    /** 函数类型接口 规范 */
    interface ConfigFn{
        (value1:string,value2:string):string
    }
    
    let setData:ConfigFn = function(value1:string,value2:string):string{
        return value1 + value2
    }
    setData("name","张三")
    
    // 泛型接口
    interface ConfigFn{
        <T>(value1:T,value2:T):T
    }
    
    let setData:ConfigFn = function<T>(value1:T,value2:T):T{
        return value1 + value2
    }
    setData<string>("name","张三")
    //----------------------------------------
    interface ConfigFn<T>{
        (value1:T,value2:T):T
    }
    
    function getData<T>(value1:T,value2:T):T{
        return value1 + value2
    }
    let myGetData:ConfigFn<string> = getData
    myGetData("name","张三")
    

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

    • 要求1: Mysql Mssql MongoDb 功能一样,都有 add update delete get 方法
    • 注意:约束统一的规范、以及代码重用
    • 解决方案:需要约束规范所以要定义接口,需要代码重用所以用到泛型
      1. 接口:在面向对象的编程中,接口是规范的定义,它定义了行为和动作的规范
      1. 泛型:通俗的理解,泛型就是解决 类 接口 方法 的复用性
    interface DBI<T>{
        add(info:T):boolean
        update(info:T,id:number):boolean
        delete(id:number):boolean
        get(id:number):any[]
    }
    
    //定义一个操作mysql数据库的类
    class MysqlDb<T> implements DBI<T>{
        add(info:T):boolean{
            
        }
        update(info:T,id:number):boolean{
            
        }
        delete(id:number):boolean{
            
        }
        get(id:number):any[]{
            
        }
    }
    
    //定义一个操作mssql数据库的类
    class MssqlDb<T> implements DBI<T>{
        add(info:T):boolean{
            
        }
        update(info:T,id:number):boolean{
            
        }
        delete(id:number):boolean{
            
        }
        get(id:number):any[]{
            
        }
    }
    
    // 操作用户表: 定义一个User类和数据库表做映射
    class User{
        username:string | undefined
        password:string | undefined
    }
    
    let u = new User()
    u.username = '张三'
    u.password = '123456'
    
    let mysql = new MysqlDb<User>() // 类作为参数来约束数据的类型
    mysql.add(u)
    
    
    

    ts模块

    内部模块:命名空间

    外部模块:模块

    // db.ts
    export function getData():any[]{
        return '数据'
    }
    
    // index.ts
    import {getData} from './db'
    
    
    // 命名空间  --> 避免命名重复
    namespace A{    // 相当于私有的,需要暴露方法
        //代码
        export class Dog{
            name:string
            constructor(name:string){
                this.name = name
            }
            run(){
                console.log(this.name + "是dog")
            }
        }
    }
    
    let d = new A.Dog("xxx")
    d.run()
    
    namespace B{
        代码
    }
    

    装饰器

    类装饰器:在不修改类的情况下扩展类的功能
    // 普通装饰器 无参数
    function logClass(params:any){
        conaole.log(params)
        // params 就是当前类
        params.prototype.apiUrl = 'xxx'
    }
    
    @logClass
    class HttpClient{
        constructor(){
            
        }
        getData(){
            
        }
    }
    
    let h:any = new HttpClient()
    console.log(h.apiUrl)
    /////----------------------------------/////
    // 装饰器工厂  可传参
    function logClass(params:string){
        conaole.log(params)
        return function(target:any){
            console.log(target) // 当前类
            console.log(params) // http://xxx
            target.prototype.apiUrl = params
        }
    }
    
    @logClass('http://xxx')
    class HttpClient{
        constructor(){
            
        }
        getData(){
            
        }
    }
    
    let h:any = new HttpClient()
    console.log(h.apiUrl)
    
    
    属性装饰器
    function logProperty(params:any){
        return function(target:any,attr:any){
            console.log(target) // 当前类
            console.log(attr)   // url
            target[attr] = params   
        }
    }
    
    class HttpClient{
        @logProperty('http://xxx')
        public url:any | undefined
        
        constructor(){
            
        }
        getData(){
            
        }
    }
    
    let h:any = new HttpClient()
    console.log(h.apiUrl)
    

    方法装饰器

    function logMethod(params:any){
        return function(target:any,methodName:any,desc:any){
            console.log(target)
            console.log(methodName)
            console.log(desc)
            console.log(desc.value)
            target.apiUrl = 'xxx'
            target.run = function(){
                console.log('run')
            }
            let oMethod = desc.value
            desc.value = function(...args:any[]){
                args = args.map((value)=>{
                    return String(value)
                })
                conaole.log(args)
                oMethod.apply(this,args)
            }
        }
    }
    
    class HttpClient{
        @logProperty('http://xxx')
        public url:any | undefined
        
        constructor(){}
        @logMethod("http://xxx")
        getData(...args:any){
            console.log('getData')
        }
    }
    

    执行顺序

    属性装饰器 => 方法装饰器 => 方法参数装饰器2 => 方法参数装饰器1 => 类装饰器2 => 类装饰器1

    同样的装饰器从后到前执行
    END

    相关文章

      网友评论

          本文标题:TS 泛型+装饰器

          本文链接:https://www.haomeiwen.com/subject/pkvjcktx.html