Learning Typescript(一)

212 阅读3分钟

最近复习基础看到了Learning Typescript这本书,翻开学习,发现了不少知识,在此记录一下。

面向对象编程

SOLID原则

利用Typescript进行面向对象编程要注意五个点,简称为“SOLID”原则

  • 单一职责原则(SRP): 表明软件组件(函数,类,模块)必须专注于单一的任务(只有单一的职责)
  • 开/闭原则(OCP): 表明软件设计时必须时刻考虑到(代码)可能的发展(具有扩展性),但是程序的发展必须最少地修改已有的代码(对已有的修改封闭) -里氏替换原则(LSP): 表明只要继承的是同一个接口,程序里任意一个类都可以被其他的类替换。在替换完成后,不需要其他额外的工作程序就能像原来一样运行。 -接口隔离原则(ISP): 表明我们应该将那些非常大的接口拆分成一些更具体的接口,这样客户端就只需要关心他们需要用到的接口 -依赖反转原则(DIP): 表明一个方法应该遵从依赖于抽象(接口)而不是一个实例(类)的概念。 用Typesciript编写一个类如下:
   class Person{
       public name: string;
       public surname: string;
       public email: string;
       constructor(name: string, surname: string, email: string){
           this.email = email;
           this.name = name;
           this.surname = surname;
       }
       greet(){
           alert("hello");
       }
   }
   var p : Person = new Person("liming", "li", "123@163.com");

如果要验证email的格式,在Person上增加代码会使Person类变得非常大,我们可以八email抽象成一个类分离出来,这体现了第一个单一职责原则。

class Email{
    public email: string;
    constructor(email: string){
        if(this.validateEmail(email)){
            this.email = email
        }else{
            throw new Error("Invalid email!")
        }
    }
    private validateEmail(email: string){
        var re = '/\S+@\S+\.\S+/';
        return re.test(email)
    }
}
class Person{
       public name: string;
       public surname: string;
       public email: Email;
       constructor(name: string, surname: string, email: string){
           this.email = email;
           this.name = name;
           this.surname = surname;
       }
       greet(){
           alert("hello");
       }
   }

在面向对象的过程中,类与类有一些关系,比如关联,聚合,组合,继承,混合等,接下来并不介绍他们的概念,而是介绍一下泛型类和泛型约束

泛型类

泛型类如同泛型函数,可以介绍很多重复的代码,接下来用代码说明 首先是一个类

ts_1.png 这里包括一个User的类和一个NotGenericUserRepository的类,后面这个类是获取User的列表,并传给JSON文件,当我们想获取一个会议,或者一个歌曲列表时,不同的类形成的这个GenericRepository类也就要重写,这时可以利用泛型类。如下所示:

ts_2.png 有时候,我们需要泛型约束,如上述例子,新需求是增加一些变更来验证通过Ajax请求的数据:

success: (data)=>{
    var list: T[]
    var items = <T[]>data.items
    for(let i=0;i<items.length;i++){
        if(items[i].isValid()){ // 验证
            // ...
        }
    }
    resolve(list)
}

那我们可以写一个验证接口,将泛型进行约束:

class User implements ValidatableInterface{
    public name: string
    public password: string
    constructor(name: string, password: string){
        this.name = name
        this.password = password
    }
    public isValid(){
        // ...
        return true
    }
}
class Talk implements ValidatableInterface{
    public name: string
    constructor(name: string, password: string){
        this.name = name
    }
    public isValid(){
        // ...
        return true
    }
}
class NotGenericUserRepository<T extends ValidatableInterface>{
    private _url: string
    constructor(url: string){
        this._url = url
    }
    public getAsync(){
        return new Promise((resolve: (users: T[]) => void. reject) => {
            $.ajax({
                url: this._url,
                type: "GET",
                dataType: "JSON",
                success: (data)=>{
                    var list: T[]
                    var items = <T[]>data.items
                    for(let i=0;i<items.length;i++){
                        if(items[i].isValid()){
                            list.push(items[i])
                        }
                    }
                    resolve(list)
                },
                error: (e)=>{
                    reject(e)
                }
            })
        })
    }
}class User implements ValidatableInterface{
    public name: string
    public password: string
    constructor(name: string, password: string){
        this.name = name
        this.password = password
    }
    public isValid(){
        // ...
        return true
    }
}
class Talk implements ValidatableInterface{
    public name: string
    constructor(name: string, password: string){
        this.name = name
    }
    public isValid(){
        // ...
        return true
    }
}
class NotGenericUserRepository<T extends ValidatableInterface>{
    private _url: string
    constructor(url: string){
        this._url = url
    }
    public getAsync(){
        return new Promise((resolve: (users: T[]) => void. reject) => {
            $.ajax({
                url: this._url,
                type: "GET",
                dataType: "JSON",
                success: (data)=>{
                    var list: T[]
                    var items = <T[]>data.items
                    for(let i=0;i<items.length;i++){
                        if(items[i].isValid()){
                            list.push(items[i])
                        }
                    }
                    resolve(list)
                },
                error: (e)=>{
                    reject(e)
                }
            })
        })
    }
}

泛型中的new操作

要通过代码来创建新的对象,我们需要声明泛型T拥有构造函数,这意味着我们需要像下面一样,用type: {new() :T;}替代type:T

ts_4.png