_length = 0;
get length() {
return this._length;
}
set length(value) {
this._length = value;
}
}
注意,没有额外逻辑的字段支持的get/set对在JavaScript中很少有用。如果在get/set操作期间不需要添加额外的逻辑,那么公开公共字段就可以了。
TypeScript对访问器有一些特殊的推理规则:
-
只有get 没有set ,这个属性自动变成raedonly
-
如果set 的参数没有明确指出,那么按照get 类型推断
-
Getters and setters必须具有相同的成员可见性(public,private)
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;
}
}
索引签名
类可以声明索引签名;它们的工作方式与其他对象类型的索引签名相同:
class MyClass {
[s: string]: boolean | ((s: string) => boolean);
check(s: string) {
return this[s] as boolean;
}
}
因为索引签名类型还需要捕获方法的类型,所以很难有效地使用这些类型。一般来说,最好将索引数据存储在另一个地方,而不是类实例本身。
与其他具有面向对象特性的语言一样,JavaScript中的类可以从基类继承。
implements
一个类可以准守一个或者多个接口去实现它:
interface Pingable {
ping(): void;
}
class Sonar implements Pingable {
ping() {
console.log(“ping!”);
}
}
class Ball implements Pingable {
//Class ‘Ball’ incorrectly implements interface ‘Pingable’.
//Property ‘ping’ is missing in type ‘Ball’ but required in type ‘Pingable’.
pong() {
console.log(“pong!”);
}
}
类同时可以准守多个接口取实现,例如 class C implements A, B {
可选值不会要求,实现类去实现:
interface A {
x: number;
y?: number;
}
class C implements A {
x = 0;
}
const c = new C();
c.y = 10;
Property ‘y’ does not exist on type ‘C’.
extends (继承)
类可以从基类扩展。派生类具有其基类的所有属性和方法,还定义其他成员。
class Animal {
move() {
console.log(“Moving along!”);
}
}
class Dog extends Animal {
woof(times: number) {
for (let i = 0; i < times; i++) {
console.log(“woof!”);
}
}
}
const d = new Dog();
// Base class method
d.move();
// Derived class method
d.woof(3);
方法重写
子类继承父类之后,可以重写属性和方法
class Base {
greet() {
console.log(“Hello, world!”);
}
}
class Derived extends Base {
greet(name?: string) {
if (name === undefined) {
super.greet();
} else {
console.log(Hello, ${name.toUpperCase()}
);
}
}
}
const d = new Derived();
d.greet();
d.greet(“reader”);
面向对象的特征父类可以指向子类(变量多态):
// Alias the derived instance through a base class reference
const b: Base = d;
// No problem
b.greet();
初始化顺序
在某些情况下,JavaScript类的初始化顺序可能令人惊讶。让我们来考虑这个代码:
class Base {
name = “base”;
constructor() {
console.log("My name is " + this.name);
}
}
class Derived extends Base {
name = “derived”;
}
// Prints “base”, not “derived”
const d = new Derived();
这里发生了什么?
JavaScript定义的类初始化顺序是:
-
基类字段已初始化
-
基类构造函数运行
-
派生类字段已初始化
-
派生类构造函数运行
这意味着基类构造函数在自己的构造函数中看到了自己的name值,因为派生类字段初始化尚未运行。
类成员访问权限
您可以使用TypeScript来控制某些方法或属性是否对类之外的代码可见。