TypeScript 入门

0x01 概述

  • TypeScript 官网

  • TypeScript 是一种基于 JavaScript 构建的强类型编程语言

    • JavaScript 的超集,即 JavaScript 是 TypeScript 的子集
    • JavaScript 类型化,即在 JavaScript 基础上添加类型系统
  • 优势:

    • 提供可读性和可维护性
    • 在编译阶段检查并报错
  • 环境:

    1. 安装 NodeJS
    2. 使用命令 npm install -g typescript 全局安装 TypeScript
  • 编译与运行:

    1. 方案一:

      1. 创建 index.ts

        let a: number = 123;
        console.log(a);
        
      2. 使用命令 tsc ./index.ts 编译 index.ts 文件,生成同名的 index.js 文件

        var a = 123;
        console.log(a);
        
      3. 使用命令 node ./index.js 运行生成的 index.js 文件

    2. 方案二:

      1. 使用命令 npm install -g ts-node 全局安装 ts-node 工具
        • 用于简化方案一的步骤,直接编译和运行 TypeScript 文件
      2. 使用命令 ts-node ./index.ts 编译和运行 index.ts 文件
        • 或使用 VSCode 的 Code Runner 插件

0x02 类型

(1)基础数据类型

  • number:数字

    let a: number = 123;
    
  • string:字符串

    let a: string = "abc";
    
  • boolean:布尔

    let a: boolean = true;
    
  • null:空值

    let a: null = null;
    
  • undefined:未定义

    let a: undefined = undefined;
    
  • symbol:Symbol

    let a: symbol = Symbol("a");
    
  • void:函数无返回值

  • never:函数返回错误值

(2)复杂数据类型

  • 对象:

    type MyObj = {
      id: number;
      name?: string;
    };
    
    let a: MyObj = { id: 1, name: "a" };
    let b: MyObj = { id: 1 };
    
    • type 是声明类型别名的关键字
  • 数组:

    let a: number[] = [1, 2, 3];
    let b: Array<number> = [1, 2, 3];
    
  • 类:

    class MyClass {}
    
    let a: MyClass = new MyClass();
    
  • 函数:

    let a: () => number = () => 1 + 2;
    
  • 元组:

    let a: [number, string] = [123, "abc"];
    
  • 任意数据类型:anyunknown

(3)类型注解与类型推断

  • 类型注解:在声明变量时,指定变量的数据类型

    let a: number = 123;
    console.log(typeof a);	// number
    
  • 类型推断:在声明变量时,指定变量的值,由 TypeScript 编译器自动推断变量的数据类型

    let a = 123;
    console.log(typeof a);	// number
    

(4)函数类型注解

  • 返回类型注解:

    function a(): number {
      return 123;
    }
    
  • 参数注解:

    function b(num: number): number {
      return num;
    }
    
  • 对象参数注解:

    function c({ a, b }: { a: number; b: number }): number {
      return a + b;
    }
    

(5)类型符号

  • A | B:联合类型,变量为 A 类型或 B 类型
  • A & B:交叉类型,变量为 A 类型且 B 类型(常用于对象类型)

(6)类型断言

  • 尖括号:

    let num: any = 123;
    console.log((<string>num).length);	// undefined
    
  • as 关键字:

    let num: any = 123;
    console.log((num as string).length);	// undefined
    

(7)操作符

  • !:非空断言

    let a: string | null;
    console.log(a!.length);
    
  • ?:可选链操作符

    let a: {
      b?: {
        c?: number;
      };
    } = {};
    console.log(a?.b?.c);	// undefined
    
  • ??:空值合并操作符

    let a: null = null;
    let b = a ?? 10;
    console.log(b);
    
    • || 区别在于:当左值为空值时采用右值,而 || 的左值为假值时采用右值

(8)interface 对象类型

  • 一种校验工具,并指定对象的各个属性

  • 一般语法:

    interface MyObj {
      id: number;
      name: string;
    }
    
    let a: MyObj = { id: 1, name: "a" };
    
  • 可选属性:?

    interface MyObj {
      id: number;
      name?: string;
    }
    
    let a: MyObj = { id: 1 };
    
  • 任意属性:

    interface MyObj {
      id: number;
      [propName: string]: any;
    }
    
    let a: MyObj = { id: 1, name: "a" };
    
  • 只读属性:

    interface MyObj {
      readonly id: number;
      [propName: string]: any;
    }
    
    let a: MyObj = { id: 1, name: "a" };
    a.id = 2;	// 此语句报错:Cannot assign to 'id' beacause it is a read-only property.
    

