typeScript学习总结

100 阅读7分钟

简介

  • typeScript是什么:typeScript是js的超集
  • 特点:提供类的类型和es6的支持
  • 优点:
    • 增加代码的可读性和可维护性以及兼容性
    • 类型系统是最好的文档
    • 在编译阶段就发现错误,比运行时发现错误好
    • 增加了编辑器和ide的功能,代码不全、接口提示、跳转到定义、重构
    • js文件可重命名为.ts文件
    • 不显式的定义类型,也能自动作出类型推论
    • 可定义一切类型 即使typescript编译报错,也可生成js文件 兼容第三方库,即使第三方库不是用typeScript写的,也可编写单独的类型文件供typeScript读取
  • 缺点:
    • 集成到构建流程需要工作量,可能和一些库结合的不是很完美
    • 安装: npm i -g typescript 执行tsc ts文件来编译会生成js文件或者ide支持

数据类型

数据类型主要作用是:方便数据维护和数据校验

布尔类型 boolean
数字类型 number
字符串类型 string
任意js对象 Object
    写法: let a: {name:string}
           let a:{name:string,age?:number} ,问号表示可选值
           let a:{name:string,[propName:string]:any},不限制其它属性
           let a:(a:number,b:number)=>number
数组类型 array 
    写法:var arr:Arrary<number> =[11,22,33];
          var arr:number[] = [11,22,33];
          var arr:any[] =['1yhuyhub1',22,33,true];
元组类型 tuple (固定长度数组)
    写法:let a:[string,string]
枚举类型 enum
    写法:enum Flag = {success =11; error=2} let s:Flag = Flag.success;
任意类型 any
    写法:function par(): void { console.log('par') }
类型安全的any unknown 
没有值或undefined void
不能是任何值 never
    写法:var a:never; a=(()=>{ throw new Error('错误'); })()

类型断言,告诉解析器变量的实际类型

a=b as string
a=<string>b

与,或

let a:{name:string}&{age:number},a={name:'大帅比',age:18}
let a:'男' | '女'

类型别名

只能声明一个
type mgType=1|2|3,let a:myType,type a{name:string,age:number}

接口

  • 只能定义对象
  • 可以重复声明
  • 定义类的时候可以限制结构
(function() {

    // 描述一个对象的类型(别名形式)
    type myType = {
        name: string,
        age: number
    }

    // type myType = {} // 报错 重复声明

    /**
     * 接口用来定义一个类结构,用来定义一个类中应该包含哪些属性和方法
     * 接口也可用来当成类型声明去使用
     * 
     * 接口可重复声明
    */

    interface myInterface {
        name: string,
        age: number
    }

    interface myInterface {
        gender: string
    }

    const obj: myInterface = {
        name: '哈哈哈',
        age: 12,
        gender: '男'
    }

    /**
     * 接口可以在定义类的时候限制类的结构
     * 接口中的所有属性都不能有实际的值
     * 接口只定义类的结构 而不考虑实际值
    */

    interface myInter {
        name: string;

        sayHello(): void;
    }

    /**
     * 定义类时,可以使类去实现一个接口
     * 实现接口就是使类满足接口的要求
     * 
    */

    class MyClass implements myInter {
        name: string;

        // 需要写构造函数 给name赋值
        constructor(name: string) {
            this.name = name;
        }

        sayHello() {
            console.log('大家好');
        }
    }

    const m = new MyClass('嘻嘻');
    m.sayHello(); // 大家好
    console.log(m); // MyClass {name: "嘻嘻"}

})();

// 编译后的js
"use strict";
(function () {
    const obj = {
        name: '哈哈哈',
        age: 12,
        gender: '男'
    };
    /**
     * 定义类时,可以使类去实现一个接口
     * 实现接口就是使类满足接口的要求
     *
    */
    class MyClass {
        // 需要写构造函数 给name赋值
        constructor(name) {
            this.name = name;
        }
        sayHello() {
            console.log('大家好');
        }
    }
    const m = new MyClass('嘻嘻');
    m.sayHello();
    console.log(m);
})();

继承

抽取公共属性或者函数,用作继续的父级

(function() {

    // 定义animal类
    class Animal {
        name: string;
        age: number;

        // constructor 构造函数 构造函数会在对象创建时调用(默认调用)
        constructor(name: string, age: number) {
            // 在实例方法中 this表示当前的实例
            // 可以通过this向新建的对象中添加属性
            this.name = name;
            this.age = age;
        }

        sayHello() {
            console.log('动物在叫~');
        }
    }

    /**
     * 此时 Animal 被称为为父类 Dog、Cat 被称为子类
     * 使用继承后 子类将会拥有父类的所有方法和属性
     * 如果在子类中添加了和父类的相同的方法 则子类方法会覆盖父类的方法
    */
    // 定义狗的类 继承Animal类
    class Dog extends Animal {
        run() {
            console.log(`${this.name}在跑路~~~`);
        }
        sayHello() {
            console.log('汪汪汪');
        }
    }

    // 定义猫的类 继承Animal类
    class Cat extends Animal {
        
    }

    const dog = new Dog('小黑', 3);
    const cat = new Dog('咪咪', 2);

    console.log(dog); // Dog {name: "小黑", age: 3}
    dog.sayHello(); // 汪汪汪
    dog.run(); // 小黑在跑路~~~

    console.log(cat); //Dog {name: "咪咪", age: 2}
    cat.sayHello(); // 动物在叫~
    cat.run(); // 报错

})();

