TypeScript完全支持ES2015中引入的class关键字。 与其他JavaScript语言特性一样,TypeScript添加了类型注释和其他语法,允许您表达类和其他类型之间的关系。
类的成员
下面是一个空的类:
代码语言:javascript复制class Point {}
这个类现在毫无用处,现在往这个类里面加点成员
字段
在类上声明字段,编程了可读写的public 属性
代码语言:javascript复制class Point {
x: number;
y: number;
}
const pt = new Point();
pt.x = 0;
pt.y = 0;
属性初始化: 类实例化的时候,会初始赋值
代码语言:javascript复制class Point {
x = 0;
y = 0;
}
const pt = new Point();
// Prints 0, 0
console.log(`${pt.x}, ${pt.y}`);
与const、let和var一样,类属性的初始值设定项将用于推断其类型:
代码语言:javascript复制const pt = new Point();
pt.x = "0";
//Type 'string' is not assignable to type 'number'.
–strictPropertyInitialization
StricPropertyInitialization设置控制类字段是否需要在构造函数中初始化。
正常构建需要初始化:
代码语言:javascript复制class GoodGreeter {
name: string;
constructor() {
this.name = "hello";
}
}
不初始化使用!断言,也不会报错:
代码语言:javascript复制class OKGreeter {
// Not initialized, but no error
name!: string;
}
readonly
只读属性,不多介绍,只能读取不能赋值。
代码语言:javascript复制注意:构造函数内可以赋值
class Greeter {
readonly name: string = "world";
constructor(otherName?: string) {
if (otherName !== undefined) {
this.name = otherName;
}
}
err() {
this.name = "not ok";
//Cannot assign to 'name' because it is a read-only property.
}
}
const g = new Greeter();
g.name = "also not ok";
//Cannot assign to 'name' because it is a read-only property.
构造函数
类构造函数与函数非常相似。可以添加带有类型注释、默认值和重载的参数:
代码语言:javascript复制class Point {
x: number;
y: number;
// Normal signature with defaults
constructor(x = 0, y = 0) {
this.x = x;
this.y = y;
}
}
代码语言:javascript复制class Point {
// Overloads
constructor(x: number, y: string);
constructor(s: string);
constructor(xs: any, y?: any) {
// TBD
}
}
super 调用
如果有基类,必须在构造函数中调用super
,且在使用this
之前
class Base {
k = 4;
}
class Derived extends Base {
constructor() {
// Prints a wrong value in ES5; throws exception in ES6
console.log(this.k);
//'super' must be called before accessing 'this' in the constructor of a derived class.
super();
}
}
Methods
在类中函数属性统称为方法
代码语言:javascript复制class Point {
x = 10;
y = 10;
scale(n: number): void {
this.x *= n;
this.y *= n;
}
}
代码语言:javascript复制let x: number = 0;
class C {
x: string = "hello";
m() {
// This is trying to modify 'x' from line 1, not the class property
this.x = "world";
x = 4
// Type 'string' is not assignable to type 'number'.
}
}
Getters / Setters
类也可以有访问器:
代码语言:javascript复制class C {
_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;
}
}
索引签名
类可以声明索引签名;它们的工作方式与其他对象类型的索引签名相同:
代码语言:javascript复制class MyClass {
[s: string]: boolean | ((s: string) => boolean);
check(s: string) {
return this[s] as boolean;
}
}
因为索引签名类型还需要捕获方法的类型,所以很难有效地使用这些类型。一般来说,最好将索引数据存储在另一个地方,而不是类实例本身。
类的实现和继承
与其他具有面向对象特性的语言一样,JavaScript中的类可以从基类继承。
implements
一个类可以准守一个或者多个接口去实现它:
代码语言:javascript复制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 {
可选值不会要求,实现类去实现:
代码语言:javascript复制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 (继承)
类可以从基类扩展。派生类具有其基类的所有属性和方法,还定义其他成员。
代码语言:javascript复制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);
方法重写
子类继承父类之后,可以重写属性和方法
代码语言:javascript复制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");
面向对象的特征父类可以指向子类(变量多态):
代码语言:javascript复制// Alias the derived instance through a base class reference
const b: Base = d;
// No problem
b.greet();