TypeScript快览

作者: rxdxxxx | 来源:发表于2018-08-05 12:56 被阅读19次

    一. 数据类型

    变量可以使用数据类型修饰, 限制了变量别随意赋值带来的不可预测性

    let age: number = 12;
    let isDone: boolean = false;
    let myName: string = 'Tom';
    let unusable: void = undefined;
    let u: undefined = undefined;
    let n: null = null;
    

    有的时候数据类型是不可预测的, 有的场景下, 也是需要可以接受任意类型的变量. 这时候就可以使用任意值

    let anyThing: any = 'hello';
    anyThing = 3;
    

    类型推断

    • 在声明时,给定了值, 那么变量就会被推断对应的类型.
    let myFavoriteNumber = 'seven'; // let myFavoriteNumber: string = 'seven';
    myFavoriteNumber = 7;
    
    • 如果定义的时候没有赋值,不管之后有没有赋值,都会被推断成 any 类型而完全不被类型检查
    let something; // let something: any;
    
    something = 'seven';
    something = 7;
    
    something.setName('Tom');
    

    联合类型

    • 一个类型可以同时指定多个类型
    let myFavoriteNumber: string | number;
    myFavoriteNumber = 'seven';
    myFavoriteNumber = 7;
    

    当使用联合类型时, 变量只能使用两个类型中公共的方法属性.

    • 如果是我们需要在方法中根据类型调用特定的方法时, 就需要使用断言语法. 断言只能从联合类型中选取类型
    
    

    对象类型---接口

    程序开发有一个很流行的模式,就是面向接口编程. 接口抽象了结构, 真正的实现就可以提供多种多样的能力.

    interface Person {
        name: string; // name是确定属性, 实现接口的对象,必须失效该属性
        age?: number; // age是可选属性, 也就是真正实现时,不需一定实现.
        readonly id: number; // 只读属性, 
    
    }
    
    let tom: Person = {
        name: 'Tom',
        age: 25,
        id: 100, // 只能在对象赋值时设置值. 
    };
    

    数组的类型

    let fibonacci: number[] = [1, 1, 2, 3, 5];
    
    // 报错, 数组中只允许单一类型
    let fibonacci2: number[] = [1, '1', 2, 3, 5];
    
    // 泛型数组
    let fibonacci: Array<number> = [1, 1, 2, 3, 5]; 
    
    // 接口类型数组
    interface NumberArray {
        [index: number]: number;
    }
    let fibonacci: NumberArray = [1, 1, 2, 3, 5]; 
    
    // 要求数组中存放不同类型的值
    let list: any[] = ['Xcat Liu', 25, { website: 'http://xcatliu.com' }];
    
    
    
    

    函数的类型

    • 注意,输入多余的(或者少于要求的)参数,是不被允许的
    function sum(x: number, y: number): number {
        return x + y;
    }
    
    sum(1, 2); // 正常
    sum(1, 2, 3);// 多输入一个参数, 会报错
    
    • 使用可选参数, 可以省略参数的输入, 可选参数一定要在参数列表的尾部.
    function buildName(firstName: string, lastName?: string) {
        if (lastName) {
            return firstName + ' ' + lastName;
        } else {
            return firstName;
        }
    }
    let tomcat = buildName('Tom', 'Cat');
    let tom = buildName('Tom'); 
    
    • 用接口定义函数的类型
    interface SearchFunc {
       (source: string, subString: string): boolean;
    }
    
    let mySearch: SearchFunc;
    mySearch = function(source: string, subString: string) {
       return source.search(subString) !== -1;
    }
    

    声明文件: declare

    我们需要使用 declare 关键字来定义它的类型,帮助 TypeScript 判断我们传入的参数类型对不对:

    declare var jQuery: (selector: string) => any;
    
    jQuery('#foo');
    

    注意:

    • 通常声明文件放到一个单独的文件中管理. 例如: jQuery.d.ts

    • 用「三斜线指令」表示引用了声明文件, /// <reference path="./jQuery.d.ts" />

    • 第三方声明文件, npm install @types/jquery --save-dev

    Node

    Node.js 不是内置对象的一部分,如果想用 TypeScript 写 Node.js,则需要引入第三方声明文件:

    npm install @types/node --save-dev
    

    二. 进阶用法

    关键字: type

    类型别名

    例如定义一个函数的类型, 参数类型加上返回值类型, 导致类型描述很长, 这时候就可以使用类型别名简化.

    type Name = string;
    type NameResolver = () => string;
    type NameOrResolver = Name | NameResolver;
    function getName(n: NameOrResolver): Name {
        if (typeof n === 'string') {
            return n;
        }
        else {
            return n();
        }
    }
    

    字符串字面量类型

    作为类型时, 参数只能是约定好的内容. 类似于枚举

    type EventNames = 'click' | 'scroll' | 'mousemove';
    function handleEvent(ele: Element, event: EventNames) {
        // do something
    }
    
    handleEvent(document.getElementById('hello'), 'scroll');  // 没问题
    handleEvent(document.getElementById('world'), 'dbclick'); // 报错,event 不能为 'dbclick'
    

    元祖

    数组: 相同元素集合,

    元祖: 不同元素集合

    let xcatliu: [string, number];
    xcatliu[0] = 'Xcat Liu';
    xcatliu[1] = 25;
    
    xcatliu[0].slice(1);
    xcatliu[1].toFixed(2);
    
    // 报错, 类型不一致
    let k: [string, number] = [18,'Tom', 18]
    
    

    注意:

    • 元素的定义时的位置是固定的. [18,'Tom', 18] 的类型就是[number, string, number]
    • 对应位置可以使用该位置类型的方法,
    • 如果在元祖中push
    • 额外元素的类型为元祖中元素的联合类型 number | string

    关键字: enum

    一般枚举

    enum Days {Sun, Mon, Tue, Wed, Thu, Fri, Sat};
    

    编译后

    var Days;
    (function (Days) {
        Days[Days["Sun"] = 0] = "Sun";
        Days[Days["Mon"] = 1] = "Mon";
        Days[Days["Tue"] = 2] = "Tue";
        Days[Days["Wed"] = 3] = "Wed";
        Days[Days["Thu"] = 4] = "Thu";
        Days[Days["Fri"] = 5] = "Fri";
        Days[Days["Sat"] = 6] = "Sat";
    })(Days || (Days = {}));
    ;
    
    • 它的默认值,如下每个较前一个 + 1
    console.log(Days["Sun"] === 0); // true
    console.log(Days["Mon"] === 1); // true
    
    
    console.log(Days[2] === "Tue"); // true
    console.log(Days[6] === "Sat"); // true
    
    • 手动赋值, 以最后面的数值递增.
    enum Days {Sun = 7, Mon = 1, Tue, Wed, Thu, Fri, Sat};
    
    console.log(Days["Sun"] === 7); // true
    console.log(Days["Mon"] === 1); // true
    console.log(Days["Tue"] === 2); // true
    console.log(Days["Sat"] === 6); // true
    

    常数枚举

    每一项的内容是常数, 不可计算得到.

    const enum Directions {
      Up,
      Down,
      Left,
      Right
    }
    
    let dir: Directions = Directions.Up
    

    编译后

    var dir = 0 /* Up */;
    

    外部枚举

    // 此处必须使用const, 不然declare 定义的类型只会用于编译时的检查,编译结果中会被删除。
    declare const enum Directions {
        Up,
        Down,
        Left,
        Right
    }
    
    let directions = [Directions.Up, Directions.Down, Directions.Left, Directions.Right];
    

    编译结果:

    var directions = [0 /* Up */, 1 /* Down */, 2 /* Left */, 3 /* Right */];
    

    三. 类的使用

    访问修饰符

    • public : 任何地方都可以被访问, 默认的属性和方法都是publick
    • private: 只有当前类可以访问.
    • protected: 和private类似, 但可以被子类访问.

    抽象类

    abstract 用于定义抽象类和其中的抽象方法.

    使用关键字 extends 继承抽象类

    注意:

    • 抽象类不能被实例化
    • 抽象方法必须被子类实现

    接口

    接口可以描述一个对象属性, 同时可以对行为进行抽象

    • 使用关键字 implements 实现接口
    • 一个类可以实现多个接口
    • 接口之间可以是继承关系
    interface Alarm {
        alert();
    }
    interface Light {
        lightOn();
        lightOff();
    }
    interface FlyableAlarm extends Alarm{
        fly();
    }
    class Door {
    }
    
    class SecurityDoor extends Door implements Alarm {
        alert() {
            console.log('SecurityDoor alert');
        }
    }
    class Car implements Alarm, Light {
        alert() {
            console.log('Car alert');
        }
        lightOn() {
            console.log('Car light on');
        }
        lightOff() {
            console.log('Car light off');
        }
    }
    class Plane implements FlyableAlarm{
        alert(){
            console.log('Plane alert');
        }
        fly(){
            console.log('Plane fly');
        }
    }
    
    • 接口继承类
    class Point {
        x: number;
        y: number;
    }
    
    interface Point3d extends Point {
        z: number;
    }
    
    let point3d: Point3d = {x: 1, y: 2, z: 3};
    

    泛型

    定义函数,接口或类的时候, 不预先指定具体的类型, 而在使用的时候再指定类型的一种特性

    • 函数使用泛型
    function createArray<T,N extends number>(length: N, value: T): Array<T> {
        let result: T[] = [];
        for (let i = 0; i < length; i++) {
            result[i] = value;
        }
        return result;
    }
    
    createArray<string>(3, 'x'); // ['x', 'x', 'x']
    
    • 接口使用泛型
    interface CreateArrayFunc {
        <T>(length: number, value: T): Array<T>;
    }
    // 也可以把泛型提升到接口名上
    //interface CreateArrayFunc<T> {
    //    (length: number, value: T): Array<T>;
    //}
    
    let createArray: CreateArrayFunc;
    createArray = function<T>(length: number, value: T): Array<T> {
        let result: T[] = [];
        for (let i = 0; i < length; i++) {
            result[i] = value;
        }
        return result;
    }
    
    createArray(3, 'x'); // ['x', 'x', 'x']
    
    • 使用泛型
    class GenericNumber<T> {
        zeroValue: T;
        add: (x: T, y: T) => T;
    }
    
    let myGenericNumber = new GenericNumber<number>();
    myGenericNumber.zeroValue = 0;
    myGenericNumber.add = function(x, y) { return x + y; };
    
    • 指定泛型的默认类型
    function createArray<T = string>(length: number, value: T): Array<T> {
        let result: T[] = [];
        for (let i = 0; i < length; i++) {
            result[i] = value;
        }
        return result;
    }
    

    原文连接: https://ts.xcatliu.com/

    相关文章

      网友评论

        本文标题:TypeScript快览

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