super

super即调用父级对象内容

// 超类
(function() {

    // 定义animal类
    class Animal {
        name: string;

        constructor(name: string) {
            this.name = name;
        }

        sayHello() {
            console.log('动物在叫~');
        }
    }

   
    class Dog extends Animal {

        age: number;

        constructor(name: string, age: number) {
            // 如果在子类中写了构造函数 在子类函数中必须对父类的构造函数进行调用
            super(name); // 调用父类的构造函数
            this.age = age;
        }

        sayHello() {
            // 在类的方法中 super表示当前类的父类
            //super.sayHello();
            console.log('汪汪汪');
        }
    }

    const dog = new Dog('小黑', 2);

    dog.sayHello(); // 汪汪汪
    console.log(dog); // Dog {name: "小黑", age: 2}

})();

抽象类

  • abstrict 一个class,抽象类不能实例化,只能继承
(function() {

    // 定义animal类
    /**
     * 以abstract开头的类是抽象类
     * 抽象类与其他类区别不大 只是不能用来创建对象
     * 抽象类就是专门用来继承的类
     * 
     * 抽象类中可以添加抽象方法
    */
    abstract class Animal {
        name: string;

        constructor(name: string) {
            this.name = name;
        }

        // 抽象方法使用abstract开头 没有方法体
        // 抽象方法只能定义在抽象类中 子类必须对起抽象方法重写
        abstract sayHello(): void;
    }

   
    class Dog extends Animal {

        sayHello() {
            // 在类的方法中 super表示当前类的父类
            //super.sayHello();
            console.log('汪汪汪');
        }
    }

    class Cat extends Animal {

    } // 报错 没有实现s对ayHello重写

    const dog = new Dog('小黑');

    dog.sayHello();
    console.log(dog);
    
    //const ani = new Animal(); // 报错 无法创建实例

})();

泛型

  • 在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的特性
// function fn(a: number): number {
//     return a;
// }

/**
 * 在定义类或函数时 如果遇到类型不明确就可以使用泛型
 * 
*/

function fn<T>(a: T): T {
    return a;
}

// 直接调用具有泛型的函数
const result = fn(123); // 不指定泛型 ts会自动对类型进行推断
const result2 = fn<string>('hello'); // 指定泛型

// 多个

function fn2<T, K>(a: T, b: K): T {
    return a;
}

const result3 = fn2<number, string>(123, 'hello');

interface Inter {
    length: number
}

function fn3<T extends Inter>(a: T): number {
    return a.length;
}

fn3('122'); // 3
//fn3(123); // 类型“number”的参数不能赋给类型“Inter”的参数
fn3({length: 10}); // 10

// 定义类也可以使用泛型

class MyClass<T> {
    name: string;
    constructor(name: string) {
        this.name = name;
    }
}

const c = new MyClass<string>('哈哈哈');
//const d = new MyClass<number>(123); // 类型“number”的参数不能赋给类型“string”的参数

属性的封装

  • public 公有修饰符,可以在实例外使用修饰符的属性或行为。
  • protected 受保护修饰符,可以在类(子类)内使用修饰符的属性或行为
  • private 私有修手符,只可以在当前类(非子类)使用修饰符的属性或行为。
  • readonly 将属性设置为只读的,只读的属性不可被修改,只读属性必须在声明时或构造函数里被初始化。
(function() {

    // 定义一个人的类
    class Person {
        // ts可以在属性前添加修饰符
        /**
         * public 修饰的属性可以在任意位置访问(修改)默认值
         * private 私有属性 只能在对象内部中访问(修改)默认值
         * protected 受保护的属性 只能在当前类和当前类的子类访问
         * 
        */
        private _name: string;
        age: number;

        constructor(name: string, age: number) {
            this._name = name;
            this.age = age;
        }

        // 定义方法 获取name属性
        // getName() {
        //     return this._name;
        // }
        // 定义方法 设置name属性
        // setName(value: string) {
        //     this._name = value;
        // }

        // ts中设置getter方法的方式
        get name() {
            console.log('get name() 方法执行了---');
            return this._name;
        }

        set name(value: string) {
            this._name = value;
        }
    }
    
    const per = new Person('猴子', 18);

    /**
     * 现在属性是在对象中设置的 属性可以任意被修改
     * 属性被任意修改会导致对象中的数据变得非常不安全
     * 
    */

    //per._age = 20; // 报错 不能访问
    //per.name = '八戒';

    //console.log(per); // 输出: {name: "八戒", age: 20}

    // per.setName('八戒');
    // console.log(per.getName()); // 输出: 八戒

    console.log(per.name); // get name() 方法执行了---   猴子
    per.name = '八戒';
    console.log(per.name); // 八戒

    class A {
        protected num: number;

        constructor(num: number) {
            this.num = num;
        }
    }

    class B extends A {
        test() {
            console.log(this.num);
        }
    }

    const b = new B(123);
    // b.num = 55; // 只能在类“A”及其子类中访问

    class C {

        // 可以直接将属性定义在构造函数中
        constructor(public name: string, public age: number) {
            this.name = name;
            this.age = age;
        }
    }

    const c = new C('xxx', 123);
    console.log(c); // {name: "xxx", age: 123}

})();

推荐看这篇 TypeScript 高级类型及用法