TypeScript类、泛的使用实践记录 | 青训营

64 阅读4分钟

TypeScript简介

TypeScript是一种由微软开发的编程语言,它是JavaScript的超集,可以编译为纯JavaScript代码。TypeScript添加了静态类型、类、接口和模块等功能,使得开发者可以更加规范和可靠地编写JavaScript代码。它还提供了更好的代码提示和自动补全功能,以及更强大的工具支持。TypeScript可以在任何支持JavaScript的地方运行,并且可以与现有的JavaScript库和框架无缝集成。

TypeScript基础知识

a. anyneverunknownnull & undefinedvoid

  • any: 不检查。很好用,但要小心变成anyScript
  • never: 永不存在的值的类型。常用于会抛出异常或不会有返回值的函数表达式或箭头函数表达式的返回值类型。
  • unknown: 任何类型的值都可以赋给 unknown 类型,但是 unknown 类型的值只能赋给 unknown 本身和 any 类型。
  • null & undefined: 默认情况下 null 和 undefined 是所有类型的子类型。
  • void: 常用于函数返回类型声明。

b. typeinterface

相同点:允许拓展(extends) 不同点:

  1. type 可以声明基本类型,联合类型(union: X | Y),元组(tuple: [X, Y])
  2. type 可以使用 typeof 获取实例的类型进行赋值
  3. 多个相同的 interface 声明可以自动合并
  4. type 能使用 in 关键字生成映射类型,但 interface 不行
  5. inerface 支持同时声明,默认导出 而type必须先声明后导出

c. keyoftypeof

keyof  获取索引类型的属性名,构成联合类型。
typeof 获取一个变量或对象的类型。

d. implementsexpends

继承,常用于复杂接口的封装和自定义组件入口设计。 extends:用来实现继承 接口与接口接口与类,不可以重写属性,但可以重写方法 implements:用来实现类实现接口,同时可以重写属性和方法,包含一些新的功能

type A = { a: number }

interface AB extends A { b: string } // 更规范常用
// 等价写法
type TAB = A & { b: string }

// 类类型接口,类可以实现多个接口 implements
interface Stu1 {}
interface Stu2 {}
class Stu implements Stu1, Stu2 {}

// 混合类型接口 extends
interface Fn {}
interface Mixed extends Fn {}
function myFn(): Fn {}

e. 断言

类型断言,只在编译阶段起作用 ! x! 非空断言运算符。将从 x 值域中排除 null 和 undefined!. 在变量名后添加,可以断言排除 undefined 和 null 类型。

f. 数组定义方式

type Ex1= Array<string>;
interface Man { man: Array<{ name: string, age: number}>}

type Ex2 = string[];
interface Man { man : { name: string, age: number }[] }

TypeScript类的基本使用

  • 类的定义和声明: 在此案例中,定义了一个名为Person的类。它有一个私有属性name和一个构造函数,构造函数接受一个参数name并将其赋值给属性name。类中还有一个名为sayHello的方法,它会在控制台输出一句问候语,包含了属性name的值。
class Person {
  private name: string;
  constructor(name: string) {
    this.name = name;
  }
  sayHello() {
    console.log(`Hello, my name is ${this.name}.`);
  }
}
  • 属性和方法的定义和访问修饰符: 在此引入了访问修饰符。私有属性name只能在类内部访问,而受保护属性age可以在类内部和子类中访问。构造函数接受两个参数name和age,将它们分别赋值给对应的属性。
class Person {
  private name: string;
  protected age: number;
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
  sayHello() {
    console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`);
  }
}
  • 类的继承和多态性:
class Student extends Person {
  private grade: number;
  constructor(name: string, age: number, grade: number) {
    super(name, age);
    this.grade = grade;
  }
  sayHello() {
    console.log(`Hello, my name is ${this.name}, I'm ${this.age} years old, and I'm in grade ${this.grade}.`);
  }
}
  • 抽象类和接口的使用:
  • 在抽象类Shape定义了一个抽象方法getArea,它没有具体的实现,只是用来约束子类必须实现该方法。接口Printable定义了一个方法print,任何实现该接口的类都必须实现print方法。Circle类继承了Shape抽象类,并实现了Printable接口。它有一个私有属性radius,并实现了getArea和print方法。
abstract class Shape {
  abstract getArea(): number;
}

interface Printable {
  print(): void;
}

class Circle extends Shape implements Printable {
  private radius: number;
  constructor(radius: number) {
    super();
    this.radius = radius;
  }
  getArea() {
    return Math.PI * this.radius ** 2;
  }
  print() {
    console.log(`The area of the circle is ${this.getArea()}.`);
  }
}

TypeScript泛型的基本概念

  • 泛型的定义和声明:
function identity<T>(arg: T): T {
  return arg;
}
let result = identity<string>("Hello TypeScript");
console.log(result);
  • 泛型类、泛型函数和泛型接口的使用:
class Box<T> {
  private value: T;
  constructor(value: T) {
    this.value = value;
  }
  getValue(): T {
    return this.value;
  }
}
let box = new Box<number>(10);
console.log(box.getValue()); // Output: 10

function printArray<T>(arr: T[]): void {
  for (let item of arr) {
    console.log(item);
  }
}
printArray<number>([1, 2, 3, 4, 5]);

interface Pair<T, U> {
  first: T;
  second: U;
}
let pair: Pair<number, string> = { first: 1, second: "two" };

总结

通过TypeScript的类和泛型特性,可以在代码中实现更高的灵活性和安全性。类的继承、多态性、抽象类和接口使得代码更加模块化和可复用,而泛型的使用则增加了代码的通用性和可扩展性。通过使用类型约束,我们可以避免运行时错误和类型错误,提高代码的可维护性。因此,在TypeScript中合理地使用类和泛型,并加以类型约束,有助于提高代码的质量和开发效率。