(9)枚举类型

  • 使用 enum 关键字声明枚举类型

  • 举例一:颜色枚举

    enum Color {
      RED = "#f00",
      GREEN = "#0f0",
      BLUE = "#00f",
    }
    
    console.log(Color.RED);
    console.log(Color.GREEN);
    console.log(Color.BLUE);
    
  • 举例二:数值自增

    enum Letter {
      a,
      b = 2,
      c,
      d,
    }
    
    console.log(Letter.a);  // 0
    console.log(Letter.b);  // 2
    console.log(Letter.c);  // 3
    console.log(Letter.d);  // 4
    

0x03 类

(1)基本使用

  • TypeScript 兼容 ES6 和 ES7 关于类的使用方法

    • ES6 类:

      class MyClass {
        constructor() {
          this.name = "ES6";
        }
        getName() {
          return this.name;
        }
      }
      
    • ES7 类:

      class MyClass {
        name;
        constructor() {
          this.name = "ES7";
        }
        getName() {
          return this.name;
        }
      }
      
  • ES 中,继承父类的子类可以使用 super 关键字调用父类的方法

    class Parent {
      name = "Parent";
      getName() {
        console.log("Parent: ", this.name);
      }
    }
    
    class Child extends Parent {
      name = "Child";
      getName() {
        console.log("Child: ", this.name);	// Child: Child
        super.getName();					// Parent: Child
      }
    }
    
    let child = new Child();
    child.getName();
    
  • TypeScript 的类提供了三种访问修饰符:publicprivateprotected

    • protected 的作用与 private 类似,区别在于可以在继承子类被访问
    class Parent {
      protected name = "Parent";
    }
    
    class Child extends Parent {
      getName() {
        console.log("Child: ", this.name);
      }
    }
    
    let child = new Child();
    child.getName();	// Child: Parent
    

(2)存取器

TypeScript 的类提供了 getter 修饰符 get 和 setter 修饰符 set

class MyClass {
  private a: number;
  constructor(a: number) {
    this.a = a;
  }
  get aValue() {
    return this.a;
  }
  set aValue(a: number) {
    this.a = a;
  }
}

let mc = new MyClass(1);
console.log(mc.aValue);		// 1
mc.aValue = 2;
console.log(mc.aValue);		// 2

(3)抽象类

  • 使用 abstract 关键字定义抽象类

  • 抽象类不可被实例化

  • 举例:

    abstract class Person {
      abstract call(): string;
    }
    
    class Student extends Person {
      call() {
        return "student";
      }
    }
    
    let student = new Student();
    console.log(student.call());
    

0x04 泛型

(1)概述

  • 泛型指根据使用时的数据类型而定,对内类型同一,对外类型不定

  • 泛型有利于方法、类的复用

  • 举例:

    function map<T>(arr: T[], fn: (item: T) => T) {
      return arr.map(fn);
    }
    
    let arr = map([1, 2, 3], (item) => item + 1);
    console.log(arr);	// [ 2, 3, 4 ]
    

(2)泛型函数与泛型接口

  • 泛型函数与非泛型函数:

    // 泛型函数
    let fn1: (arg: any) => any;
    
    // 非泛型函数
    let fn2: <T>(arg: T) => T;
    
  • 相比非泛型函数,泛型函数可以在使用时统一函数中的数据类型,而 any 不具有统一性

  • 泛型接口与泛型函数类似:

    interface I {
      <T>(x: T): T;
    }
    

(4)泛型类

  • 泛型类的定义方法与泛型函数类似

  • 举例:模拟数组

    class MyArray<T> {
      private data: T[];
      private count: number;
      private capacity: number;
    
      constructor(capacity: number) {
        this.data = new Array(capacity);
        this.count = 0;
        this.capacity = capacity;
      }
    
      push(element: T): void {
        if (this.count === this.capacity) {
          this.resize(this.capacity * 2);
        }
        this.data[this.count] = element;
        this.count++;
        return;
      }
    
      pop(): T {
        if (this.count === 0) {
          throw new Error("Empty array");
        }
        const element = this.data[this.count - 1];
        this.count--;
        if (this.count < this.capacity / 4) {
          this.resize(this.capacity / 2);
        }
        return element;
      }
    
      private resize(newCapacity: number): void {
        const newData = new Array(newCapacity);
        for (let i = 0; i < this.count; i++) {
          newData[i] = this.data[i];
        }
        this.data = newData;
        this.capacity = newCapacity;
      }
    }
    
    let arr = new MyArray<number>(10);
    arr.push(1);
    arr.push(2);
    arr.push(3);
    console.log(arr);
    arr.pop();
    console.log(arr);
    

(5)泛型约束

  • 通过接口与 extends 关键字实现约束

  • 用于确保它至少具有某些特定的属性或符合某个特定的接口

  • 举例:

    interface Length {
      length: number;
    }
    
    function fn<T extends Length>(arg: T): T {
      console.log(arg.length);
      return arg;
    }
    

-End-

posted @ 2024-08-12 23:39  SRIGT  阅读(15)  评论(0编辑  收藏  举报