一、简介
1.类(class)是面向对象编程的基本构件,封装了属性和方法
1.1、属性的类型:类的属性可以在顶层声明,也可以在构造方法内部声明,如果不给出类型;TypeScript 会认为x
和y
的类型都是any;
如果声明时给出初值,可以不写类型,TypeScript 会自行推断属性的类型;
class Point {
x:number;
y:number;
}
1.1.1.TypeScript 有一个配置项strictPropertyInitialization
,只要打开(默认是打开的),就会检查属性是否设置了初值,如果没有就报错
// 打开 strictPropertyInitialization
class Point {
x: number; // 报错
y: number; // 报错
}
// 如果类的顶层属性不赋值,就会报错。如果不希望出现报错,可以使用非空断言。
class Point {
x!: number;
y!: number;
}
// 属性x和y没有初值,但是属性名后面添加了感叹号,表示这两个属性肯定不会为空,所以TypeScript
//就不报错了
1.2、readonly 修饰符:属性名前面加上 readonly 修饰符,就表示该属性是只读的。实例对象不能修改这个属性(构造方法内部设置只读属性的初值,修改只读属性的值都是可以的)
1.2.1. readonly 属性的初始值,可以写在顶层属性,也可以写在构造方法里面
// 构造方法内部设置只读属性的初值,这是可以的
class A {
readonly id:string;
constructor() {
this.id = 'bar'; // 正确
}
}
class A {
readonly id:string = 'foo';
constructor() {
this.id = 'bar'; // 正确
}
}
// 构造方法修改只读属性的值也是可以的。或者说,如果两个地方都设置了只读属性的值,以构造方法
//为准。在其他方法修改只读属性都会报错
1.3、方法的类型:类的方法就是普通函数,类型声明方式与函数一致
class Point {
x:number;
y:number;
constructor(x:number, y:number) {
this.x = x;
this.y = y;
}
add(point:Point) {
return new Point(
this.x + point.x,
this.y + point.y
);
}
}
// 构造方法constructor()和普通方法add()都注明了参数类型,但是省略了返回值类型,因为
//TypeScript 可以自己推断出来
1.3.1.类的方法跟普通函数一样,可以使用参数默认值,以及函数重载。
class Point {
x: number;
y: number;
constructor(x = 0, y = 0) {
this.x = x;
this.y = y;
}
}
// 下面是函数重载的例子
class Point {
constructor(x:number, y:string);
constructor(s:string);
constructor(xs:number|string, y?:string) {
// ...
}
}
1.3.2.构造方法不能声明返回值类型,否则报错,因为它总是返回实例对象
class B {
constructor():object { // 报错:构造方法声明了返回值类型object,导致报错
// ...
}
}
1.4、存取器方法:取值器用来读取属性,存值器用来写入属性
class C {
_name = '';
get name() {
return this._name;
}
set name(value) {
this._name = value;
}
}
// get name()是取值器,其中get是关键词,name是属性名。外部读取name属性时,实例对象会
//自动调用这个方法,该方法的返回值就是name属性的值
// set name()是存值器,其中set是关键词,name是属性名。外部写入name属性时,实例对象会
//自动调用这个方法,并将所赋的值作为函数参数传入
1.4.1.TypeScript 对存取器有以下规则
a、如果某个属性只有get
方法,没有set
方法,那么该属性自动成为只读属性
class C {
_name = 'foo';
get name() {
return this._name;
}
}
const c = new C();
c.name = 'bar'; // 报错
b、TypeScript 5.1 版之前,set
方法的参数类型,必须兼容get
方法的返回值类型,否则报错。
// TypeScript 5.1 版之前
class C {
_name = '';
get name():string { // 报错因为set参数类型必须兼容get返回值类型,在此不兼容
return this._name;
}
set name(value:number) {
this._name = String(value);
}
}
// set方法的参数类型(number|string)兼容get方法的返回值类型(string),这是允许的
class C {
_name = '';
get name():string {
return this._name;
}
set name(value:number|string) {
this._name = String(value);
}
}
// TypeScript 5.1 版做出了改变,现在两者可以不兼容
c、get
方法与set
方法的可访问性必须一致,要么都为公开方法,要么都为私有方法。
1.5、属性索引:类允许定义属性索引
class MyClass {
[s:string]: boolean |
((s:string) => boolean);
get(s:string) {
return this[s] as boolean;
}
}
// [s:string]表示所有属性名类型为字符串的属性,它们的属性值要么是布尔值,要么是返回
//布尔值的函数
1.5.1.由于类的方法是一种特殊属性(属性值为函数的属性),所以属性索引的类型定义也涵盖了方法。如果一个对象同时定义了属性索引和方法,那么前者必须包含后者的类型。
class MyClass {
[s:string]: boolean;
f() { // 报错
return true;
}
}
//上例的属性索引的类型里面不包括方法,导致后面的方法f()定义直接报错;正确的写法如下
class MyClass {
[s:string]: boolean | (() => boolean);
f() {
return true;
}
}
1.5.2属性存取器视同属性
class MyClass {
[s:string]: boolean;
get isInstance() {
return true;
}
}
// 属性inInstance的读取器虽然是一个函数方法,但是视同属性,所以属性索引虽然没有涉及方
//法类型,但是不会报错
二、类的 interface 接口
2.1、implements 关键字:interface 接口或 type 别名,可以用对象的形式,为 class 指定一组检查条件。然后,类使用 implements 关键字,表示当前类满足这些外部类型条件的限制。
interface Country {
name:string;
capital:string;
}
// 或者
type Country = {
name:string;
capital:string;
}
class MyCountry implements Country {
name = '';
capital = '';
}