typescript-类与接口

204 阅读3分钟

ES6 类

  1. 类的定义和实例

ES6 中的class用于定义类,使用 constructor定义构造函数,通过new生成实例的时候,会自动调用构造函数。
class通过extends关键字实现继承,子类需要使用super关键字来调用父类的构造函数和方法。

class Animal {
    public name;
    constructor(name) {
        this.name = name; //不执行次操作,this只是Animal类,自身不会存在name属性
    }
    sayHi() {
        return `My name is ${this.name}`;
    }
}
let a = new Animal('Jack');
console.log(a.sayHi()); // My name is Jack
class Cat extends Animal {
  constructor(name) {
    super(name); // 调用父类的 constructor(name)
    console.log(this.name);
  }
  sayHi() {
    return 'Meow, ' + super.sayHi(); // 调用父类的 sayHi()
  }
}
let c = new Cat('Tom'); // Tom
console.log(c.sayHi()); // Meow, My name is Tom
  1. 存取器

类的getter和setter可以改变属性的赋值和读取操作。

class Animal {
    constructor(name) {
        this.name = name;
    }
    get name() {
        return 'Jack';
    }
    set name(value) {
        console.log('setter: ' + value);
    }
}
let a = new Animal('Kitty'); // setter: Kitty
a.name = 'Tom'; // setter: Tom
console.log(a.name); // Jack

当使用了存取器中的getter时setter也会同步生效,且无返回值

interface 一般用于规范三个东西,分别是函数、类和构造器

TS 中接口除了可用于对类的一部分行为进行抽象外,也常用于对对象的形状进行描述,接口定义时一般首字母大写。

一般定义接口后,赋值的时候参数也需要完全匹配,形状必须和接口的形状保持一致,当需要动态时就需要用到可选属性和任意属性的接口定义。

// 可选属性接口
interface Person { 
    name: string; 
    readonly id: number; //只读属性
    age?: number; 
} 
let tom: Person = { 
    name: 'Tom',
    id: 112,
};

// 任意属性接口
interface Person {
    name: string;
    age?: number;
    // `[propName: string]` 定义了任意属性取 `string` 类型的值。
    [propName: string]: string | number;  //或者any
}

let tom: Person = {
    name: 'Tom',
    gender: 'male'
};

一旦定义了任意属性,那么确定属性和可选属性的类型都必须是它的类型的子集
只读的约束存在于第一次给对象赋值的时候,而不是第一次给只读属性赋值的时候

  1. 函数 interface

函数 interface 可规范函数的参数和返回值

interface xxx{    
    (参数,...):返回值类型 
}
interface SearchFn {
    (key: string, page?: number): number[]
}
const search: SearchFn = function (key: string, page: number) {
    return [1, 2, 3]
}

当函数是一个 interface 时,要求;
1、参数名可以不一致,但参数的类型必须与接口定义的对应,且参数可以少不可以多;
2、返回值必须要有,且与接口定义的一致。 2.类 interface 实现 implements 是面向对象中的一个重要概念,js 里一个类只能继承自另一个类,当不同类之间有公共的特性的时候,就可以把这些特性提取成一个接口(interfaces),用 implements 关键字来实现。

interface Alarm {
    alert(): void;
}
class Door {
    x: number;
    y: number;
    constructor(x: number, y: number) {
        this.x = x;
        this.y = y;
    }
}
interface Light {
    lightOn(): void;
    lightOff(): void;
}
class Car extends Door implements Alarm, Light {
    alert() {
        console.log('Car alert');
    }
    lightOn() {
        console.log('Car light on');
    }
    lightOff() {
        console.log('Car light off');
    }
}

接口通过extends继承类, 其原理就是在声明class Door的时候,除了会创建一个名为Door的类外,也会创建一个名为Door的类。

class Point {
    x: number;
    y: number;
    constructor(x: number, y: number) {
        this.x = x;
        this.y = y;
    }
}
interface PointInstanceType {
    x: number;
    y?: number; //可选属性
}
// 等价于 interface Point3d extends PointInstanceType
interface Point3d extends Point {
    z: number;
}
let point3d: Point3d = {x: 1, y: 2, z: 3};

PointInstanceType 相比于 Point,缺少了 constructor 方法,这是因为声明 Point 类时创建的 Point 类型是不包含构造函数的。另外,除了构造函数是不包含的,静态属性或静态方法也是不包含的(实例的类型当然不应该包括构造函数、静态属性或静态方法)。

一个类可以实现继承多个接口且继承某一类(继承类的时候,只会继承他的实例属性和方法,不包含今天属性和方法),接口也可以通过extends继承接口,拥有所继承接口中的属性方法并且拓展自身的方法。

interface Alarm {
    alert(): void;
}

interface LightableAlarm extends Alarm {
    lightOn(): void;
    lightOff(): void;
}