TypeScript基础

TypeScript 与 JavaScript 的区别

  • TypeScript
    • JavaScript 的超集用于解决大型项目的代码复杂性
    • 可以在编译期间发现并纠正错误
    • 强类型,支持静态和动态类型
    • 最终被编译成 JavaScript 代码,使浏览器可以理解
    • 支持模块、泛型和接口
    • 支持 ES3,ES4,ES5 和 ES6 等
    • 社区的支持仍在增长,而且还不是很大
  • JavaScript
    • 一种脚本语言,用于创建动态网页
    • 作为一种解释型语言,只能在运行时发现错误
    • 弱类型,没有静态类型选项
    • 可以直接在浏览器中使用
    • 不支持模块,泛型或接口
    • 不支持编译其他 ES3,ES4,ES5 或 ES6 功能

TypeScript 基础类型

  • Boolean 布尔类型 let isDone: boolean = false;
  • Number 数字 let count: number = 10;
  • String 字符串 let name: string = "semliker";
  • Symbol
    const sym = Symbol();
    let obj = {
        [sym]: "semlinker",
    };
    console.log(obj[sym]); // semlinker 
  • Array 数组
    • let list: number[] = [1, 2, 3];
    • let list: Array<number> = [1, 2, 3];
  • Enum 枚举
    • 数字枚举
       enum Direction {
            NORTH,
            SOUTH,
            EAST,
            WEST,
        }
        let dir: Direction = Direction.NORTH;
    
    • 字符串枚举
        enum Direction {
            NORTH = "NORTH",
            SOUTH = "SOUTH",
            EAST = "EAST",
            WEST = "WEST",
        }
        let dirName = Direction[0]; // NORTH
        let dirVal = Direction["NORTH"]; // 0
    
    • 常量枚举(const修饰)
        const enum Direction {
            NORTH,
            SOUTH,
            EAST,
            WEST,
        }
        let dir: Direction = Direction.NORTH;
    
    • 异构枚举
        enum Enum {
            A,
            B,
            C = "C",
            D = "D",
            E = 8,
            F,
        }
        console.log(Enum.A) //输出:0
        console.log(Enum[0]) // 输出:A
    
  • Any类型(全局超级类型)
    • any 类型本质上是类型系统的一个逃逸舱。作为开发者,这给了我们很大的*:TypeScript 允许我们对 any 类型的值执行任何操作,而无需事先执行任何形式的检查。
    • 使用 any 类型,可以很容易地编写类型正确但在运行时有问题的代码。如果我们使用 any 类型,就无法使用 TypeScript 提供的大量的保护机制。为了解决 any 带来的问题,TypeScript 3.0 引入了 unknown 类型。
        let value: any;
        value.foo.bar; // OK
        value.trim(); // OK
        value(); // OK
        new value(); // OK
        value[0][1]; // OK
    
  • Unknown类型
        let value: unknown;
        value = true; // OK
        value = 42; // OK
        value = "Hello World"; // OK
        value = []; // OK
        value = {}; // OK
        value = Math.random; // OK
        value = null; // OK
        value = undefined; // OK
        value = new TypeError(); // OK
        value = Symbol("type"); // OK
        let value1: unknown = value; // OK
        let value2: any = value; // OK
        let value3: boolean = value; // Error
        let value4: number = value; // Error
        let value5: string = value; // Error
        let value6: object = value; // Error
        let value7: any[] = value; // Error
        let value8: Function = value; // Error
    
  • Tuple元组类型
    • 数组一般由同种类型的值组成,但有时我们需要在单个变量中存储不同类型的值,这时候我们就可以使用元组(ts特有)
    • 元组可用于定义具有有限数量的未命名属性的类型。每个属性都有一个关联的类型。使用元组时,必须提供每个属性的值。
        let tupleType:[string,boolean];
        tupleType = ["semlinker", true];
        console.log(tupleType[0]); // semlinker
        console.log(tupleType[1]); // true
    
  • Void类型
    • 表示没有任何类型。当一个函数没有返回值时,你通常会见到其返回值类型是 void
    // 声明函数返回值为void
    function warnUser(): void {
        console.log("This is my warning message");
    }
    //声明一个 void 类型的变量没有什么作用,因为在严格模式下,它的值只能为 undefined
    let unusable: void = undefined;
    
  • Null 和 Undefined
  • object, Object 和 {} 类型
    • object 用于表示非原始类型
    • Object 所有 Object 类的实例的类型
      • Object 接口定义了 Object.prototype 原型对象上的属性
      • ObjectConstructor 接口定义了 Object 类的属性。
            interface Object {
                constructor: Function;
                toString(): string;
                toLocaleString(): string;
                valueOf(): Object;
                hasOwnProperty(v: PropertyKey): boolean;
                isPrototypeOf(v: Object): boolean;
                propertyIsEnumerable(v: PropertyKey): boolean;
            }
            interface ObjectConstructor {
                /** Invocation via `new` */
                new(value?: any): Object;
                /** Invocation via function calls */
                (value?: any): any;
                readonly prototype: Object;
                getPrototypeOf(o: any): any;
                // ···
            }
            declare var Object: ObjectConstructor;
        
    • {} 类型描述了一个没有成员的对象
  • Never 类型
    • 永不存在的值的类型。never 类型是那些总是会抛出异常或根本就不会有返回值的函数表达式或箭头函数表达式的返回值类型。
          // 返回never的函数必须存在无法达到的终点
          function error(message: string): never {
              throw new Error(message);
          }
          function infiniteLoop(): never {
              while (true) {}
          }
      

