Day24 :【TypeScript 学起来】TypeScript 中使用 Class

今天来了解在 TypeScript 中使用 Class,Class Member 包含了: Fields 、 Readonly、Constructors、Method、Getters / Setters、Index Signatures。


Fields & Readonly

  • 实例属性: 在ES6中, 是无法直接在class中定义属性,必须定义在 constructor里面并使用this.,而 ES7这可以直接在calss中定义, 而 TypeSript 也跟上脚步,可以直接在class里面去定义属性,且public公用的。

  • readonly : 可以使用 readonly 关键字来唯读属性, 防止进行赋值。

class Point {
  x: number; //可以使用实例属性
  y: number;
  readonly name: string = "show point"; //readonly唯读

  constructor(x = 0, y = 0) {  //预设给0
    this.x = x;
    this.y = y;
  }
  
  printPoint() {
    console.log(`x: ${this.x}, y: ${this.y}`);
  }
}

let p = new Point(2, 4);
p.printPoint();  //x: 2, y: 4 
p.name = "hihi"; //若对readonly属性赋值会报错 error: Cannot assign to 'name' because it is a read-only property.
  • --strictPropertyInitialization (tsconfig.json) : class实例属性的赋值检查。如下面例子,已宣告name属性型别,却没给予赋值, 就会报错提醒。
class GoodGreeter {
  name: string; //error: Property 'name' has no initializer and is not definitely assigned in the 
  word: string;

  constructor() {
    this.word = "hello";
  }
}

Constructors

constructors: 他跟function的使用很像, 你可以使用型别注记,预设参数。但官网提到可以 overloads, 内心一个问号,javascript class 只有一个 constructor, 所以 TS 可以多个吗?

//原文: Class constructors are very similar to functions. You can add parameters with type annotations, default values, and overloads

class Point2 {
  x: number;
  y: number;
 
  // Normal signature with defaults
  constructor(x = 0, y = 0) {
    this.x = x;
    this.y = y;
  }
}

let p2 = new Point2(100,200);
class Point {
  // Overloads
  constructor(x: number, y: string);
  constructor(s: string);
  constructor(xs: any, y?: any) {
    // TBD
  }
}

後来实做发现,是不行的唷,不能使用 multiple constructor, 是无法overloads的, 我在想他应该想讲的是method可以overloads, 一个函式提供多个型别定义。

class Point3 {
  // Overloads
  constructor(x: number, y: string){ //errro: Multiple constructor implementations are not allowed.
      this.x = x;
      this.y = y;
  };
  constructor(s: string){
    this.s = x;
  }
}

let p3 = new Point3(1,"5");
let p4 = new Point3("helllo")
console.log(p3); //Point3 { x: 1, y: '5' }
console.log(p4); //Point3 { x: 'helllo', y: undefined }


Super call

super: 在 JavaScript 我们有时候会忘记在 this之前使用 super 去调用父层,但在 TypeScript 我们忘了使用 super, complier就会提醒我们。

class Base {
  k = 4;
}
 
class Derived extends Base {
  constructor() {
    console.log(this.k);
// 'super' must be called before accessing 'this' in the constructor of a derived class.
    super();
  }
}

Method

这跟 JavaScript 一样,可增加 class 方法,并定义参数型别。此外,在 method 里要使用 class 的属性,需要使用 this 关键字。

let z: number = 0;

class Point4 {
  x = 10;
  y = 10;
  z: string = "hello";
  
  //method
  scale(n: number): void {
    this.x *= n;
    this.y *= n;
  }
  
  //修改class的z属性,需使用this.z,不然视为修改class外的 z
  editZ(){
      z = "world"; //error: Type 'string' is not assignable to type 'number'.
  }
}

Getters / Setters

class 也有存取器(accessors), 就是getter 及 setter,用以改变属性的读取和赋值行为,与 es6 class 一样。 另外在TS4.3引入了新特性, set 及 set 传入的参数型别可以多种型别。

class Thing {
   _size = 0;

  get size(): number {
    return this._size;
  }
 
  set size(value: string | number | boolean) {
    let num = Number(value);
 
    // Don't allow NaN, Infinity, etc
 
    if (!Number.isFinite(num)) {
      this._size = 0;
      return;
    }
 
    this._size = num;
  }
}

let thing = new Thing();
console.log(thing.size); //0
thing.size = "seven";
console.log(thing.size); //0
thing.size = 2.2;
console.log(thing.size); //2.2

Index Signatures

在JavaScript中使用[]来操作object属性,那些属性JavaScript 都会要 toString 去读取, 如下方例子, 使用obj["name0"]没问题,使用obj[name1]则会报错。

let obj = {
  name0: "iris",
  name1: "iris",
  2: "iris"
};

console.log(obj["name0"]);  //iris
console.log(obj[2]); //iris
console.log(obj[name1]); //error: name1 is not defined

在 TypeScript 中 , 会强制提醒使用 toString,减少我们的错误。
TypeScript 的Index Signatures 必须是 string 或者 number。

let obj2 = {
  toString() {
    console.log('toString called');
    return 'Hello';
  }
};

class Foo {
  constructor(public message: string) {}
  log() {
    console.log(this.message);
  }
}

let foo: any = {};
foo['Hello'].log(); // World
foo[obj2] = new Foo('World'); //error: Type '{ toString(): string; }' cannot be used as an index type.


想了解更多 Index Signatures 相关可参考 Day16这篇


感谢阅读!明天见~


参考资料

https://www.typescriptlang.org/docs/handbook/2/classes.html
https://willh.gitbook.io/typescript-tutorial/advanced/class#typescript-zhong-lei-bie-de-yong-fa


<<:  Day24 用python写UI-聊聊Text(一)

>>:  Day25 Vue 双向绑定 vs 单向绑定

DAY 21 Big Data 5Vs – Variety(速度) Kinesis (1)

串流处理的应用场景近年来越来越常见,尤其是IOT产业的蓬勃发展,加上硬体技术的发展,越来越多的即时资...

Day 09 | Livewire 生命周期勾 Lifecycle Hooks

在 Vue.js 有的生命周期在 Livewire 中也都有,除此之外在 Livewire 中各自变...

D01 / 为什麽要写这个? - 前言

Hi 我是 Tomaz.  第一次参加铁人赛,和各位铁人一起进行磨练,希望撑得过去 ? 认真学 Co...

Day 21: Behavioral patterns - Iterator

目的 了解 forEach() 的来由。 说明 简单来说,实作任意资料结构的 forEach(),最...

grep简介

grep grep(Global search a Regular Expression and P...