TS 泛型+裝飾器

typescript 中的泛型

  1. 泛型的定義
  2. 泛型函數(shù)
  3. 泛型類
  4. 泛型接口

  • 泛型:軟件工程中灸拍,我們不僅要創(chuàng)建一致的定義良好的API做祝,同時也要考慮可重用性。組件不僅能夠支持當前的數(shù)據(jù)類型鸡岗,同時也能支持未來的數(shù)據(jù)類型混槐,這在創(chuàng)建大型系統(tǒng)是為你提供了十分靈活的功能

  • 在像 C# 和 java 這樣的語言中,可以使用泛型來創(chuàng)建可重用的組件轩性,一個組件可以支持多種類型的數(shù)據(jù)声登。這樣用戶就可以以自己的數(shù)據(jù)類型來使用組件

  • 通俗的講:泛型就是解決 類 接口 方法 的復(fù)用性、以及對不特定數(shù)據(jù)類型的支持


泛型的定義
// 只能返回 string 類型的數(shù)據(jù)
function getData(value:string):string{
    return value
}

// 傳入什么類型,就返回什么類型
// 泛型: 可以支持不特定的數(shù)據(jù)類型
// T 表示泛型,具體什么類型是調(diào)用方法是決定的
function getData<T>(value:T):T{
    return value
}
getData<number>('123')  // ×
getData<number>(123)    // √

泛型類
// 泛型類: 比如有個最小堆算法,需要同時支持返回數(shù)字和字符串兩種類型,通過類的泛型來實現(xiàn)
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())

函數(shù)類型接口
/** 函數(shù)類型接口 規(guī)范 */
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","張三")

需求:定義一個操作數(shù)據(jù)庫的庫 支持 Mysql Mssql MongoDb

  • 要求1: Mysql Mssql MongoDb 功能一樣揣苏,都有 add update delete get 方法
  • 注意:約束統(tǒng)一的規(guī)范悯嗓、以及代碼重用
  • 解決方案:需要約束規(guī)范所以要定義接口卸察,需要代碼重用所以用到泛型
    1. 接口:在面向?qū)ο蟮木幊讨猩鹱鳎涌谑且?guī)范的定義,它定義了行為和動作的規(guī)范
    1. 泛型:通俗的理解蛾派,泛型就是解決 類 接口 方法 的復(fù)用性
interface DBI<T>{
    add(info:T):boolean
    update(info:T,id:number):boolean
    delete(id:number):boolean
    get(id:number):any[]
}

//定義一個操作mysql數(shù)據(jù)庫的類
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數(shù)據(jù)庫的類
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類和數(shù)據(jù)庫表做映射
class User{
    username:string | undefined
    password:string | undefined
}

let u = new User()
u.username = '張三'
u.password = '123456'

let mysql = new MysqlDb<User>() // 類作為參數(shù)來約束數(shù)據(jù)的類型
mysql.add(u)



ts模塊

內(nèi)部模塊:命名空間

外部模塊:模塊

// db.ts
export function getData():any[]{
    return '數(shù)據(jù)'
}

// index.ts
import {getData} from './db'

// 命名空間  --> 避免命名重復(fù)
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{
    代碼
}

裝飾器

類裝飾器:在不修改類的情況下擴展類的功能
// 普通裝飾器 無參數(shù)
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')
    }
}

執(zhí)行順序

屬性裝飾器 => 方法裝飾器 => 方法參數(shù)裝飾器2 => 方法參數(shù)裝飾器1 => 類裝飾器2 => 類裝飾器1

同樣的裝飾器從后到前執(zhí)行
END
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末俄认,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子洪乍,更是在濱河造成了極大的恐慌眯杏,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件壳澳,死亡現(xiàn)場離奇詭異岂贩,居然都是意外死亡,警方通過查閱死者的電腦和手機巷波,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進店門萎津,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人抹镊,你說我怎么就攤上這事锉屈。” “怎么了垮耳?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵颈渊,是天一觀的道長。 經(jīng)常有香客問我终佛,道長俊嗽,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任铃彰,我火速辦了婚禮绍豁,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘牙捉。我一直安慰自己竹揍,他們只是感情好敬飒,可當我...
    茶點故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著鬼佣,像睡著了一般驶拱。 火紅的嫁衣襯著肌膚如雪霜浴。 梳的紋絲不亂的頭發(fā)上晶衷,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天,我揣著相機與錄音阴孟,去河邊找鬼晌纫。 笑死,一個胖子當著我的面吹牛永丝,可吹牛的內(nèi)容都是我干的锹漱。 我是一名探鬼主播,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼慕嚷,長吁一口氣:“原來是場噩夢啊……” “哼哥牍!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起喝检,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤嗅辣,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后挠说,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體澡谭,經(jīng)...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年损俭,在試婚紗的時候發(fā)現(xiàn)自己被綠了蛙奖。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,834評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡杆兵,死狀恐怖雁仲,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情琐脏,我是刑警寧澤伯顶,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站骆膝,受9級特大地震影響祭衩,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜阅签,卻給世界環(huán)境...
    茶點故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一掐暮、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧政钟,春花似錦路克、人聲如沸樟结。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瓢宦。三九已至,卻和暖如春灰羽,著一層夾襖步出監(jiān)牢的瞬間驮履,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工廉嚼, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留玫镐,地道東北人。 一個月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓怠噪,卻偏偏與公主長得像恐似,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子傍念,可洞房花燭夜當晚...
    茶點故事閱讀 44,779評論 2 354

推薦閱讀更多精彩內(nèi)容