TypeScript 断言

  • 类型断言类似类型转换,但不进行特殊的数据检查和解构。仅在编译阶段起作用无运行时影响
let someValue: any = "this is a string";
// 尖括号语法
let strLength: number = (<string>someValue).length;
// as语法
let strLength1: number = (someValue as string).length;

类型守卫

  • 类型保护是可执行运行时检查的一种表达式,用于确保该类型在一定的范围内。
  • in关键字
    interface Admin {
        name: string;
        privileges: string[];
    }
    interface Employee {
        name: string;
        startDate: Date;
    }
    type UnknownEmployee = Employee | Admin;
    function printEmployeeInformation(emp: UnknownEmployee) {
        console.log("Name: " + emp.name);
        if ("privileges" in emp) {
            console.log("Privileges: " + emp.privileges);
        }
        if ("startDate" in emp) {
            console.log("Start Date: " + emp.startDate);
        }
    } 
  • typeof关键字
    • typeof 类型保护只支持两种形式:typeof v === “typename” 和 typeof v !== typename,“typename” 必须是 “number”,“string”,"boolean"或 “symbol”。但是 TypeScript 并不会阻止你与其它字符串比较,语言不会把那些表达式识别为类型保护。
        function padLeft(value: string, padding: string | number) {
            if (typeof padding === "number") {
                return Array(padding + 1).join(" ") + value;
            }
            if (typeof padding === "string") {
                return padding + value;
            }
            throw new Error(`Expected string or number, got '${padding}'.`);
        }
    
  • instanceof 关键字
    interface Padder {
        getPaddingString(): string;
    }
    class SpaceRepeatingPadder implements Padder {
        constructor(private numSpaces: number) {}
        getPaddingString() {
            return Array(this.numSpaces + 1).join(" ");
        }
    }
    class StringPadder implements Padder {
        constructor(private value: string) {}
        getPaddingString() {
            return this.value;
        }
    }
    let padder: Padder = new SpaceRepeatingPadder(6);
    if (padder instanceof SpaceRepeatingPadder) {
    // padder的类型收窄为 'SpaceRepeatingPadder'
    }
  • 自定义类型保护的类型谓词
    function isNumber(x: any): x is number {
        return typeof x === "number";
    }
    function isString(x: any): x is string {
        return typeof x === "string";
    }

联合类型和类型别名

  • 联合类型 联合类型通常与 null 或 undefined 一起使用
const sayHello = (name: string | undefined) => { /* ... */ };
  • 可辨识联合 可辨识、联合类型和类型守卫
// 可辨识要求联合类型中的每个元素都含有一个单例类型属性
    enum CarTransmission {
        Automatic = 200,
        Manual = 300
    }
    interface Motorcycle {
        vType: "motorcycle"; // 可辨识属性
        make: number; // year
    }
    interface Car {
        vType: "car"; // 可辨识属性
        transmission: CarTransmission
    }
    interface Truck {
        vType: "truck"; // discriminant
        capacity: number; // in tons
    }
// 类型别名(类型别名常用于联合类型)
    type Vehicle = Motorcycle | Car | Truck;
// 类型守卫
    const EVALUATION_FACTOR = Math.PI; 
    function evaluatePrice(vehicle: Vehicle) {
        return vehicle.capacity * EVALUATION_FACTOR;
    }
    const myTruck: Truck = { vType: "truck", capacity: 9.5 }; 
    evaluatePrice(myTruck); 
    // Property 'capacity' does not exist on type 'Vehicle'. 
    // Property 'capacity' does not exist on type 'Motorcycle'.

TypeScript 泛型

  • 可以使用泛型来创建可重用的组件,一个组件可以支持多种类型的数据,这样用户就可以以自己的数据类型来使用组件。
  • 设计泛型的关键目的是在成员之间提供有意义的约束,这些成员可以是:类的实例成员、类的方法、函数参数和函数返回值
  • 泛型是允许同一个函数接受不同类型参数的一种模板,泛型会保留参数类型。
  • 泛型变量
    • T(Type):表示一个 TypeScript 类型
    • K(Key):表示对象中的键类型
    • V(Value):表示对象中的值类型
    • E(Element):表示元素类型
  • 泛型工具
    • Partial 将传入的属性变为可选项
    • Record<K, T> 对象属性名联合类型
    • Readonly 把传入的类型变为只读状态
    • Required 把传入的类型变为必填状态
    • Pick<T, S> 在 T 中,过滤掉非 S 的类型
    • Exclude<T, U> 从类型T中剔除所有可以赋值给类型U的类型
    • Extract<T, U> 从类型T中获取所有可以赋值给类型U的类型
    • Omit<T, K> 在 T 中删除对应的 K
    • ReturnType 获取函数类型T的返回值类型
    • Parameters 返回类型为T的函数的参数类型所组成的数组
    • NonNullable 去除T中的 null 和 undefined 类型
    • InstanceType 返回构造函数类型T的实例类型
// 泛型接口
interface GenericIdentityFn<T> {
  (arg: T): T;
}
// 泛型类
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;
};  
上一篇:typescript 中 public private protect 区别


下一篇:五款在未来大放异彩的编程语言