类 Classes-TypeScript 官网Cheat Sheets

166 阅读3分钟

建议把 Handbook 部分(官网链接掘金链接)全看完,再看本章节

class

要点

TypeScript 对 JavaScript ES2015 版本的类,有一些特定类型的扩展,以及添加一个或两个运行时内容。

创建一个类实例

class ABC { /**...*/ }
const abc = new ABC();

new ABC 的参数来自构造函数

private 和 # 的区别

前缀 private 只是 TS 语法,在运行时不起作用,类外部能够访问(虽然类型检查器会报错)

class Bag { private item: any }

修饰符 # 是 JS 语法,是运行时私有的,并且在 JavaScript 引擎内部强制执行它只能在类内部访问

class Bag { #item: any }

修饰符 #,MDN 参考链接:developer.mozilla.org/zh-CN/docs/…

类中的 'this'

类中方法中的 this 依赖于方法是如何调用的。这可能和预期的不一致。可以使用绑定函数箭头函数this 参数,确保 this 类型。

this 参数是 TypeScript 语法,只是进行类型检查,编译后会被擦除,不影响运行时。

// TypeScript 输入带有 'this' 参数
function fn(this: SomeType, x: number) { /* ... */ }

// 编译后
function fn(x) { /* ... */ }

类型和值(Type and Value)

令人惊讶的是,类能够作为类型也能作为值。

const a: Bag = new Bag()

但最好不要这么做:

class C implements Bag { }

常用语法(common Syntax)

interface Updatable { }
type Serializzable = {}
class Account { }
// 继承 Account 类,实现 Updatable 接口 和 Serializzable 类型
class User extends Account implements Updatable, Serializzable {
  id: string; // 字段声明
  displayName?: boolean; //  可选属性
  name!: string; // 告诉类型检查器一定有 name 字段
  #attributes: Map<any, any>; // 私有属性,js语法
  roles = ["user"]; // 默认值
  readonly createdAt = new Date(); //只读属性和默认值
  private readonly createdAt = new Date(); // 只读私有属性和默认值
  constructor(id: string) {
    super()
    this.id = id
    this.#attributes = new Map()
  }

  setName(name: string) { this.name = name } // 原型方法
  verifyName = (name: string) => { this.name = name } // 实例方法,箭头函数

  // 函数重载
  sync(): Promise<{}>
  sync(cb: (result: string)=>void): void
  // 函数重载,最后要接着方法实现
  sync(cb?: (result: string)=>void): void | Promise<{}>{}
  // 属性描述符:Getters 和 Setters
  get accountID(){return 123}
  set accountID(value: number){ /** ... */ }
  
  private handleRequest(){} // 私有方法,ts 语法
  // 保护方法,只能在类和子类中使用,不可以在类外部访问
  protected handleReques(){}
  // 静态属性和方法
  static #userCount = 0 
  static registerUser(user: number){this.#userCount = user}
  // 静态块,this 引用静态类,可以获取静态私有属性,类初始化的时候执行
  static { this.#userCount = -1 }
}

泛型(Generics)

以下声明了一个泛型类,该泛型参数根据类的 content 字段进行推断

class Box<Type>{
  constructor(public content:Type){}
}
const stringBox = new Box("a package")
// stringBox 类型:stringBox: Box<string>

接下来的特性是 TypeScript 特有的语言扩展,它们可能永远不会出现在 JavaScript 中。

参数属性

这是 TypeScript 特定于类的一个扩展,自动将一个实例字段设置为输入参数。

class User {
  constructor(public name:string, public gender:string){}
}
const user = new User('Emma','lady');
user.name  // 'Emma'
user,gender  // 'lady'

public 可换成 privatepublic readonlyprotected, 等等......,但不能是 static 静态类型属性修饰符和 js 语法 # 私有属性修饰符

这种写法等同于:

class User {
  name: string // 必须声明后才能在 constructor 中赋值
  gender: string // 必须声明后才能在 constructor 中赋值
  constructor(name: string, gender: string) {
    this.name = name
    this.gender = gender
  }
}

抽象类(Abstract Classes)

在 TypeScript 中,类,方法和字段都可以是抽象的。抽象方法和字段都只能出现在抽象类中。

抽象类不能实例化,只能作为派生类的基类,派生类必须实现抽象类的所有抽象方法和字段。

abstract class Base {
  abstract getName(): string;

  printName() {
    console.log("Hello, " + this.getName());
  }
}
const b = new Base(); 
Error: // 无法创建抽象类的实例。

class Derived extends Base {
  // 必须实现该抽象方法
  getName() {
    return "world";
  }
}
const d = new Derived();
d.printName();

修饰器和属性(Decorators and Attributes)

tsconfig 中启用 experimentalDecorators 字段

可以在类,方法,方法参数,属性和访问器上用修饰器

import { Syncable, triggerSync, preferCache, required } from "mylib"
@Syncable
class User {
  @triggerSync() // 函数修饰器
  save() { }
  @preferCache(false) // 访问器修饰器
  get displayName() { }
  update(@required info: Partial<User>) { } // 参数修饰器
}

感谢观看,如有错误,望指正

官网文档地址: www.typescriptlang.org/static/Type…

本章已上传 github: github.com/Mario-Mario…

上一篇: 控制流分析 CFA-TypeScript 官网Cheat Sheets

下一篇: 类型别名 Types-TypeScript 官网Cheat Sheets