typescript 订阅
TypeScript是一种由微软开发的开源、跨平台的编程语言。它是JavaScript的超集,最终会被编译为JavaScript代码。TypeScript添加了可选的静态类型系统、很多尚未正式发布的ECMAScript新特性(如装饰器 [1]  )。2012年10月,微软发布了首个公开版本的TypeScript,2013年6月19日,在经历了一个预览版之后微软正式发布了正式版TypeScript。当前最新版本为TypeScript3.8。 [2] 展开全文
TypeScript是一种由微软开发的开源、跨平台的编程语言。它是JavaScript的超集,最终会被编译为JavaScript代码。TypeScript添加了可选的静态类型系统、很多尚未正式发布的ECMAScript新特性(如装饰器 [1]  )。2012年10月,微软发布了首个公开版本的TypeScript,2013年6月19日,在经历了一个预览版之后微软正式发布了正式版TypeScript。当前最新版本为TypeScript3.8。 [2]
信息
开发公司
微软
类    型
编程语言
首版发布
2012年10月
正式版发布
2013年6月19日
性    质
JavaScript超集
外文名
TypeScript
最新版
3.8
typescript语言概况
TypeScript的作者是安德斯·海尔斯伯格,C#的首席架构师。 [3]  它是开源和跨平台的编程语言。它是JavaScript的一个超集,而且本质上向这个语言添加了可选的静态类型和基于类的面向对象编程。 [3-6]  TypeScript扩展了JavaScript的语法,所以任何现有的JavaScript程序可以运行在在TypeScript环境中。TypeScript是为大型应用的开发而设计,并且可以编译为JavaScript。 [7]  TypeScript 支持为已存在的 JavaScript 库添加类型信息的头文件,扩展了它对于流行的库如 jQuery,MongoDB,Node.js 和 D3.js 的好处。
收起全文
精华内容
参与话题
问答
  • 以通俗易懂的方式讲解 TypeScript 语法,帮您快速入门,将TypeScript应用到项目中! 本课程基于新版TypeScript录制,非常适合初学者的入门教学视频,全面的讲解TypeScript语法,让你少走弯路,直达技术前沿! ...
  • typescript ---- 基础篇

    千次阅读 多人点赞 2020-05-25 21:18:57
    全局安装typescript npm i -g typescript ts的文件后缀是以.ts来结尾的 浏览器无法解析ts文件的代码,需要编译成js文件的代码,执行命令:tsc index01.ts --转换成–>index01.js(手动编译) vscode配置自动...

    全局安装typescript npm i -g typescript

    • ts的文件后缀是以.ts来结尾的
    • 浏览器无法解析ts文件的代码,需要编译成js文件的代码,执行命令:tsc index01.ts --转换成–>index01.js(手动编译)
    • tsc --outFile ./js/demo.js demo.ts 编译到指定目录下

    vscode配置自动编译ts文(进入到根目录下)件:

    • tsc --init,生成tsconfig.json配置文件
    • 在tsconfig。json文件中找到outDir(输出至哪个文件夹,默认为根目录下,配置ts编译成js后需要存储的位置
    • 点击“ 终端 – 运行任务 – tsc-监视config.json ”

    HBuilder配置自动编译ts文件:

    • 点击“工具–插件安装“

    • 点击”浏览eclipse插件市场“

    • 弹框中找到输入框find,输入 “typescript”,找到typescript(有点慢),点击安装

    • 安装完成后重启编译器,点击“工具-选项-Typescript-Compiler",勾选上Compiler all TypeScript files on builder,点击确定

    • 右键点击项目根目录–配置–点击“enable TypeScript Hbuilder”

    TS新增了类型校验,写ts代码的时候必须指定类型

    var flag:number = 1;

    var flag:number = '1';错误写法

    TS的数据类型:(11种)

    • boolean number string array tuple(元祖类型) enum(枚举) any(任意类型) null undefined void never
    数组类型:ts中定义数组的方式有两种
    • 第一种:

      var arr:number[] = [1,2,3,11] 表示arr这个数组中的元素必须都是数字类型

    • 第二种:

      var arr:Array<number> = [1,2,3,11]

    元组类型:属于数组的一种
    • 元组类型指可以给数组中的每一个位置的元素指定类型,指定的类型与数组中的元素位置一一对应

      var arr:[number, string, boolean] = [12,"11",true] // 位置要与指定类型对应起来

    枚举类型:(常用于状态码)

    enum 枚举名 {标示符1,标示符2,标示符3}

    enum 枚举名 {‘标示符1’=1,‘标示符2’=2}

    console.log(枚举名.标示符x)

    如果不给标示符赋值,打印出来的就是标示符所在位置的角标,赋值则打印出标示符对应的值

    enum flag {'success' = 1, 'error' = 2}

    var f:flag = flag.error

    字符串类型

    var str:string='abcccd';

    any任意类型

    var obj:any = document.getElementById('box')

    obj.style.color='red'

    var num:any;
    var num1:number;
    var num2:number | undefined;
    console.log(num); // 输出undefined
    console.log(num1); // 报错
    console.log(num2); // 输出undefined
    

    null undefined类型
    var num:number | undefined // num的类型为number类型或者只定义了num这个变量,没有赋值。如果要赋值的话,只能是number类型或者值为undefined
    var num:undefined // num只申明了但是没有赋值,如果要赋值,只能赋undefined
    var num:null; // 表示num只能是null,不能给它赋值,或者说只能赋null给num
    
    
    void 类型

    typescript中void表示没有任何类型,一般用于定义方法的时候方法没有返回值

    function fn():void {} // 定义一个没有任何返回值的fn方法
    // 指定返回数组类型
    function fn():Array<any> {
        var obj:any = {name:'张三'};
        let arr:Array<any> = [];
        arr.push(obj);
        return arr;
    }
    console.log(fn())
    

    TS函数

    函数声明指定类型
    function fn():string {return String} // 定义了一个方法,该方法只能返回字符串
    function fn():Object {return Object} // 定义了一个方法,该方法只能返回一个对象
    var fn=function ():string {return string} // 定义了一个方法,该方法只能返回字符串
    function fn(name:string, age:number, sex:string):object {return object}
    // 指定传入的参数类型,返回指定类型的数据
    function backStr(name:string, age:number):string {
        let str = name + '----' +age;
        return str;
    }
    console.log(backStr('小明', 20));
    
    TS函数重载(函数同名,参数不同)
    
    
    匿名函数指定类型
    // 声明一个返回字符串的函数
    let strfn = function ():string {
        var str = 'qwe';
        return str;
    }
    // 声明一个返回对象的函数
    let objFn = function ():Object {
        let obj = {'name':'账单'};
        return obj;
    }
    // 声明一个返回数组的函数
    let arrFn = function ():Array<any> {
        let arr:Array<any> = [1, '2', {name: "张三"}];
        return arr;
    }
    console.log(strfn());
    console.log(objFn());
    console.log(arrFn());
    
    声明一个没有返回值的函数
    function noReturn():void {
      console.log('没有返回值');
    }
    console.log(noReturn);
    
    方法的可选参数
    // ES5中方法的形参和实参可以不一样,但是在TS中必须一样,如果不一样,则需要配置可选参数
    
    // ts中,如果在age后面不加?,则表示调用fn1函数的时候,name和age这两个参数都必须要传,如果在参数后面加一个?,则表示这个参数可传可不传,是可以选择的。
    ···注意:可选参数的位置必须放置在所有参数的最后面,不能放在必传参数的前面···
    function fn1(name:string, age?:number):object{ // age为可选参数
      reuturn {}
    }
    
    函数的默认参数
    // es5中是不能给函数指定默认参数的,但是在es6和ts中是可以给函数指定默认参数的
    function getInfo(name:string, age:number = 30):void {
        console.log(name+'---'+age)
    }
    // age不是可选参数,但是age有默认参数,如果不传age的话,则会默认使用age的默认值20
    getInfo('zhangsan', 100) // zhangsan---100
    getInfo('zhangsan') // zhangsan---30
    
    函数的剩余参数
    // 剩余参数(有点类似于agreement伪数组传参数)
    function fn3(...result:number[]):void {
      var sum=0;
      for (vat i=0;i<result.lenth;i++){
        sum+=result[i]
      }
    	console.log(sum)
    }
    // fn3(1,2,3)
    // fn3(1,2,3,4,5)
    function fn4(a:number,...res:number[]):Array<any> {
      var sum = a;
      return res;
    }
    fn4(1, 2, 3, 4, 5);
    
    函数重载
    // java中,函数重载指的是函数名一样,但是他们的参数不一样,这是会出现函数重载的情况
    // ts中的重载,是指通过为同一个函数提供多个函数类型定义来实现多种功能的目的
    // ts为了兼容es5/es6,重载的写法和java有区别
    /*
    es5中,出现同名的函数时,下面的函数会替换掉上面的函数
    function css(conf){}
    functioncss(conf:number, color:string){} // 会替换掉上面的css函数
    */
    // ts中的重载
    function info(name:string):string ;
    function info(age:number):string ;
    function info(str:any):any {
        if (typeof str == 'string') {
            return '姓名'+str;
        } else {
            return '年龄'+str
        }
    };
    
    console.log(info('张三'))
    console.log(info(20))
    
    // 参数重复时的写法
    function info(name:string):string;
    function info(name:string,age:number):string;
    function info(name:any, age?:any):any {
      if (age) {
        ...
        return ...
      } else {
        ...
        return ...
      }
    }
    
    箭头函数
    function fn() {}    ----------   () => {} this指向上下文
    

    TS中的类

    es5中定义类
    function Person() {
      this.name='张安';
      this.age=20;
      this.run=function() {
        console.log('在构造函数中定义方法')
      }
    }
    // 原型链上的属性和方法会被它的所有的实例所共享
    Person.prototype.sex="男"; // 在原型链上定义属性
    Person.prototype.work = function() {
      console.log('在原型链上定义函数')
    }
    
    // es5的静态方法(是直接写在Person这个对象上的,而不是写在Person的实例上的,实例是无法访问到对应的方法的)
    Person.staticFn = function () {
      console.log('我是静态方法')
    }
    
    var p = new Person();
    console.log(p.name)
    Person.staticFn()
    
    // es5中如何实现继承
    
    	// 父类
    function Parent() {
      this.name="parent";
      this.age=100;
      this.run = function () {
        console.log('跑的贼快')
      }
    }
    Parent.prototype.work = function () {
      console.log('一天要跑10个小时')
    }
    //方法一 改变this指向继承(对象冒充),可以继承父类的构造函数中的方法,但是无法继承原型链中的方法
    function Child() {
      Person.call(this); // this指向的是Person中的this
    }
    let child = new Child();
    child.run(); // 跑的贼快
    child.work(); // 会直接报错 child.work() is not a function
    
    // 方法二: 原型链继承
    	// 既会继承原型链上的方法和属性,也会继承构造函数中的方法和属性
    	// 原型链继承的缺陷:实例化子类的时候无法给父类传参,因此需要使用原型链加对象冒充组合继承
    function Child1() {}
    Child1.prototype=new Parent(); // 将Parent的实例挂载到Child1的原型上,达到继承Parent的原型链中的方法
    let child = new Child();
    child.run(); // 跑的贼快
    child.work(); // 一天要跑10个小时
    
    
    
    // 因此,一般如果要实现一个完整的继承,,是需要原型链继承和对象冒充继承组合使用
    function Parent1(name, age) {
      this.name=name;
      this.age=age;
      this.run=function() {....}
    }
    Parent1.prototype.work=function() {...}
    function Child2(name,age) {
      Parent1.call(this,name,age); // 对象冒充,this指向Parent1的this
    }
    Child2.prototype=Parent1.prototype; // 将Parent1的原型链对象挂载到Child2的原型链上
    let child = new Child('张三', 30);
    child.run();
    child.work(); 
    
    
    
    
    
    es6定义类结合ts语法
    class Person{
        name:string; // 类里面的属性
        constructor(name:string) { // 构造函数,在类进行实例化的时候调用
            this.name = name;
        }
        run ():void {
            console.log(this.name);
        }
    }
    let per:any = new Person('张三');
    per.run();
    
    ts中实现继承 extends super
    class Parent{
        name:string;
            constructor(name:string) {
            this.name=name;
        }
        run():void {
            console.log(this.name);
        }
        work():void {
          console.log('我是Parent');
        }
    }
    class Child extends Parent{ // extends表示继承Parent
        constructor(name:string) {
            super(name); // super表示调用父类的constructor函数,将值传入到父类的构造函数中
        }
        work():void {
          console.log('我是Child');
        }
    }
    let child = new Child('李四');
    child.run();
    child.work(); // 我是child
    
    // 如果子类中的方法和父类中的方法的函数名,参数都相同,则表示函数进行了重写
    
    类里面的修饰符 public protected private static
    public: 共有的     在类里面,类外面,子类都可以访问
    protected: 受保护的 	在类里面,子类里面可以访问,在类外面不能访问
    private: 私有的	在类里面可以访问,在子类,类外部都不能访问
    
    // 属性如果不加修饰符,默认为public
    
    • protected
    class Pub{
        protected name:string;
        constructor(name:string) {
            this.name=name;
        }
        run ():void {
            console.log(this.name);
        }
    }
    var p = new Pub('张三---asas')
    alert(p.name) // p.name能正常打印出来,是因为ts编译成了js,但是实际上在ts代码只中是会报错的,无法在类的外部访问protected的属性
    
    • private
    class Pub{
        protected name:string;
        constructor(name:string) {
            this.name=name;
        }
        run ():void {
            console.log(this.name);
        }
    }
    var p = new Pub('张三---asas')
    
    alert(p.name)// 会报错
    
    class Child extends Pub{
      constructor(name:string) {
        super(name);
      }
      run():void {
        console.log(this.name) // 此处会报错,private修饰的变量只能在 当前类 里面访问,其他的任何类都不能访问
      }
    }
    
    • 静态方法 关键字static
    class Person{
      name:string;
    	constructor(name:string) {
        this.name=name;
      }
    	static print() {
        // !!!注意,静态方法里面无法直接调用lei里面的属性,会报错
        // 如果需要调用,则需要将要调用的属性该成静态属性
        console.log(this.name)
      }
    }
    

    多态

    解释:父类定义一个方法,但是不实现,让继承他的子类去实现,每一个子类的表现形式都不一样

    多态属于继承的一种

    class Animal{
        name:string;
        constructor(name:string) {
          this.name=name;
        }
        eat():void {} // 父类定义一个方法,但是不去实现它,由子类去实现
    }
    class Dog extends Animal{
        constructor(name:string) {
        super(name);
        }
        eat():void {
        console.log(`${this.name}吃肉`)
        }
    }
    class Cat extends Animal{
        constructor(name:string) {
        super(name);
        }
        eat():void {
        console.log(`${this.name}吃鱼`)
        }
    }
    let dog = new Dog('狗');
    dog.eat();
    let cat = new Cat('猫');
    cat.eat();
    

    ts中的抽象类 abstract

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

    用abstract关键字定义抽象类和抽象方法,抽象类中的抽象方法不包含具体实现并且必须在派生类(子类)中实现

    // abstract抽象方法  只能  放在抽象类里面 
    // 抽象类和抽象方法用来  定义标准
    // 比如,要求Animal的所有的  子类  必须包含eat这个方法
    abstract class Animal{
      name:string;
    	constructor(name:string) {
        this.name=name;
      }
    // 划重点
      abstract eat():any;
    }
    // 抽象类的子类必须实现抽象父类中的抽象方法
    class Dog extends Animal{
      constructor(name:string) {
        super(name);
      }
      eat():any {
        console.log(`${this.name}吃肉`)
      }
    }
    class Cat extends Animal{
      constructor(name:string) {
        super(name);
      }
      eat():any {
        console.log(`${this.name}吃鱼`)
      }
    }
    
    多态与抽象类的区别

    多态—子类可以实现父类定义的方法,也可以不实现父类定义的方法

    抽象类—父类中定义的抽象方法,其子类 必须 要实现

    接口

    接口 ---- interface关键词

    行为和动作的规范,对批量方法进行约束

    // 接口在ts中主要是用来定义 对象 的类型
    // 接口的写法
    interface methods1 {
      firstName:string; // 注意:必须要使用;来结尾,而不是使用,结尾
      secondName:string;
      gender?:string; // 接口的可选属性,可传可不传
    }
    // 表示该函数传入的参数必须要满足接口methods,也就是methods1中定义的变量必须要都包含才行,否则编译的时候会报错
    function interFn1(params:methods1):void {
      
    }
    // ⚠️注意:在调用interFn1函数的时候,如果这样传参的话
      interFn1({
        firstName: '张',
        secondName: '三',
        age: 20 // 这样穿参的话age回报错,因为在接口中之定义了两个字段,没有定义age这个字段
      })
    
    定义函数类型的接口
    对方法传入的 参数 以及 返回值 进行约束
    interface interFn {
      (name:string, age:number):string;
    }
    let md:interFn = function (name:string, age:number):string {
       return name+age;
    }
    alert(md('张三', 20))
    
    可索引接口 ----- 对数组/对象的约束(不常用 )
    // 接口对数组的约束
    interface _array {
      [index:number]:string // 数组的约束,数组元素只能是字符串
    }
    let arr:_array = ['aaa', 'bbb']; //接口对数组进行了一个约束,只能是字符串
    console.log(arr[0]); // 'aaa'
    
    // 接口对对象的约束
    interface userObj {
      [index:string]:string
    }
    let obj:userObj = {name: '张三'} // 当切仅当只能传一个key_value
    
    类类型接口 (对类的约束 和抽象类有点相似) ----- ⚠️经常使用
    // 定义接口
    
    // 接口中定义的属性和函数,在类中都必须要定义,否则会报错,但是
    // 在接口中定义的函数的参数,在实现接口的类中可以不定义
    interface Ani {
        name:string;
        eat(food:string):void;
    }
    
    class dd implements Ani {
        name:string
        constructor(name:string) {
            this.name = name
        }
    		
        eat(food:string):string {
            console.log(this.name+"吃"+ food +",多管闲事!")
            return this.name;
        }
    }
    let d = new dd('小黑');
    console.log(d.eat('老鼠')); // 小黑吃老鼠,多管闲事
    
    class cc implements Ani {
        name:string
        constructor(name:string) {
            this.name = name
        }
        eat() {
            console.log(this.name+"吃鱼")
        }
    }
    
    let c = new cc('花花');
    c.eat(); // 花花吃鱼
    
    接口的扩展 (接口可以继承接口)
    interface Animal {
        eat():void;
    }
    interface Person extends Animal {
        work():void;
    }
    class Progrommer {
      name:string
      constructor(name:string) {
        this.name=name
      }
    	coding():void {
        console.log('写代码')
      }
    }
    class Web extends Progrommer implements Person {
        constructor(name:string) {
            super(name);
        }
        eat() {
            console.log(this.name + '吃饭')
        }
        work() {
            console.log(this.name + '上班挣钱')
        }
    }
    let web = new Web('小明');
    web.eat();
    web.work();
    web.coding();
    

    泛型

    ​ 解决 类 接口 方法 的复用性以及对不特定数据类型的支持

    泛型的定义和泛型 函数
    // 定义泛型的时候,使用<>来定义,<>中的变量可以是任意的,但是一般都是用T表示,这个T表示的传入的类型
    function fx<T>(value:T):T {
        return value;
    }
    console.log(fx<number>(123)); // 123
    console.log(fx<string>('123')); // '123'
    
    泛型 — 定义类
    // 泛型可以进行类型校验,如果使用any,则默认放弃了类型校验
    class minClass<T> {
        protected lists:T[]=[];
        constructor() {}
        add(value:T):void {
          this.lists.push(value);
        }
        minNum():T {
        	let minValue = this.lists[0];
        	this.lists.forEach(item => {
            if (minValue > item) minValue = item;
        	})
          return minValue;
        }
    }
    let min = new minClass<number>(); // 实例化对象,并且指定了T的类型是number类型
    min.add(20);
    min.add(10);
    min.add(55);
    min.add(200);
    console.log(min.minNum()); // 10
    
    let min1 = new minClass<string>(); // 实例化对象,并且指定了T的类型是string类型
    min1.add('a');
    min1.add('c');
    min1.add('f');
    min1.add('g');
    console.log(min1.minNum()); // 'a'
    
    泛型 接口
    // 泛型函数接口
    // 方法一:
    interface configfx1 {
        <T>(value:T):T;
    }
    let getValue1:configfx1 = function<T>(value:T):T {
        return value;
    }
    console.log(getValue1<number>(10086)); // 10086
    
    // 方法二
    interface configfx2<T> {
        (value:T):T;
    }
    function getValue2<T>(value:T):T {
        return value;
    }
    let getDate:configfx2<string> = getValue2;
    let val = getDate('12345')
    console.log(val) // '12345'
    
    泛型类 – 把类作为参数类型
    class User {
        username:string | undefined;
        password:string | undefined;
    }
    class MysqlDb<T> {
        add(user:T):boolean {
            console.log(user)
            return true;
        }
    }
    let u = new User();
    u.username = '张三';
    u.password = '13143344';
    
    let m = new MysqlDb<User>(); // 将User类作为校验的参数
    m.add(u); // {username:'张三',password:'13143344'}
    

    约束规范--定义接口 代码重用--泛型

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

    泛型: 解决类 接口 方法的复用性

    注意:如果要实现一个泛型接口,那么实现这个接口的类也必须是泛型类

    模块

    注意:在ts1.5中术语发生了变化,“内部模块"被称为"命名空间”,“外部模块"被称为"模块”,模块在其自身的作用域里面执行,而不是在全局作用域里面执行。除非导出它!

    模块导出的方法
    export导出
    • 使用export导出,可以导出常量 函数 文件 模块 对象
    • 在使用import引入的时候,需要加 {}才能正常引入
    • export不能直接导出一个 变量 或者具体的一个 ,它导出的是一个 表达式 或者 语句 或者直接导出 {}
      • 错误写法
      • let str='ascv'; export str;
      • function fn() {}; export fn;
      • 正确写法
      • export let str = 'ascv';
      • export function fn() {};
      • export {str, arr ...}

    暴露函数和变量

    // a.js中定义
    // export暴露方法一:直接暴露出去
    export var str = 'xxx';
    export function fn() {
      console.log('暴露函数');
    }
    
    
    // export暴露方法二:集中暴露
    var str = 'yyyyy';
    function ff() {};
    export {str, ff}; // import导入方法不变
    
    
    
    // 在b.js文件中导入
    
    import {str, fn} from 'a'; // ⚠️:不加.js这个后缀
    // str as s 表示用s这个变量来替换掉str这个变量,他们之间的关系是 str === s(全等)
    import {str as s, fn as f} from 'a';
    // 调用函数时
    fn() / f() // 这两种写法都可以
    

    暴露对象

    // a.js
    let obj = {}
    let arr = []
    export {obj, arr};
    
    // b.js
    import {obj, arr} from 'a'; // 变量名要相同
    

    暴露class

    //a.js 
    export class Test{...}
    
    /*
    * 这种暴露方式是错的
    * class Test{}
    * export Test;
    */
    
    // b.js
    import { Test } from 'a.js'
    
    export default导出
    • 在用法上跟export导出几乎一致,没有什么区别,导出class的时候需要注意一下

    • 一个模块只能导出 一次,可以是常量 函数 文件 **模块 ** 对象

    • 在使用import引入的时候,不需要加{},可以直接用 任意 变量接收

    导出class

    // a.js
    // 方法一
    export default class Test2{
      constructor() {}
    }
    // 方法二:
    class Test1{...}
    export default Test1;
    
    
    // b.js
    import TT from 'a';
    
    

    命名空间 namespace

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

    命名空间: 内部模块,主要用于组织代码,避免命名冲突

    模块: ts的外部模块的简称,侧重代码的复用(公用的代码抽离出来,放置在一个文件中),一个模块里可能会有多个命名空间

    总结:命名空间就是指,同样名字的命名,在两个不同的namesapce里面是不会存在任何冲突的,实现的功能也可能是不一一样的

    class pub{
        name:string | undefined;
        constructor(name:string) {
            this.name=name;
        }
        eat():void{};
    }
    interface Animal{
        name:string | undefined;
        gender:string |undefined;
        age:number | undefined;
    }
    namespace A{
      // 将命名空间当成一个模块暴露出来
        export class Dog extends pub implements Animal{
            name:string | undefined;
            gender:string |undefined;
            age:number | undefined;
            constructor(name:string, gender:string, age:number) {
                super(name);
                this.name = name;
            }
            eat():void {
                console.log(this.name+"在吃肉哦!!!!!")
            }
        }
    }
    let test1 = new A.Dog('狼狗', '公的', 20);
    test1.eat();
    namespace B{
        export class Dog extends pub implements Animal{
            name:string | undefined;
            gender:string |undefined;
            age:number | undefined;
            constructor(name:string, gender:string, age:number) {
                super(name);
                this.name = name;
            }
            eat():void {
                console.log(this.name+"混的很惨,在吃空气!!!!!")
            }
        }
    }
    let test2 = new B.Dog('tony', '男', 20);
    test2.eat();
    

    装饰器

    • 是一种特殊类型的声明,它能够被附加到类声明,方法,属性或参数上,可以修改类的行为
    • 通俗的讲装饰器就是一个方法,可以注入到类,方法,属性参数上来扩展类,属性,方法,参数的功能
    • 常见的装饰器:类装饰器、方法装饰器、属性装饰器、参数装饰器
    • 装饰器的写法:普通装饰器(无法传参)、装饰器工厂(可以传参)
    • 是ES7的标准特性之一
    类装饰器 ---- 普通装饰器(无法传参)
    • 类装饰器在类声明之前被声明(紧靠着类声明)。类装饰器应用于类构造函数,可以用来监视、修改或替换类定义
    • 在不修改类的前提条件下扩展类的属性和方法
    function logClass(params:any) {
        console.log(params); // params就是当前类Log,只是是以函数的形式呈现出来的 function Log() {...}
        params.prototype.name="装饰器";
        params.prototype.run=function () {
            console.log('run_装饰器');
        }
    }
    @logClass // logClass函数是Log类的装饰器,注意⚠️:@logClass后面不要加;
    class Log{
        constructor() {}
        eat() {}
    }
    let log:any = new Log();
    console.log(log.name); // 输出  装饰器
    log.run(); // 输出  run_装饰器
    
    类装饰器 ---- 工厂装饰器(可以传参)

    TS项目使用注意事项:

    ref:

    ​ ts中是无法直接获取ref绑定的dom节点的,如果需要获取

    <div ref="dv"></div>
    <header ref="head"></header>
    // js中获取ref绑定的节点
    <script>
    import Header from '......'
    	
      componemts: header
      mounted() {
        console.log(this.$refs.dv)
      }
      // ts中获取ref绑定的dom节点
      mounted():void {
        // 如果ref绑定的是一个dom元素节点
        console.log(this.$refs.dv as Element)
        // ⚠️:as后面的header是引入后组件的名称
        // 如果ref绑定的是一个组件
        console.log(this.$refs.head as header)
      }
    </script>
    
    vue-property-decorator 里面提供的装饰器有: @Emit、@Inject、@Model、@Prop、@Provide、@Watch、@Component
    在组件中定义装饰器的时候,需要有@component这个装饰器,否则可能会报错:Property or method XXX is not defined on ths instance but referenced ...
    

    生命周期的使用

    import { Component, Vue} from 'vue-property-decorator';
    
    @Component({})
    export default class AAA extend Vue{
      created() {}
      beforeMuont() {}
      mounted() {}
    }
    

    注册组件

    import { Component, Vue} from 'vue-property-decorator';
    import Aside from '......';
    import Tabbar from '......';
    
    @Component({
      components: {
        Aside,
        Tabbbar
      }
    })
    

    普通变量的使用

    // 普通变量直接定义在class里面就行
    import { Vue } from 'vue-property-decorator';
    
    export default class Demo {
      str:string | undefined;
    	arr:any[] | undefined;
    }
    

    watch的使用

    ...
    export default class Demo {
    	name:string = 'zf';
      // @watch('需要监听的变量')
      @watch('name')
    	watchName(newVal:string, oldVal:string):void {
        ......
      }
    }
    

    Props的使用

    export default class Demo {
      @prop
      str:string | undefined;
    	num!:number; // 这种写法也可以,等价于 num:number | undefined
    	arr:any[] | undefined;
    	
    }
    

    computed使用

    // 计算属性 computed
    export default class Demo {
    	name:string = 'zf';
      get Compile () {
        return this.name;
      }
    }
    

    !!!!!
    gitDEMO地址: https://github.com/zFei-runner/typescript_demo.git(部分地方不是很准确,有误!!!)

    展开全文
  • TypeScript --- 快速学习

    千次阅读 2019-06-10 01:58:10
    1. typescript是什么Typescript是由微软开发的一款开源的编程语言Typescript是Javascript的超集,遵循最新的ES5/ES6规范。TypeScript扩展了Javascript语法TypeScript更像后端Java、C#这样的面向对象语言可以让JS开发...

    1. typescript是什么

    • Typescript是由微软开发的一款开源的编程语言
    • Typescript是Javascript的超集,遵循最新的ES5/ES6规范。TypeScript扩展了Javascript语法
    • TypeScript更像后端Java、C#这样的面向对象语言可以让JS开发大型企业应用
    • 越来越多的项目是基于TS的,比如VSCode、Angular6、Vue3、React16
    • TS提供的类型系统可以帮助我们在写代码的时候提供更丰富的语法提示
    • 在创建前的编译阶段经过类型系统的检查,就可以避免很多线上的错误

    2. TypeScript安装和编译

    2.1 安装

    cnpm i typescript -g
    复制代码
    tsc helloworld.ts
    复制代码

    2.2 Vscode+TypeScript

    2.2.1 生成配置文件

    tsc --init
    复制代码
    {
      "compilerOptions": {
        /* Basic Options */
        "target": "es5",                          /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. 指定ECMAScript的目标版本*/
        "module": "commonjs",                     /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. 指定模块代码的生成方式*/
        // "lib": [],                             /* Specify library files to be included in the compilation. 指定编译的时候用来包含的编译文件*/
        // "allowJs": true,                       /* Allow javascript files to be compiled. 允许编译JS文件*/
        // "checkJs": true,                       /* Report errors in .js files. 在JS中包括错误*/
        // "jsx": "preserve",                     /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. 指定JSX代码的生成方式 是保留还是react-native或者react*/
        // "declaration": true,                   /* Generates corresponding '.d.ts' file.生成相应的类型声明文件 */
        // "declarationMap": true,                /* Generates a sourcemap for each corresponding '.d.ts' file. 为每个类型声明文件生成相应的sourcemap*/
        // "sourceMap": true,                     /* Generates corresponding '.map' file. 生成对应的map文件 */
        // "outFile": "./",                       /* Concatenate and emit output to single file. 合并并且把编译后的内容输出 到一个文件里*/
        // "outDir": "./",                        /* Redirect output structure to the directory.按原始结构输出到目标目录 */
        // "rootDir": "./",                       /* Specify the root directory of input files. Use to control the output directory structure with --outDir. 指定输入文件的根目录,用--outDir来控制输出的目录结构*/
        // "composite": true,                     /* Enable project compilation 启用项目编译*/
        // "removeComments": true,                /* Do not emit comments to output. 移除注释*/
        // "noEmit": true,                        /* Do not emit outputs. 不要输出*/
        // "importHelpers": true,                 /* Import emit helpers from 'tslib'. */
        // "downlevelIteration": true,            /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. 当目标是ES5或ES3的时候提供对for-of、扩展运算符和解构赋值中对于迭代器的完整支持*/
        // "isolatedModules": true,               /* Transpile each file as a separate module (similar to 'ts.transpileModule').r把每一个文件转译成一个单独的模块 */
    
        /* Strict Type-Checking Options */
        //"strict": true,                           /* Enable all strict type-checking options. 启用完全的严格类型检查 */
        // "noImplicitAny": true,                 /* Raise error on expressions and declarations with an implied 'any' type. 不能使用隐式的any类型*/
        // "strictNullChecks": true,              /* Enable strict null checks. 启用严格的NULL检查*/
        // "strictFunctionTypes": true,           /* Enable strict checking of function types. 启用严格的函数类型检查*/
        // "strictBindCallApply": true,           /* Enable strict 'bind', 'call', and 'apply' methods on functions.启用函数上严格的bind call 和apply方法 */
        // "strictPropertyInitialization": true,  /* Enable strict checking of property initialization in classes. 启用类上初始化属性检查*/
        // "noImplicitThis": true,                /* Raise error on 'this' expressions with an implied 'any' type.在默认的any中调用 this表达式报错 */
        // "alwaysStrict": true,                  /* Parse in strict mode and emit "use strict" for each source file. 在严格模式下解析并且向每个源文件中发射use strict*/
    
        /* Additional Checks */
        // "noUnusedLocals": true,                /* Report errors on unused locals. 有未使用到的本地变量时报错 */
        // "noUnusedParameters": true,            /* Report errors on unused parameters. 有未使用到的参数时报错*/
        // "noImplicitReturns": true,             /* Report error when not all code paths in function return a value. 当不是所有的代码路径都有返回值的时候报错*/
        // "noFallthroughCasesInSwitch": true,    /* Report errors for fallthrough cases in switch statement. 在switch表达式中没有替代的case会报错 */
    
        /* Module Resolution Options */
        // "moduleResolution": "node",            /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). 指定模块的解析策略 node classic*/
        // "baseUrl": "./",                       /* Base directory to resolve non-absolute module names. 在解析非绝对路径模块名的时候的基准路径*/
        // "paths": {},                           /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. 一些路径的集合*/
        // "rootDirs": [],                        /* List of root folders whose combined content represents the structure of the project at runtime. 根目录的列表,在运行时用来合并内容*/
        // "typeRoots": [],                       /* List of folders to include type definitions from. 用来包含类型声明的文件夹列表*/
        // "types": [],                           /* Type declaration files to be included in compilation.在编译的时候被包含的类型声明 */
        // "allowSyntheticDefaultImports": true,  /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking.当没有默认导出的时候允许默认导入,这个在代码执行的时候没有作用,只是在类型检查的时候生效 */
        //"esModuleInterop": true                   /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'.*/
        // "preserveSymlinks": true,              /* Do not resolve the real path of symlinks.不要symlinks解析的真正路径 */
    
        /* Source Map Options */
        // "sourceRoot": "",                      /* Specify the location where debugger should locate TypeScript files instead of source locations. 指定ts文件位置*/
        // "mapRoot": "",                         /* Specify the location where debugger should locate map files instead of generated locations. 指定 map文件存放的位置 */
        // "inlineSourceMap": true,               /* Emit a single file with source maps instead of having a separate file. 源文件和sourcemap 文件在同一文件中,而不是把map文件放在一个单独的文件里*/
        // "inlineSources": true,                 /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. 源文件和sourcemap 文件在同一文件中*/
    
        /* Experimental Options */
        // "experimentalDecorators": true,        /* Enables experimental support for ES7 decorators. 启动装饰器*/
        // "emitDecoratorMetadata": true,         /* Enables experimental support for emitting type metadata for decorators. */
      }
    }
    复制代码

    2.2.2 执行编译

    tsc 
    复制代码

    2.2.3 vscode运行

    • Terminal->Run Task-> tsc:build 编译
    • Terminal->Run Task-> tsc:watch 编译并监听

    2.2.4 npm scripts

    • npm run 实际上是调用本地的 Shell 来执行对应的 script value,所以理论上能兼容所有 bash 命令
    • Shell 在类 Unix 系统上是 /bin/sh,在 Windows 上是 cmd.exe

    2.2.5 npm scripts 的 PATH

    • npm run 会预置 PATH,对应包下的 node_modules/.bin 目录

    3. 数据类型

    3.1 布尔类型(boolean)

    let married: boolean=false;
    复制代码

    3.2 数字类型(number)

    let age: number=10;
    复制代码

    3.3 字符串类型(string)

    let firstname: string='zfpx';
    复制代码

    3.4 数组类型(array)

    let arr2: number[]=[4,5,6];
    let arr3: Array<number>=[7,8,9];
    复制代码

    3.5 元组类型(tuple)

    • 在 TypeScript 的基础类型中,元组( Tuple )表示一个已知数量类型的数组
    let zhufeng:[string,number] = ['zhufeng',5];
    zhufeng[0].length;
    zhufeng[1].toFixed(2);
    复制代码
    元组数组
    每一项可以是不同的类型每一项都是同一种类型
    有预定义的长度没有长度限制
    用于表示一个固定的结构用于表示一个列表
    const animal:[string,number,boolean] = ['zhufeng',10,true];
    复制代码

    3.6 枚举类型(enum)

    • 事先考虑某一个变量的所有的可能的值,尽量用自然语言中的单词表示它的每一个值
    • 比如性别、月份、星期、颜色、单位、学历

    3.6.1 普通枚举

    enum Gender{
        GIRL,
        BOY
    }
    console.log(`李雷是${Gender.BOY}`);
    console.log(`韩梅梅是${Gender.GIRL}`);
    
    enum Week{
        MONDAY=1,
        TUESDAY=2
    }
    console.log(`今天是星期${Week.MONDAY}`);
    复制代码

    3.6.2 常数枚举

    • 常数枚举与普通枚举的区别是,它会在编译阶段被删除,并且不能包含计算成员。
    • 假如包含了计算成员,则会在编译阶段报错
    const enum Colors {
        Red,
        Yellow,
        Blue
    }
    
    let myColors = [Colors.Red, Colors.Yellow, Colors.Blue];
    复制代码
    const enum Color {Red, Yellow, Blue = "blue".length};
    复制代码

    3.7 任意类型(any)

    • any就是可以赋值给任意类型
    • 第三方库没有提供类型文件时可以使用any
    • 类型转换遇到困难时
    • 数据结构太复杂难以定义
    let root:any=document.getElementById('root');
    root.style.color='red';
    复制代码
    let root:(HTMLElement|null)=document.getElementById('root');
    root!.style.color='red';//非空断言操作符
    复制代码

    3.8 null 和 undefined

    • null 和 undefined 是其它类型的子类型,可以赋值给其它类型,如数字类型,此时,赋值后的类型会变成 null 或 undefined
    • strictNullChecks 参数用于新的严格空检查模式,在严格空检查模式下, null 和 undefined 值都不属于任何一个类型,它们只能赋值给自己这种类型或者 any
    let x: number;
    x = 1;
    x = undefined;    
    x = null;   
    
    let y: number | null | undefined;
    y = 1;
    y = undefined;   
    y = null;   
    复制代码

    3.9 void 类型

    • void 表示没有任何类型
    • 当一个函数没有返回值时,TS 会认为它的返回值是 void 类型。
    function greeting(name:string):void {
        console.log('hello',name);
        //当我们声明一个变量类型是 void 的时候,它的非严格模式(strictNullChecks:false)下仅可以被赋值为 null 和 undefined
        //严格模式(strictNullChecks:true)下只能返回undefined
        //return null;
        //return undefined;
    }
    复制代码

    3.10 never类型

    never是其它类型(null undefined)的子类型,代表不会出现的值

    3.10.1

    • 作为不会返回( return )的函数的返回值类型
    // 返回never的函数 必须存在 无法达到( unreachable ) 的终点
    function error(message: string): never {
        throw new Error(message);
    }
    let result1 = error('hello');
    // 由类型推论得到返回值为 never
    function fail() {
        return error("Something failed");
    }
    let result = fail();
    
    // 返回never的函数 必须存在 无法达到( unreachable ) 的终点
    function infiniteLoop(): never {
        while (true) {}
    }
    复制代码

    3.10.2 strictNullChecks

    • 在 TS 中, null 和 undefined 是任何类型的有效值,所以无法正确地检测它们是否被错误地使用。于是 TS 引入了 --strictNullChecks 这一种检查模式
    • 由于引入了 --strictNullChecks ,在这一模式下,null 和 undefined 能被检测到。所以 TS 需要一种新的底部类型( bottom type )。所以就引入了 never。
    // Compiled with --strictNullChecks
    function fn(x: number | string) {
      if (typeof x === 'number') {
        // x: number 类型
      } else if (typeof x === 'string') {
        // x: string 类型
      } else {
        // x: never 类型
        // --strictNullChecks 模式下,这里的代码将不会被执行,x 无法被观察
      }
    }
    复制代码

    3.10.3 never 和 void 的区别

    • void 可以被赋值为 null 和 undefined的类型。 never 则是一个不包含值的类型。
    • 拥有 void 返回值类型的函数能正常运行。拥有 never 返回值类型的函数无法正常返回,无法终止,或会抛出异常。

    3.11 类型推论

    • 是指编程语言中能够自动推导出值的类型的能力,它是一些强静态类型语言中出现的特性
    • 定义时未赋值就会推论成any类型
    • 如果定义的时候就赋值就能利用到类型推论
    let username2;
    username2 = 10;
    username2 = 'zhufeng';
    username2 = null;
    复制代码

    3.12 包装对象(Wrapper Object)

    • JavaScript 的类型分为两种:原始数据类型(Primitive data types)和对象类型(Object types)。
    • 所有的原始数据类型都没有属性(property)
    • 原始数据类型
      • 布尔值
      • 数值
      • 字符串
      • null
      • undefined
      • Symbol
    let name = 'zhufeng';
    console.log(name.toUpperCase());
    
    console.log((new String('zhufeng')).toUpperCase());
    复制代码
    • 当调用基本数据类型方法的时候,JavaScript 会在原始数据类型和对象类型之间做一个迅速的强制性切换
    let isOK: boolean = true; // 编译通过
    let isOK: boolean = Boolean(1) // 编译通过
    let isOK: boolean = new Boolean(1); // 编译失败   期望的 isOK 是一个原始数据类型
    复制代码

    3.13 联合类型

    • 联合类型(Union Types)表示取值可以为多种类型中的一种
    • 未赋值时联合类型上只能访问两个类型共有的属性和方法
    let name: string | number;
    console.log(name.toString());
    name = 3;
    console.log(name.toFixed(2));
    name = 'zhufeng';
    console.log(name.length);
    
    export {};
    复制代码

    3.14 类型断言

    • 类型断言可以将一个联合类型的变量,指定为一个更加具体的类型
    • 不能将联合类型断言为不存在的类型
    let name: string | number;
    console.log((name as string).length);
    console.log((name as number).toFixed(2));
    console.log((name as boolean));
    复制代码

    3.15 字面量类型

    • 可以把字符串、数字、布尔值字面量组成一个联合类型
    type ZType = 1 | 'One'|true;
    let t1:ZType = 1;
    let t2:ZType = 'One';
    let t3:ZType = true;
    复制代码

    3.16 字符串字面量 vs 联合类型

    • 字符串字面量类型用来约束取值只能是某几个字符串中的一个, 联合类型(Union Types)表示取值可以为多种类型中的一种
    • 字符串字面量 限定了使用该字面量的地方仅接受特定的值,联合类型 对于值并没有限定,仅仅限定值的类型需要保持一致

    4. 函数

    4.1 函数的定义

    • 可以指定参数的类型和返回值的类型
    function hello(name:string):void {
        console.log('hello',name);
    }
    hello('zfpx');
    复制代码

    4.2 函数表达式

    • 定义函数类型
    type GetUsernameFunction = (x:string,y:string)=>string;
    let getUsername:GetUsernameFunction = function(firstName,lastName){
      return firstName + lastName;
    }
    复制代码

    4.3 没有返回值

    let hello2 = function (name:string):void {
        console.log('hello2',name);
        return undefined;
    }
    hello2('zfpx');
    复制代码

    4.4 可选参数

    在TS中函数的形参和实参必须一样,不一样就要配置可选参数,而且必须是最后一个参数

    function print(name:string,age?:number):void {
        console.log(name,age);
    }
    print('zfpx');
    复制代码

    4.5 默认参数

    function ajax(url:string,method:string='GET') {
        console.log(url,method);
    }
    ajax('/users');
    复制代码

    4.6 剩余参数

    function sum(...numbers:number[]) {
        return numbers.reduce((val,item)=>val+=item,0);
    }
    console.log(sum(1,2,3));
    复制代码

    4.7 函数重载

    • 在Java中的重载,指的是两个或者两个以上的同名函数,参数不一样
    • 在TypeScript中,表现为给同一个函数提供多个函数类型定义
    let obj: any={};
    function attr(val: string): void;
    function attr(val: number): void;
    function attr(val:any):void {
        if (typeof val === 'string') {
            obj.name=val;
        } else {
            obj.age=val;
        }
    }
    attr('zfpx');
    attr(9);
    attr(true);
    console.log(obj);
    复制代码

    5. 类

    5.1 如何定义类

    • "strictPropertyInitialization": true /
      启用类属性初始化的严格检查
      /
    • name!:string
    class Person{
        name:string;
        getName():void{
            console.log(this.name);
        }
    }
    let p1 = new Person();
    p1.name = 'zhufeng';
    p1.getName();
    复制代码

    5.2 存取器

    • 在 TypeScript 中,我们可以通过存取器来改变一个类中属性的读取和赋值行为
    • 构造函数
      • 主要用于初始化类的成员变量属性
      • 类的对象创建时自动调用执行
      • 没有返回值
    class User {
        myname:string;
        constructor(myname: string) {
            this.myname = myname;
        }
        get name() {
            return this.myname;
        }
        set name(value) {
            this.myname = value;
        }
    }
    
    let user = new User('zhufeng');
    user.name = 'jiagou'; 
    console.log(user.name); 
    复制代码
    "use strict";
    var User = /** @class */ (function () {
        function User(myname) {
            this.myname = myname;
        }
        Object.defineProperty(User.prototype, "name", {
            get: function () {
                return this.myname;
            },
            set: function (value) {
                this.myname = value;
            },
            enumerable: true,
            configurable: true
        });
        return User;
    }());
    var user = new User('zhufeng');
    user.name = 'jiagou';
    console.log(user.name);
    复制代码

    5.3 参数属性

    class User {
        constructor(public myname: string) {}
        get name() {
            return this.myname;
        }
        set name(value) {
            this.myname = value;
        }
    }
    
    let user = new User('zhufeng');
    console.log(user.name); 
    user.name = 'jiagou'; 
    console.log(user.name);
    复制代码

    5.4 readonly

    • readonly修饰的变量只能在构造函数中初始化
    • 在 TypeScript 中,const 是常量标志符,其值不能被重新分配
    • TypeScript 的类型系统同样也允许将 interface、type、 class 上的属性标识为 readonly
    • readonly 实际上只是在编译阶段进行代码检查。而 const 则会在运行时检查(在支持 const 语法的 JavaScript 运行时环境中)
    class Animal {
        public readonly name: string
        constructor(name:string) {
            this.name = name;
        }
        changeName(name:string){
            this.name = name;
        }
    }
    
    let a = new Animal('zhufeng');
    a.changeName('jiagou');
    复制代码

    5.5 继承

    • 子类继承父类后子类的实例就拥有了父类中的属性和方法,可以增强代码的可复用性
    • 将子类公用的方法抽象出来放在父类中,自己的特殊逻辑放在子类中重写父类的逻辑
    • super可以调用父类上的方法和属性
    class Person {
        name: string;//定义实例的属性,默认省略public修饰符
        age: number;
        constructor(name:string,age:number) {//构造函数
            this.name=name;
            this.age=age;
        }
        getName():string {
            return this.name;
        }
        setName(name:string): void{
            this.name=name;
        }
    }
    class Student extends Person{
        no: number;
        constructor(name:string,age:number,no:number) {
            super(name,age);
            this.no=no;
        }
        getNo():number {
            return this.no;
        }
    }
    let s1=new Student('zfpx',10,1);
    console.log(s1);
    
    复制代码

    5.6 类里面的修饰符

    class Father {
        public name: string;  //类里面 子类 其它任何地方外边都可以访问
        protected age: number; //类里面 子类 都可以访问,其它任何地方不能访问
        private money: number; //类里面可以访问, 子类和其它任何地方都不可以访问
        constructor(name:string,age:number,money:number) {//构造函数
            this.name=name;
            this.age=age;
            this.money=money;
        }
        getName():string {
            return this.name;
        }
        setName(name:string): void{
            this.name=name;
        }
    }
    class Child extends Father{
        constructor(name:string,age:number,money:number) {
            super(name,age,money);
        }
        desc() {
            console.log(`${this.name} ${this.age} ${this.money}`);
        }
    }
    
    let child = new Child('zfpx',10,1000);
    console.log(child.name);
    console.log(child.age);
    console.log(child.money);
    复制代码

    5.7 静态属性 静态方法

    class Father {
        static className='Father';
        static getClassName() {
            return Father.className;
        }
        public name: string;
        constructor(name:string) {//构造函数
            this.name=name;
        }
    
    }
    console.log(Father.className);
    console.log(Father.getClassName());
    复制代码

    5.8 抽象类

    • 抽象描述一种抽象的概念,无法被实例化,只能被继承
    • 无法创建抽象类的实例
    • 抽象方法不能在抽象类中实现,只能在抽象类的具体子类中实现,而且必须实现
    abstract class Animal {
        name!:string;
        abstract speak():void;
    }
    class Cat extends Animal{
        speak(){
            console.log('喵喵喵');
        }
    }
    let animal = new Animal();//Cannot create an instance of an abstract class
    animal.speak();
    let cat = new Cat();
    cat.speak();
    复制代码
    访问控制修饰符private protected public
    只读属性readonly
    静态属性static
    抽象类、抽象方法abstract

    5.9 抽象类 vs 接口

    • 不同类之间公有的属性或方法,可以抽象成一个接口(Interfaces)
    • 而抽象类是供其他类继承的基类,抽象类不允许被实例化。抽象类中的抽象方法必须在子类中被实现
    • 抽象类本质是一个无法被实例化的类,其中能够实现方法和初始化属性,而接口仅能够用于描述,既不提供方法的实现,也不为属性进行初始化
    • 一个类可以继承一个类或抽象类,但可以实现(implements)多个接口
    • 抽象类也可以实现接口
    abstract class Animal{
        name:string;
        constructor(name:string){
          this.name = name;
        }
        abstract speak():void;
      }
      interface Flying{
          fly():void
      }
    class Duck extends Animal implements Flying{
          speak(){
              console.log('汪汪汪');
          }
          fly(){
              console.log('我会飞');
          }
    }
    let duck = new Duck('zhufeng');
    duck.speak();
    duck.fly();
    复制代码

    5.10 抽象方法

    • 抽象类和方法不包含具体实现,必须在子类中实现
    • 抽象方法只能出现在抽象类中
    • 子类可以对抽象类进行不同的实现
    abstract class Animal{
        abstract speak():void;
    }
    class Dog extends  Animal{
        speak(){
            console.log('小狗汪汪汪');
        }
    }
    class Cat extends  Animal{
        speak(){
            console.log('小猫喵喵喵');
        }
    }
    let dog=new Dog();
    let cat=new Cat();
    dog.speak();
    cat.speak();
    复制代码

    5.11 重写(override) vs 重载(overload)

    • 重写是指子类重写继承自父类中的方法
    • 重载是指为同一个函数提供多个类型定义
    class Animal{
        speak(word:string):string{
            return '动作叫:'+word;
        }
    }
    class Cat extends Animal{
        speak(word:string):string{
            return '猫叫:'+word;
        }
    }
    let cat = new Cat();
    console.log(cat.speak('hello'));
    //--------------------------------------------
    function double(val:number):number
    function double(val:string):string
    function double(val:any):any{
      if(typeof val == 'number'){
        return val *2;
      }
      return val + val;
    }
    
    let r = double(1);
    console.log(r);
    复制代码

    5.12 继承 vs 多态

    • 继承(Inheritance)子类继承父类,子类除了拥有父类的所有特性外,还有一些更具体的特性
    • 多态(Polymorphism)由继承而产生了相关的不同的类,对同一个方法可以有不同的响应
    class Animal{
        speak(word:string):string{
            return 'Animal: '+word;
        }
    }
    class Cat extends Animal{
        speak(word:string):string{
            return 'Cat:'+word;
        }
    }
    class Dog extends Animal{
        speak(word:string):string{
            return 'Dog:'+word;
        }
    }
    let cat = new Cat();
    console.log(cat.speak('hello'));
    let dog = new Dog();
    console.log(dog.speak('hello'));
    复制代码

    6. 接口

    • 接口一方面可以在面向对象编程中表示为行为的抽象,另外可以用来描述对象的形状
    • 接口就是把一些类中共有的属性和方法抽象出来,可以用来约束实现此接口的类
    • 一个类可以继承另一个类并实现多个接口
    • 接口像插件一样是用来增强类的,而抽象类是具体类的抽象概念
    • 一个类可以实现多个接口,一个接口也可以被多个类实现,但一个类的可以有多个子类,但只能有一个父类

    6.1 接口

    • interface中可以用分号或者逗号分割每一项,也可以什么都不加

    6.1.1 对象的形状

    //接口可以用来描述`对象的形状`,少属性或者多属性都会报错
    interface Speakable{
        speak():void;
        name?:string;//?表示可选属性
    }
    
    let speakman:Speakable = {
        speak(){},//少属性会报错
        name,
        age//多属性也会报错
    }
    复制代码

    6.1.2 行为的抽象

    //接口可以在面向对象编程中表示为行为的抽象
    interface Speakable{
        speak():void;
    }
    interface Eatable{
        eat():void
    }
    //一个类可以实现多个接口
    class Person implements Speakable,Eatable{
        speak(){
            console.log('Person说话');
        }
        eat(){}
    }
    class TangDuck implements Speakable{
        speak(){
            console.log('TangDuck说话');
        }
        eat(){}
    }
    复制代码

    6.1.3 任意属性

    //无法预先知道有哪些新的属性的时候,可以使用 `[propName:string]:any`,propName名字是任意的
    interface Person {
      readonly id: number;
      name: string;
      [propName: string]: any;
    }
    
    let p1 = {
      id:1,
      name:'zhufeng',
      age:10
    }
    复制代码

    6.2 接口的继承

    • 一个接口可以继承自另外一个接口
    interface Speakable {
        speak(): void
    }
    interface SpeakChinese extends Speakable {
        speakChinese(): void
    }
    class Person implements SpeakChinese {
        speak() {
            console.log('Person')
        }
        speakChinese() {
            console.log('speakChinese')
        }
    }
    复制代码

    6.3 readonly

    • 用 readonly 定义只读属性可以避免由于多人协作或者项目较为复杂等因素造成对象的值被重写
    interface Person{
      readonly id:number;
      name:string
    }
    let tom:Person = {
      id :1,
      name:'zhufeng'
    }
    tom.id = 1;
    复制代码

    6.4 函数类型接口

    • 对方法传入的参数和返回值进行约束
    interface discount{
      (price:number):number
    }
    let cost:discount = function(price:number):number{
       return price * .8;
    }
    复制代码

    6.5 可索引接口

    • 对数组和对象进行约束
    • userInterface 表示:只要 index 的类型是 number,那么值的类型必须是 string
    • UserInterface2 表示:只要 index 的类型是 string,那么值的类型必须是 string
    interface UserInterface {
      [index:number]:string
    }
    let arr:UserInterface = ['zfpx1','zfpx2'];
    console.log(arr);
    
    interface UserInterface2 {
      [index:string]:string
    }
    let obj:UserInterface2 = {name:'zhufeng'};
    
    复制代码

    6.6 类接口

    • 对类的约束
    interface Speakable {
        name: string;
        speak(words: string): void
    }
    class Dog implements Speakable {
        name!: string;
        speak(words:string) {
            console.log(words);
        }
    }
    let dog = new Dog();
    dog.speak('汪汪汪');
    复制代码

    6.7 构造函数的类型

    • 在 TypeScript 中,我们可以用 interface 来描述类
    • 同时也可以使用interface里特殊的new()关键字来描述类的构造函数类型
    class Animal{
      constructor(public name:string){
      }
    }
    interface WithNameClass{
      new(name:string):Animal
    }
    function createAnimal(clazz:WithNameClass,name:string){
       return new clazz(name);
    }
    let a = createAnimal(Animal,'zhufeng');
    console.log(a.name);
    复制代码

    7. 泛型

    • 泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性
    • 泛型T作用域只限于函数内部使用

    7.1 泛型函数

    • 首先,我们来实现一个函数 createArray,它可以创建一个指定长度的数组,同时将每一项都填充一个默认值
    function createArray(length: number, value: any): Array<any> {
      let result: any = [];
      for (let i = 0; i < length; i++) {
        result[i] = value;
      }
      return result;
    }
    let result = createArray(3,'x');
    console.log(result);
    复制代码

    使用了泛型

    function createArray<T>(length: number, value: T): Array<T> {
        let result: T[] = [];
        for (let i = 0; i < length; i++) {
          result[i] = value;
        }
        return result;
      }
    let result = createArray2<string>(3,'x');
    console.log(result);
    复制代码

    7.2 类数组

    • 类数组(Array-like Object)不是数组类型,比如 arguments
    function sum(...parameters: number[]) {
        let args: IArguments = arguments;
        for (let i = 0; i < args.length; i++) {
            console.log(args[i]);
        }
    }
    sum(1, 2, 3);
    
    let root = document.getElementById('root');
    let children: HTMLCollection = (root as HTMLElement).children;
    children.length;
    let nodeList: NodeList = (root as HTMLElement).childNodes;
    nodeList.length;
    复制代码

    7.3 泛型类

    class MyArray<T>{
        private list:T[]=[];
        add(value:T) {
            this.list.push(value);
        }
        getMax():T {
            let result=this.list[0];
            for (let i=0;i<this.list.length;i++){
                if (this.list[i]>result) {
                    result=this.list[i];
                }
            }
            return result;
        }
    }
    let arr=new MyArray();
    arr.add(1); arr.add(2); arr.add(3);
    let ret = arr.getMax();
    console.log(ret);
    复制代码

    7.5 泛型接口

    • 泛型接口可以用来约束函数
    interface Calculate{
      <T>(a:T,b:T):T
    }
    let add:Calculate = function<T>(a:T,b:T){
      return a;
    }
    add<number>(1,2);
    
    复制代码

    7.6 多个类型参数

    • 泛型可以有多个
    function swap<A,B>(tuple:[A,B]):[B,A]{
      return [tuple[1],tuple[0]];
    }
    let swapped = swap<string,number>(['a',1]);
    console.log(swapped);
    console.log(swapped[0].toFixed(2));
    console.log(swapped[1].length);
    复制代码

    7.7 默认泛型类型

    function createArray3<T=number>(length: number, value: T): Array<T> {
      let result: T[] = [];
      for (let i = 0; i < length; i++) {
        result[i] = value;
      }
      return result;
    }
    let result2 = createArray3(3,'x');
    console.log(result2);
    复制代码

    7.8 泛型约束

    • 在函数中使用泛型的时候,由于预先并不知道泛型的类型,所以不能随意访问相应类型的属性或方法。
    function logger<T>(val: T) {
        console.log(val.length); //直接访问会报错
    }
    //可以让泛型继承一个接口
    interface LengthWise {
        length: number
    }
    //可以让泛型继承一个接口
    function logger2<T extends LengthWise>(val: T) {
        console.log(val.length)
    }
    logger2('zhufeng');
    logger2(1);
    复制代码

    7.9 泛型接口

    • 定义接口的时候也可以指定泛型
    interface Cart<T>{
      list:T[]
    }
    let cart:Cart<{name:string,price:number}> = {
      list:[{name:'zhufeng',price:10}]
    }
    console.log(cart.list[0].name,cart.list[0].price);
    复制代码

    7.10 泛型类型别名

    • 泛型类型别名可以表达更复杂的类型
    type Cart<T> = {list:T[]} | T[];
    let c1:Cart<string> = {list:['1']};
    let c2:Cart<number> = [1];
    复制代码

    7.11 泛型接口 vs 泛型类型别名

    • 接口创建了一个新的名字,它可以在其他任意地方被调用。而类型别名并不创建新的名字,例如报错信息就不会使用别名
    • 类型别名不能被 extends和 implements,这时我们应该尽量使用接口代替类型别名
    • 当我们需要使用联合类型或者元组类型的时候,类型别名会更合适

    8.结构类型系统

    8.1 接口的兼容性

    • 如果传入的变量和声明的类型不匹配,TS就会进行兼容性检查
    • 原理是Duck-Check,就是说只要目标类型中声明的属性变量在源类型中都存在就是兼容的
    interface Animal {
        name: string;
        age: number;
    }
    
    interface Person {
        name: string;
        age: number;
        gender: number
    }
    // 要判断目标类型`Person`是否能够兼容输入的源类型`Animal`
    function getName(animal: Animal): string {
        return animal.name;
    }
    
    let p = {
        name: 'zhufeng',
        age: 10,
        gender: 0
    }
    
    getName(p);
    //只有在传参的时候两个变量之间才会进行兼容性的比较,赋值的时候并不会比较,会直接报错
    let a: Animal = {
        name: 'zhufeng',
        age: 10,
        gender: 0
    }
    复制代码

    8.2 基本类型的兼容性

    //基本数据类型也有兼容性判断
    let num : string|number;
    let str:string='zhufeng';
    num = str;
    
    //只要有toString()方法就可以赋给字符串变量
    let num2 : {
      toString():string
    }
    
    let str2:string='jiagour';
    num2 = str2;
    复制代码

    8.3 类的兼容性

    • 在TS中是结构类型系统,只会对比结构而不在意类型
    class Animal{
        name:string
    }
    class Bird extends Animal{
       swing:number
    }
    
    let a:Animal;
    a = new Bird();
    
    let b:Bird;
    //并不是父类兼容子类,子类不兼容父类
    b = new Animal();
    复制代码
    class Animal{
      name:string
    }
    //如果父类和子类结构一样,也可以的
    class Bird extends Animal{}
    
    let a:Animal;
    a = new Bird();
    
    let b:Bird;
    b = new Animal();
    
    复制代码
    //甚至没有关系的两个类的实例也是可以的
    class Animal{
      name:string
    }
    class Bird{
      name:string
    }
    let a:Animal ;
    a = new Bird();
    let b:Bird;
    b = new Animal();
    复制代码

    8.4 函数的兼容性

    • 比较函数的时候是要先比较函数的参数,再比较函数的返回值

    8.4.1 比较参数

    type sumFunc = (a:number,b:number)=>number;
    let sum:sumFunc;
    function f1(a:number,b:number):number{
      return a+b;
    }
    sum = f1;
    
    //可以省略一个参数
    function f2(a:number):number{
       return a;
    }
    sum = f2;
    
    //可以省略二个参数
    function f3():number{
        return 0;
    }
    sum = f3;
    
     //多一个参数可不行
    function f4(a:number,b:number,c:number){
        return a+b+c;
    }
    sum = f4;
    复制代码

    8.4.2 比较返回值

    type GetPerson = ()=>{name:string,age:number};
    let getPerson:GetPerson;
    //返回值一样可以
    function g1(){
        return {name:'zhufeng',age:10};
    }
    getPerson = g1;
    //返回值多一个属性也可以
    function g2(){
        return {name:'zhufeng',age:10,gender:'male'};
    }
    getPerson = g2;
    //返回值少一个属性可不行
    function g3(){
        return {name:'zhufeng'};
    }
    getPerson = g3;
    //因为有可能要调用返回值上的方法
    getPerson().age.toFixed();
    复制代码

    8.5 函数参数的协变

    • 目标如果能够兼容源就是可以的
    type LogFunc = (a:number|string)=>void;
    let log:LogFunc;
    
    function log1(a:number|string|boolean){
      console.log(a);
    }
    //目标如果能够兼容源就是可以的
    log = log1;
    复制代码

    8.6 泛型的兼容性

    • 泛型在判断兼容性的时候会先判断具体的类型,然后再进行兼容性判断
    //接口内容为空没用到泛型的时候是可以的
    //1.接口内容为空没用到泛型的时候是可以的
    interface Empty<T>{}
    let x!:Empty<string>;
    let y!:Empty<number>;
    x = y;
    
    //2.接口内容不为空的时候不可以
    interface NotEmpty<T>{
      data:T
    }
    let x1!:NotEmpty<string>;
    let y1!:NotEmpty<number>;
    x1 = y1;
    
    //实现原理如下,称判断具体的类型再判断兼容性
    interface NotEmptyString{
        data:string
    }
    
    interface NotEmptyNumber{
        data:number
    }
    let xx2!:NotEmptyString;
    let yy2!:NotEmptyNumber;
    xx2 = yy2;
    复制代码

    8.7 枚举的兼容性

    • 枚举类型与数字类型兼容,并且数字类型与枚举类型兼容
    • 不同枚举类型之间是不兼容的
    //数字可以赋给枚举
    enum Colors {Red,Yellow}
    let c:Colors;
    c = Colors.Red;
    c = 1;
    c = '1';
    
    //枚举值可以赋给数字
    let n:number;
    n = 1;
    n = Colors.Red;
    复制代码

    9.类型保护

    • 类型保护就是一些表达式,他们在编译的时候就能通过类型信息确保某个作用域内变量的类型
    • 类型保护就是能够通过关键字判断出分支中的类型

    9.1 typeof 类型保护

    function double(input: string | number | boolean) {
        if (typeof input === 'string') {
            return input + input;
        } else {
            if (typeof input === 'number') {
                return input * 2;
            } else {
                return !input;
            }
        }
    }
    复制代码

    9.2 instanceof类型保护

    class Animal {
        name!: string;
    }
    class Bird extends Animal {
        swing!: number
    }
    function getName(animal: Animal) {
        if (animal instanceof Bird) {
            console.log(animal.swing);
        } else {
            console.log(animal.name);
        }
    }
    复制代码

    9.3 null保护

    • 如果开启了strictNullChecks选项,那么对于可能为null的变量不能调用它上面的方法和属性
    function getFirstLetter(s: string | null) {
        //第一种方式是加上null判断
        if (s == null) {
            return '';
        }
        //第二种处理是增加一个或的处理
        s = s || '';
        return s.charAt(0);
    }
    //它并不能处理一些复杂的判断,需要加非空断言操作符
    function getFirstLetter2(s: string | null) {
        function log() {
            console.log(s!.trim());
        }
        s = s || '';
        log();
        return s.charAt(0);
    }
    复制代码

    9.4 链判断运算符

    • 链判断运算符是一种先检查属性是否存在,再尝试访问该属性的运算符,其符号为 ?.
    • 如果运算符左侧的操作数 ?. 计算为 undefined 或 null,则表达式求值为 undefined 。否则,正常触发目标属性访问,方法或函数调用。
    a?.b; //如果a是null/undefined,那么返回undefined,否则返回a.b的值.
    a == null ? undefined : a.b;
    
    a?.[x]; //如果a是null/undefined,那么返回undefined,否则返回a[x]的值
    a == null ? undefined : a[x];
    
    a?.b(); // 如果a是null/undefined,那么返回undefined
    a == null ? undefined : a.b(); //如果a.b不函数的话抛类型错误异常,否则计算a.b()的结果
    
    a?.(); //如果a是null/undefined,那么返回undefined
    a == null ? undefined : a(); //如果A不是函数会抛出类型错误
    //否则 调用a这个函数
    复制代码

    链判断运算符 还处于 stage1 阶段,TS 也暂时不支持

    9.5 可辨识的联合类型

    • 就是利用联合类型中的共有字段进行类型保护的一种技巧
    • 相同字段的不同取值就是可辨识
    interface WarningButton{
      class:'warning',
      text1:'修改'
    }
    interface DangerButton{
      class:'danger',
      text2:'删除'
    }
    type Button = WarningButton|DangerButton;
    function getButton(button:Button){
     if(button.class=='warning'){
      console.log(button.text1);
     }
     if(button.class=='danger'){
      console.log(button.text2);
     }
    }
    复制代码

    9.6 in操作符

    • in 运算符可以被用于参数类型的判断
    interface Bird {
        swing: number;
    }
    
    interface Dog {
        leg: number;
    }
    
    function getNumber(x: Bird | Dog) {
        if ("swing" in x) {
          return x.swing;
        }
        return x.leg;
    }
    复制代码

    9.7 自定义的类型保护

    • TypeScript 里的类型保护本质上就是一些表达式,它们会在运行时检查类型信息,以确保在某个作用域里的类型是符合预期的
    • 要自定义一个类型保护,只需要简单地为这个类型保护定义一个函数即可,这个函数的返回值是一个类型谓词
    • 类型谓词的语法为 parameterName is Type 这种形式,其中 parameterName 必须是当前函数签名里的一个参数名`
    interface Bird {
      swing: number;
    }
    
    interface Dog {
      leg: number;
    }
    
    //没有相同字段可以定义一个类型保护函数
    function isBird(x:Bird|Dog): x is Bird{
      return (<Bird>x).swing == 2;
      return (x as Bird).swing == 2;
    }
    function getAnimal(x: Bird | Dog) {
      if (isBird(x)) {
        return x.swing;
      }
      return x.leg;
    }
    复制代码

    10. 类型变换

    10.1 交叉类型

    • 交叉类型(Intersection Types)表示将多个类型合并为一个类型
      interface Bird {
        name: string,
        fly(): void
      }
      interface Person {
        name: string,
        talk(): void
      }
      type BirdPerson = Bird & Person;
      let p: BirdPerson = { name: 'zhufeng', fly() { }, talk() { } };
      p.fly;
      p.name
      p.talk;
      复制代码

    10.2 typeof

    • 可以获取一个变量的类型
    //先定义类型,再定义变量
    type People = {
        name:string,
        age:number,
        gender:string
    }
    let p1:People = {
        name:'zhufeng',
        age:10,
        gender:'male'
    }
    复制代码
    //先定义变量,再定义类型
    let p1 = {
        name:'zhufeng',
        age:10,
        gender:'male'
    }
    type People = typeof p1;
    function getName(p:People):string{
        return p.name;
    }
    getName(p1);
    复制代码

    10.3 索引访问操作符

    • 可以通过[]获取一个类型的子类型
    interface Person{
        name:string;
        age:number;
        job:{
            name:string
        };
        interests:{name:string,level:number}[]
    }
    let FrontEndJob:Person['job'] = {
        name:'前端工程师'
    }
    let interestLevel:Person['interests'][0]['level'] = 2;
    复制代码

    10.4 keyof

    • 索引类型查询操作符
    interface Person{
      name:string;
      age:number;
      gender:'male'|'female';
    }
    //type PersonKey = 'name'|'age'|'gender';
    type PersonKey = keyof Person;
    
    function getValueByKey(p:Person,key:PersonKey){
      return p[key];
    }
    let val = getValueByKey({name:'zhufeng',age:10,gender:'male'},'name');
    console.log(val);
    复制代码

    10.5 映射类型

    • 在定义的时候用in操作符去批量定义类型中的属性
    interface Person{
      name:string;
      age:number;
      gender:'male'|'female';
    }
    //批量把一个接口中的属性都变成可选的
    type PartPerson = {
      [Key in keyof Person]?:Person[Key]
    }
    
    let p1:PartPerson={};
    //也可以使用泛型
    type Part<T> = {
      [key in keyof T]?:T[key]
    }
    let p2:Part<Person>={};
    复制代码

    10.6 内置工具类型

    • TS 中内置了一些工具类型来帮助我们更好地使用类型系统

      10.6.1 Partial

    • Partial 可以将传入的属性由非可选变为可选,具体使用如下:
    type Partial<T> = { [P in keyof T]?: T[P] };
    
    interface A {
      a1: string;
      a2: number;
      a3: boolean;
    }
    
    type aPartial = Partial<A>;
    
    const a: aPartial = {}; // 不会报错
    复制代码

    10.6.2 Required

    • Required 可以将传入的属性中的可选项变为必选项,这里用了 -? 修饰符来实现。
    //type Required<T> = { [P in keyof T]-?: T[P] };
    
    interface Person{
      name:string;
      age:number;
      gender?:'male'|'female';
    }
    /**
     * type Require<T> = { [P in keyof T]-?: T[P] };
     */
    let p:Required<Person> = {
      name:'zhufeng',
      age:10,
      //gender:'male'
    }
    复制代码

    10.6.3 Readonly

    • Readonly 通过为传入的属性每一项都加上 readonly 修饰符来实现。
    interface Person{
      name:string;
      age:number;
      gender?:'male'|'female';
    }
    //type Readonly<T> = { readonly [P in keyof T]: T[P] };
    let p:Readonly<Person> = {
      name:'zhufeng',
      age:10,
      gender:'male'
    }
    p.age = 11;
    复制代码

    10.6.4 Pick

    • Pick 能够帮助我们从传入的属性中摘取某一项返回
    interface Animal {
      name: string;
      age: number;
    }
    /**
     * From T pick a set of properties K
     * type Pick<T, K extends keyof T> = { [P in K]: T[P] };
     */
    // 摘取 Animal 中的 name 属性
    type AnimalSub = Pick<Animal, "name">; //{ name: string; }
    let a:AnimalSub = {
        name:'zhufeng',
        age:10
    }
    复制代码

    10.6.5 映射类型修饰符的控制

    • TypeScript中增加了对映射类型修饰符的控制
    • 具体而言,一个 readonly? 修饰符在一个映射类型里可以用前缀 +-来表示这个修饰符应该被添加或移除
    • TS 中部分内置工具类型就利用了这个特性(Partial、Required、Readonly...),这里我们可以参考 Partial、Required 的实现

    10.7 条件类型

    • 在定义泛型的时候能够添加进逻辑分支,以后泛型更加灵活

    10.7.1 定义条件类型

    interface Fish {
        name: string
    }
    interface Water {
        name: string
    }
    interface Bird {
        name: string
    }
    interface Sky {
        name: string
    }
    //三元运算符
    type Condition<T> = T extends Fish ? Water : Sky;
    let condition: Condition<Fish> = { name: '水' };
    复制代码

    10.7.2 条件类型的分发

    interface Fish {
        fish: string
    }
    interface Water {
        water: string
    }
    interface Bird {
        bird: string
    }
    interface Sky {
        sky: string
    }
    
    type Condition<T> = T extends Fish ? Water : Sky;
    //(Fish extends Fish ? Water : Sky) | (Bird extends Fish ? Water : Sky)
    // Water|Sky
    let condition1: Condition<Fish | Bird> = { water: '水' };
    let condition2: Condition<Fish | Bird> = { sky: '天空' };
    复制代码

    10.7.3 内置条件类型

    • TS 在内置了一些常用的条件类型,可以在 lib.es5.d.ts 中查看:
    10.7.3.1 Exclude
    • 从 T 可分配给的类型中排除 U
      type  E = Exclude<string|number,string>;
      let e:E = 10;
      复制代码
    10.7.3.2 Extract
    • 从 T 可分配的类型中提取 U
      type  E = Extract<string|number,string>;
      let e:E = '1';
      复制代码
    10.7.3.3 NonNullable
    • 从 T 中排除 null 和 undefined
    type  E = NonNullable<string|number|null|undefined>;
    let e:E = null;
    复制代码
    10.7.3.4 ReturnType
    • 获取函数类型的返回类型 `js function getUserInfo() { return { name: "zhufeng", age: 10 }; }

    // 通过 ReturnType 将 getUserInfo 的返回值类型赋给了 UserInfo type UserInfo = ReturnType;

    const userA: UserInfo = { name: "zhufeng", age: 10 };

    ##### 10.7.3.5 InstanceType<T>
    -  获取构造函数类型的实例类型
    ```js
    class Person{
      name:string;
      constructor(name){
        this.name = name;
      }
      getName(){console.log(this.name)}
    }
    
    type  P = InstanceType<typeof Person>;
    let p:P = {name:'zhufeng',getName(){}};
    复制代码

    11.类型声明

    • 声明文件可以让我们不需要将JS重构为TS,只需要加上声明文件就可以使用系统
    • 类型声明在编译的时候都会被删除,不会影响真正的代码

    11.1 普通类型声明

    declare const $:(selector:string)=>{ //变量
        click():void;
        width(length:number):void;
    };
    declare let name:string;  //变量
    declare let age:number;  //变量
    declare function getName():string;  //方法
    declare class Animal{name:string}  //类
    
    interface Person{ //声明接口
        name:string
    }
    
    type Student = { //声明类型
        name:string
    }|'string';
    复制代码

    11.2 外部枚举

    • 外部枚举是使用declare enum定义的枚举类型
    • 外部枚举用来描述已经存在的枚举类型的形状
    declare enum Seasons {
        Spring,
        Summer,
        Autumn,
        Winter
    }
    
    let seasons = [
        Seasons.Spring,
        Seasons.Summer,
        Seasons.Autumn,
        Seasons.Winter
    ];
    复制代码

    declare 定义的类型只会用于编译时的检查,编译结果中会被删除。上例的编译结果如下

    var seasons = [
        Seasons.Spring,
        Seasons.Summer,
        Seasons.Autumn,
        Seasons.Winter
    ];
    复制代码

    也可以同时使用declareconst

    declare const enum Seasons {
        Spring,
        Summer,
        Autumn,
        Winter
    }
    
    let seasons = [
        Seasons.Spring,
        Seasons.Summer,
        Seasons.Autumn,
        Seasons.Winter
    ];
    复制代码

    编译结果

    var seasons = [
        0 /* Spring */,
        1 /* Summer */,
        2 /* Autumn */,
        3 /* Winter */
    ];
    复制代码

    11.3 namespace

    • 如果一个全局变量包括了很多子属性,可能使用namespace
    • 在声明文件中的namespace表示一个全局变量包含很多子属性
    • 在命名空间内部不需要使用 declare 声明属性或方法
    declare namespace ${
        function ajax(url:string,settings:any):void;
        let name:string;
        namespace fn {
            function extend(object:any):void;
        }
    }
    $.ajax('/api/users',{});
    $.fn.extend({
        log:function(message:any){
            console.log(message);
        }
    });
    export {};
    
    复制代码

    11.4 类型声明文件

    • 我们可以把类型声明放在一个单独的类型声明文件中
    • 可以在类型声明文件中使用类型声明
    • 文件命名规范为*.d.ts
    • 观看类型声明文件有助于了解库的使用方式

    11.4.1 jquery.d.ts

    typings\jquery.d.ts

    declare const $:(selector:string)=>{
        click():void;
        width(length:number):void;
    }
    复制代码

    11.4.2 tsconfig.json

    tsconfig.json

    {
      "compilerOptions": {
        "module": "commonjs",
        "target": "ES2015",  
        "outDir":"lib"
      },
      "include": [
        "src/**/*",
        "typings/**/*"
      ]
    }
    复制代码

    11.4.3 test.js

    $('#button').click();
    $('#button').width(100);
    export {};
    复制代码

    11.5 第三方声明文件

    • 可以安装使用第三方的声明文件
    • @types是一个约定的前缀,所有的第三方声明的类型库都会带有这样的前缀
    • JavaScript 中有很多内置对象,它们可以在 TypeScript 中被当做声明好了的类型
    • 内置对象是指根据标准在全局作用域(Global)上存在的对象。这里的标准是指 ECMAScript 和其他环境(比如 DOM)的标准
    • 这些内置对象的类型声明文件,就包含在TypeScript 核心库的类型声明文件

    11.5.1 使用jquery

    //对于common.js风格的模块必须使用 import * as 
    import * as jQuery from 'jquery';
    jQuery.ajax('/user/1');
    复制代码

    11.5.2 安装声明文件

    cnpm i @types/jquery -S
    复制代码

    11.5.3 自己编写声明文件

    types\jquery\index.d.ts

    declare function jQuery(selector:string):HTMLElement;
    declare namespace jQuery{
      function ajax(url:string):void
    }
    export default jQuery;
    复制代码

    tsconfig.json

    • 如果配置了paths,那么在引入包的的时候会自动去paths目录里找类型声明文件
    • 在 webpack 中,我们可以通过配置 alias 的形式来为项目里的文件做映射。在 tsconfig.json 中,我们同样也可以做路径的映射
    • 在 tsconfig.json 中,我们通过 compilerOptions 里的 paths 属性来配置路径映射。 tsconfig.json
      {
      "baseUrl": "./",// 使用 paths 属性的话必须要指定 baseUrl 的值
      "paths": {
      "*":["types/*"]
      }
      复制代码

    11.5.4 npm声明文件可能的位置

    • node_modules/jquery/package.json
      • "types":"types/xxx.d.ts"
    • node_modules/jquery/index.d.ts
    • node_modules/@types/jquery/index.d.ts

    11.6 扩展全局变量的类型

    11.6.1 扩展局部变量类型

    interface String {
        double():string;
    }
    
    String.prototype.double = function(){
        return this+'+'+this;
    }
    console.log('hello'.double());
    
    interface Window{
        myname:string
    }
    console.log(window.myname);
    //export {}
    复制代码

    11.6.2 模块内全局扩展

    types\global\index.d.ts

    declare global{
        interface String {
            double():string;
        }
        interface Window{
            myname:string
        }
    }
    
    export  {}
    复制代码
    "include": [
        "src/**/*",
        "types/**/*"
    ]
    复制代码

    11.7 合并声明

    • 同一名称的两个独立声明会被合并成一个单一声明
    • 合并后的声明拥有原先两个声明的特性
    • 类既可以作为类型使用,也可以作为值使用,接口只能作为类型使用
    关键字作为类型使用作为值使用
    classyesyes
    enumyesyes
    interfaceyesno
    typeyesno
    functionnoyes
    var,let,constnoyes
    class Person{
        name:string=''
    }
    let p1:Person;//作为类型使用
    let p2 = new Person();//作为值使用
    
    interface Animal{
        name:string
    }
    let a1:Animal;
    let a2 = Animal;//接口类型不能用作值
    复制代码

    11.7.1 合并类型声明

    • 可以通过接口合并的特性给一个第三方为扩展类型声明

    use.js

    interface Animal{
        name:string
    }
    let a1:Animal={name:'zhufeng',age:10};
    console.log(a1.name);
    console.log(a1.age);
    复制代码

    types\animal\index.d.ts

    interface Animal{
        age:number
    }
    复制代码

    11.7.2 使用命名空间扩展类

    • 我们可以使用 namespace 来扩展类,用于表示内部类
      class Form {
        username: Form.Item='';
        password: Form.Item='';
      }
      //Item为Form的内部类
      namespace Form {
        export class Item {}
      }
      let item:Form.Item = new Form.Item();
      console.log(item);
      复制代码

    11.7.3 使用命名空间扩展函数

    • 我们也可以使用 namespace 来扩展函数
    function greeting(name: string): string {
        return greeting.words+name;
    }
    
    namespace greeting {
        export let words = "Hello,";
    }
    
    console.log(greeting('zhufeng'))
    复制代码

    11.7.4 使用命名空间扩展枚举类型

    enum Color {
        red = 1,
        yellow = 2,
        blue = 3
    }
    
    namespace Color {
        export const green=4;
        export const purple=5;
    }
    console.log(Color.green)
    复制代码

    11.8 生成声明文件 #

    • 把TS编译成JS后丢失类型声明,我们可以在编译的时候自动生成一份JS文件
    {
      "compilerOptions": {
         "declaration": true, /* Generates corresponding '.d.ts' file.*/
      }
    }复制代码


    展开全文
  • TypeScript 程序设计

    2018-12-31 19:34:49
    1.了解什么是TypeScript?以及TypeScript的基础知识,安装、编译和IDE介绍; 2.掌握 TypeScript 程序设计的基本结构; 3.从传统 JavaScript 到 TypeScript 中 OOP 思想的进阶; 4.能够使用 TypeScript 开发...
  • 5分钟了解 凭啥Typescript 比JS还火

    千次阅读 2019-04-18 16:37:24
    文/北妈阅读本文需要5.1分钟一人的观念和喜好其实对一个成年人,而且有自己特定思想的人来说很难转变,比如生活里,你是宅男、腐女型的。然后,突然有人说宅不好,要多出去走走...
        

    640?wx_fmt=other

    文/北妈

    阅读本文需要 5.1分钟



    人的观念和喜好其实对一个成年人,而且有自己特定思想的人来说很难转变,比如生活里,你是宅男、腐女型的。


    然后,突然有人说宅不好,要多出去走走,体验体验大自然和不同的生活模式,这对你就造成了一种冲击和下意识抵触,因为这需要改变你平时固有的思维和生活习惯,无疑的痛苦的。


    但一旦你跨出去了第一步,并且切实感受到了积极生活习惯带来的变化和好处,那么你就会觉得这是正确的选择和,甚至豁然开朗。


    我写了这么多感慨,你们一定以为北妈又在洗脑了对不对(我打死你丫的)?其实这段话我是用来做个引子比喻,延伸到今天的文章系列主题


    「Typescript 你别闹」 之 「JavaScript我不服」


    1、【JavaScript 和 TypeScript 的主要差异 】


    2、【TypeScript 有什么好处和必要 】

    3、简单初识TypeScript


    之前的我,很信任并且很喜欢JavaScript 这种闲散、自由、弱类型的、无约束的语言风格,才决定一路走到黑,而有的人天生喜欢java、c#这种严格规范的,无需自己控制语义的成熟语言,这就和自己的性格和习惯有莫大关系了。


    所以我第一段说的完全不是废话,而是切实原因,而且我也调查了很多喜欢前端的同行和读者,他们都有一个共性属性,那就是喜欢所见即所得,而且相对自由些的事物,无疑js是最好的契合物。



    那么今天北妈我为何要写关于TypeScript的文章呢?


    因为我之前还是一直是js、原生es6都坚定者,TypeScript加了很多类型检测和接口、面向对象概念,我一直不想应用到项目里,虽说好处很多,但限制和严格性也会增多很多,所以我一直不想应用。


    但随着越来越多的著名项目和大佬推崇和安利它,而且据最新的框架语言排行榜 TS的热度和应用超过JS本身,成为一件不可思议的事,所以这也说明 TypeScript 势必被市场验证了。


    你不学也得学了,这不这些天我也在巩固ts,因为我们的项目已经是vue+ts 的架构了。看到这里你以为我又要广告(我打死你啊)?大错特错,这是我的又一个原创系列  TypeScript 你别闹


    而且这个系列也很重要,我也会一直更下去,直到大家跟着我都学会并且掌握基础,因为这个涉及到之前说我针对大家出的自己的vue课程系列,因为在 Vue 的下一个大版本 (3.x) 中也计划了相当多的 TypeScript 支持改进,包括内置的基于 class 的组件 API 和 TSX 的支持。


    所以我计划把这个技术栈讲一下,在放出vue的课,就可以做到无缝链接了,不然会和主流越差越远,现在线上针对vue+ts结合的系列文章也不多,所以我在这里凑着自己和大家学习也做份贡献。


    三 

    开始(部分总结摘自网络)

    1、【JavaScript 和 TypeScript 的主要差异 】

    TypeScript 和 JavaScript 是目前项目开发中较为流行的两种脚本语言,我们已经熟知 TypeScript 是 JavaScript 的一个超集,但是 TypeScript 与 JavaScript 之间又有什么样的区别呢?


    JavaScript 是一种轻量级的解释性脚本语言,可嵌入到 HTML 页面中,在浏览器端执行,能够实现浏览器端丰富的交互功能,为用户带来流畅多样的用户体验。

    JavaScript 是基于对象和事件驱动的,无需特定的语言环境,只需在支持的浏览器上就能运行。

    JavaScript 语言具有以下特点:

    • JavaScript 是一种脚本编写语言,无需编译,只要嵌入 HTML 代码中,就能由浏览器逐行加载解释执行。

    • JavaScript 是一种基于对象的语言,可以创建对象同时使用现有对象。但是 Javascript 并不支持其它面向对象语言所具有的继承和重载功能。

    • JavaScript 的语法简单,使用的变量为弱类型。

    • JavaScript 语言较为安全,仅在浏览器端执行,不会访问本地硬盘数据。

    • JavaScript 语言具有动态性。JavaScript 是事件驱动的,只根据用户的操作做出相应的反应处理。

    • JavaScript 只依赖于浏览器,与操作系统的因素无关。因此 JavaScript 是一种跨平台的语言。

    • JavaScript 兼容性较好,能够与其他技术(如 XML,REST API 等)一起使用。

    TypeScript

    TypeScript 是 Microsoft 开发和维护的一种面向对象的编程语言。它是 JavaScript 的超集,包含了 JavaScript 的所有元素,可以载入 JavaScript 代码运行,并扩展了 JavaScript 的语法。

    TypeScript 具有以下特点:

    • TypeScript 是 Microsoft 推出的开源语言,使用 Apache 授权协议

    • TypeScript 增加了静态类型、类、模块、接口和类型注解

    • TypeScript 可用于开发大型的应用

    • TypeScript 易学易于理解

    JavaScript 和 TypeScript 的主要差异

    TypeScript 可以使用 JavaScript 中的所有代码和编码概念,TypeScript 是为了使 JavaScript 的开发变得更加容易而创建的。例如,TypeScript 使用类型和接口等概念来描述正在使用的数据,这使开发人员能够快速检测错误并调试应用程序

    TypeScript 从核心语言方面和类概念的模塑方面对 JavaScript 对象模型进行扩展。

    • JavaScript 代码可以在无需任何修改的情况下与 TypeScript 一同工作,同时可以使用编译器将 TypeScript 代码转换为 JavaScript。

    • TypeScript 通过类型注解提供编译时的静态类型检查。

    • TypeScript 中的数据要求带有明确的类型,JavaScript不要求。

    • TypeScript 为函数提供了缺省参数值。

    • TypeScript 引入了 JavaScript 中没有的“类”概念。

    • TypeScript 中引入了模块的概念,可以把声明、数据、函数和类封装在模块中。

    2、【TypeScript 有什么好处和必要 】
    TypeScript 的优势

    下面列举 TypeScript 相比于 JavaScript 的显著优势:

    1. 静态输入

    静态类型化是一种功能,可以在开发人员编写脚本时检测错误。查找并修复错误是当今开发团队的迫切需求。有了这项功能,就会允许开发人员编写更健壮的代码并对其进行维护,以便使得代码质量更好、更清晰。

    2. 大型的开发项目

    有时为了改进开发项目,需要对代码库进行小的增量更改。这些小小的变化可能会产生严重的、意想不到的后果,因此有必要撤销这些变化。使用TypeScript工具来进行重构更变的容易、快捷。

    3. 更好的协作

    当发开大型项目时,会有许多开发人员,此时乱码和错误的机也会增加。类型安全是一种在编码期间检测错误的功能,而不是在编译项目时检测错误。这为开发团队创建了一个更高效的编码和调试过程。

    4. 更强的生产力

    干净的 ECMAScript 6 代码,自动完成和动态输入等因素有助于提高开发人员的工作效率。这些功能也有助于编译器创建优化的代码。

    JavaScript 的优势

    相比于 TypeScript,JavaScript 也有一些明显优势。

    1. 人气

    JavaScript 的开发者社区仍然是巨大而活跃的,在社区中可以很方便地找到大量成熟的开发项目和可用资源。

    2. 学习曲线

    由于 JavaScript 语言发展的较早,也较为成熟,所以仍有一大批开发人员坚持使用他们熟悉的脚本语言 JavaScript,而不是学习 TypeScript。

    3. 本地浏览器支持

    TypeScript 代码需要被编译(输出 JavaScript 代码),这是 TypeScript 代码执行时的一个额外的步骤。

    4. 不需要注释

    为了充分利用 TypeScript 特性,开发人员需要不断注释他们的代码,这可能会使项目效率降低。

    5. 灵活性

    有些开发人员更喜欢 JavaScript 的灵活性。

    如何抉择

    TypeScript 正在成为开发大型编码项目的有力工具。因为其面向对象编程语言的结构保持了代码的清洁、一致和简单的调试。

    因此在应对大型开发项目时,使用 TypeScript 更加合适。如果有一个相对较小的编码项目,似乎没有必要使用 TypeScript,只需使用灵活的 JavaScript 即可。


    3、简单初识TypeScript

    篇幅过长,今天这一节先展示下最简单,最典型的静态类型检测功能,剩下的众多属性,后面我们慢慢讲

    编写第一个 TypeScript 程序

    这一节会介绍如何开始体验 TypeScript,下一节开始会介绍一些有特点、有趣的例子。

    前置准备

    安装 TypeScript。

    npm install -g typescript

    初始化工作区。

    mkdir learning-typescript
    cd learning-typescript

    新建第一个测试文件。

    touch taste.ts

    第一个例子

    我们刚才已经新建了一个名为 taste.ts 的文件,对 TypeScript 的后缀名为 ts,那我们写点什么进去吧!

    taste.ts

    function say(text: string) {
    console.log(text);
    }
    say('hello!');

    然后执行命令(tsc 是刚才 npm 装的 typescript 中带的)。

    tsc taste.ts

    然后我们得到一个编译后的文件 taste.js,内容如下。

    function say(text) {
    console.log(text);
    }
    say('hello!');

    可以看到,只是简单去除了 text 后面的类型标注,然后我们用 node 执行 taste.js

    node taste.js
    // hello!

    完美执行,让我再改写东西看看?

    taste.ts

    function say(text: string) {
    console.log(text);
    }
    say(969);

    然后再执行 tsc taste.ts,然后就类型检查就报错了。这就是 TypeScript 的主要功能 —— 静态类型检查。

    > tsc taste.ts
    taste.ts(4,5): error TS2345: Argument of type '969' is not assignable to parameter of type 'string'.



    意思,如果你规定了你的参数的string类型,就必须是字符串,如果s其他类型,是不允许的。这有助于后面对类型和所有的关联程序的控制,不至于出现各种'undefined'.导致程序无法执行报错。


    如果有想了解的,先看下ts相关文献和电子教程


    TypeScript 入门教程 ~ 
    https://ts.xcatliu.com/

    认识 TypeScript:~

    http://taobaofed.org/blog/2017/03/09/head-first-typescript/


    每日金句过放荡不羁的生活,容易得像顺水推舟,但是要结识良朋益友,却难如登天。


    热门阅读

    开发必备最全 Chrome 插件

    今年我真要去 Google 工作了


    每天只想听你们说:小北最帅!


    640?wx_fmt=jpeg

    长按扫码关注我

    前端你别闹

    我觉得你们应该点 「在看」 640?wx_fmt=gif

    展开全文
  • TypeScript 数组Array操作

    万次阅读 2018-06-20 18:19:51
    数组是一个很简单的数据结构,但是每次使用TypeScript的数组的时候又总是忘记怎么用了,干脆直接弄成干货,忘了过来看看。 一、数组的声明 let array1:Array&amp;lt;number&amp;gt;; let array2:number[];...

    数组是一个很简单的数据结构,但是每次使用TypeScript的数组的时候又总是忘记怎么用了,干脆直接弄成干货,忘了过来看看。

    一、数组的声明

    let array1:Array<number>;
    let array2:number[];

    二、数组初始化

    let array1:Array<number> = new Array<number>();
    let array2:number[] = [123];

    三、数组元素赋值、添加、更改

    let array:Array<number> = [1,2,3,4];
    console.log(array)      // [1, 2, 3, 4]
    
    array[0] = 20;          // 修改
    console.log(array)      // [20, 2, 3, 4]
    
    array[4] = 5;           // 赋值
    console.log(array)      // [20, 2, 3, 4, 5]
    
    array.push(6);          // 添加
    console.log(array)      // [20, 2, 3, 4, 5, 6]
    
    array.unshift(8, 0);    // 在第一个位置依次添加
    console.log(array);     // [8, 0, 20, 2, 3, 4, 5, 6]

    四、删除

    let array:Array<number> = [1,2,3,4];
    console.log(array)      // [1, 2, 3, 4]
    
    let popValue = array.pop();     // 弹出
    console.log(array)      // [1, 2, 3]
    
    array.splice(0, 1);     // 删除元素(index, deleteCount)
    console.log(array)      // [2, 3]
    
    array.shift();          // 删除第一个元素
    console.log(array);     // [3]

    五、合并、断开数组

    /**
      * Combines two or more arrays.
      * @param items Additional items to add to the end of array1.
      */
    concat(...items: T[][]): T[];
    /**
      * Combines two or more arrays.
      * @param items Additional items to add to the end of array1.
      */
    concat(...items: (T | T[])[]): T[];
    /**
     * 该方法返回指定起始位置的一个新的数组
     */
    slice(start?: number, end?: number): T[];
    let array: Array<number> = [1, 2, 3];
    let array2: Array<number> = [4, 5, 6];
    let arrayValue = 7;
    array = array.concat( array2);
    console.log(array)          // [1, 2, 3, 4, 5, 6]
    
    array = array.concat(arrayValue);
    console.log(array)          // [1, 2, 3, 4, 5, 6, 7]
    
    let newArray = array.slice(2, 4);
    console.log(newArray)      // [3, 4]

    六、查找数组元素位置

    /**
      * 返回查找到的第一个元素所在位置
      */
    indexOf(searchElement: T, fromIndex?: number): number;
    /**
      * 返回反序查找的第一个元素所在位置
      */
    lastIndexOf(searchElement: T, fromIndex?: number): number;
    let array: Array<string> = ["a","b","c","d","c","a"];
    let indexC = array.indexOf("c");
    console.log(indexC);            // 2
    let lastA = array.lastIndexOf("a");
    console.log(lastA);             // 5

    七、连接数组元素

    /**
     * 连接数组
     */
    join(separator?: string): string;
    let array: Array<string> = ["a","b","c","d","c","a"];
    let result = array.join();
    console.log(result);            // a,b,c,d,c,a
    
    result = array.join("+");
    console.log(result);            // a+b+c+d+c+a
    
    result = array.join("");
    console.log(result);            // abcdca

    八、排序、反序数组

    let array:Array<number> = [3, 2, 1, 8, 7, 0, 4];
    console.log(array);             // [3, 2, 1, 8, 7, 0, 4]
    
    array.sort();
    console.log(array);             // [0, 1, 2, 3, 4, 7, 8]
    
    array.reverse();
    console.log(array);             // [8, 7, 4, 3, 2, 1, 0]

    九、遍历请看这里 上一篇

    展开全文
  • typescript 高级技巧

    千次阅读 2019-10-17 11:53:59
    用了一段时间的typescript之后,深感中大型项目中typescript的必要性,它能够提前在编译期避免许多 bug,如很恶心的拼写问题。而越来越多的pac...
  • 设置变量A的值总是10,变量B的值总是20 运算符:== 描述:比较两个运算元是否相等,如果相等则结果为 true 例子:(A == B)为 false,A == '10' 为 true 运算符:=== 描述:比较两个运算元的值和类型是否都相等,...
  • TypeScript

    2019-08-15 14:29:18
    什么是 TypeScript TypeScript 简称 TS。TypeScript 是 JavaScript 的超集,就是在 JavaScript 上做了一层封装,封装出 TypeScript 的特性,当然最终代码可以编译为 JavaScript。 TypeScript作为JavaScript的超集,...
  • 转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。 原文出处:https://medium.com/swlh/what-is-typescript-bf333e23f259 ...在过去的几年中,TypeScript的受..
  • Typescript安装与使用

    2020-03-23 13:53:45
    全局安装typescript 前提安装npm、node 命令 npm install -g typescript 命令 cnpm install -g typescript 验证是否已经安装命令 tsc -v 在终端运行typescript命令 tsc xx.ts 在vscode中运行typescript 查看tsc命令...
  • TypeScript是JavaScript的超集,主要提供可选的静态类型,类和接口。其中一个重要好处是使IDE能够在您键入代码时提供更丰富的环境来发现常见错误。 要了解我的意思,请观看Microsoft关于该语言的介绍性视频。 对于...
  • typescript学习笔记

    2020-06-29 18:53:16
    categories: [前端,typescript] thumbnail: /images/fe/leetcode.jpg toc: true 前言 TypeScript 是 JavaScript 的类型的超集,它可以编译成纯 JavaScript。编译出来的 JavaScript 可以运行在任何浏览器上。...
  • 生成typescript配置文件tsconfig.json tsc init tsconfig.json { "compilerOptions": { /* Basic Options */ // "incremental": true, /* Enable incremental compilation */ "target": "es5", /* Specify ...
  • TypeScript

    2014-03-24 19:44:21
    1)解压之后目录是 typescript_plugin 2)把它整个 typescript_plugin文件拷贝到您安装到Eclipse或者是MyEclipse的一个叫dropins文件夹.然后重载Eclipse/MyEclipse 3)重启Eclipse之后会Window-->>Preferences出现...
  • TypeScript

    2019-12-31 17:57:31
    TypeScript是什么 Type+EcmaScript6 TypeScript是JavaScript的强类型版本。然后在编译期去掉类型和特有语法,生成纯粹的JavaScript代码。由于最终 在浏览器中运行的仍然是JavaScript, 所以TypeScript并不依赖于...
  • (精华)2020年8月1日 Typescript 数据类型

    万次阅读 2020-08-01 00:03:58
    flag = '你好typescript'; //错误 第二种:数字类型(number) var num: number = 1314; num = 4131;//正确 num = '你好typescript'; //错误 第三种:字符串类型(string) var str: string = '你好typescript'; ...
  • Typescript

    千次阅读 2017-11-01 09:15:26
    TypeScript是微软开发的一门脚本语言,它是JavaScript的超集,它遵循ES6语言规范。Angular2框架是谷歌发明的,他用的就是TypeScript。ES5,ES6都是脚本语言的规范JavaScript和TypeScript是两种脚本语言。JavaScript...
  • TypeScript

    2017-05-02 14:08:24
    TypeScript
  • TypeScript

    2019-03-05 21:01:55
    typescript新特性 字符串新特性 字符串拼接 字符串模板:在多行字符串用表达式插入变量或者调用方法,直接使用变量名、{变量名}、变量名、{调用方法} 只有在撇号中间才可以,双引号内不可以 结果: 自动拆分...

空空如也

1 2 3 4 5 ... 20
收藏数 72,756
精华内容 29,102
关键字:

typescript