接口实现与类类型
接口实现与类类型
TypeScript中的接口和类类型是构建复杂类型系统的核心工具。接口定义契约,类实现这些契约,两者结合能创建出强类型且可扩展的代码结构。
接口的基本实现
类可以通过implements
关键字实现一个或多个接口。当类实现接口时,必须包含接口中定义的所有属性和方法:
interface Animal {
name: string;
makeSound(): void;
}
class Dog implements Animal {
name: string;
constructor(name: string) {
this.name = name;
}
makeSound() {
console.log("Woof!");
}
}
未实现接口全部成员会导致编译错误:
class Cat implements Animal {
// 错误: 缺少'makeSound'属性
name: string;
}
可选属性和只读属性
接口可以定义可选属性和只读属性,实现类需要遵守这些约束:
interface User {
readonly id: number;
username: string;
age?: number;
}
class RegisteredUser implements User {
readonly id: number;
username: string;
constructor(id: number, username: string) {
this.id = id;
this.username = username;
}
// age是可选的,可以不实现
}
实现多个接口
一个类可以实现多个接口,用逗号分隔:
interface Loggable {
log(): void;
}
interface Serializable {
serialize(): string;
}
class Document implements Loggable, Serializable {
log() {
console.log("Logging document");
}
serialize() {
return "Serialized document";
}
}
接口继承与类实现
接口可以继承其他接口,类实现时需要满足继承链上的所有要求:
interface Shape {
color: string;
}
interface Square extends Shape {
sideLength: number;
}
class MySquare implements Square {
color: string = "red";
sideLength: number = 10;
}
类类型与构造函数签名
接口不仅可以描述实例结构,还可以描述类构造函数:
interface ClockConstructor {
new (hour: number, minute: number): ClockInterface;
}
interface ClockInterface {
tick(): void;
}
function createClock(
ctor: ClockConstructor,
hour: number,
minute: number
): ClockInterface {
return new ctor(hour, minute);
}
class DigitalClock implements ClockInterface {
constructor(h: number, m: number) {}
tick() {
console.log("beep beep");
}
}
class AnalogClock implements ClockInterface {
constructor(h: number, m: number) {}
tick() {
console.log("tick tock");
}
}
let digital = createClock(DigitalClock, 12, 17);
let analog = createClock(AnalogClock, 7, 32);
静态部分与实例部分
TypeScript中的类有静态部分和实例部分。实现接口时,类只检查实例部分:
interface Person {
name: string;
greet(): void;
}
class Employee implements Person {
static company = "ACME";
constructor(public name: string) {}
greet() {
console.log(`Hello, I'm ${this.name}`);
}
}
抽象类与接口
抽象类可以实现接口,但不一定要实现所有成员,可以由派生类完成:
interface Vehicle {
startEngine(): void;
stopEngine(): void;
}
abstract class Car implements Vehicle {
abstract startEngine(): void;
stopEngine() {
console.log("Engine stopped");
}
}
class SportsCar extends Car {
startEngine() {
console.log("Vroom!");
}
}
接口中的索引签名
类实现带有索引签名的接口时,需要满足索引签名的约束:
interface StringArray {
[index: number]: string;
}
class MyArray implements StringArray {
[index: number]: string;
constructor() {
this[0] = "first";
this[1] = "second";
}
}
混合类型接口
接口可以描述同时作为函数和对象的类型:
interface Counter {
(start: number): string;
interval: number;
reset(): void;
}
function getCounter(): Counter {
let counter = <Counter>function (start: number) {
return "Started at " + start;
};
counter.interval = 123;
counter.reset = () => {
console.log("Reset counter");
};
return counter;
}
let c = getCounter();
c(10);
c.reset();
c.interval = 5.0;
接口与类类型的类型检查
TypeScript使用结构性子类型进行类型检查,只要形状匹配就认为类型兼容:
interface Point {
x: number;
y: number;
}
class Point2D {
constructor(public x: number, public y: number) {}
}
let p: Point = new Point2D(1, 2); // 有效
泛型类实现泛型接口
泛型类可以实现泛型接口,类型参数可以不同:
interface Pair<T, U> {
first: T;
second: U;
}
class StringNumberPair implements Pair<string, number> {
constructor(public first: string, public second: number) {}
}
class GenericPair<T, U> implements Pair<T, U> {
constructor(public first: T, public second: U) {}
}
接口中的私有成员
从TypeScript 3.8开始,接口可以声明私有字段,但实现类必须在同一文件中:
interface PrivateExample {
#secret: string;
reveal(): string;
}
class SecretKeeper implements PrivateExample {
#secret: string;
constructor(secret: string) {
this.#secret = secret;
}
reveal() {
return this.#secret;
}
}
接口与类类型的进阶模式
结合接口和类类型可以实现更复杂的模式,如工厂模式:
interface Product {
operation(): string;
}
abstract class Creator {
public abstract factoryMethod(): Product;
public someOperation(): string {
const product = this.factoryMethod();
return `Creator: ${product.operation()}`;
}
}
class ConcreteProduct1 implements Product {
operation(): string {
return "Result of ConcreteProduct1";
}
}
class ConcreteCreator1 extends Creator {
public factoryMethod(): Product {
return new ConcreteProduct1();
}
}
接口合并与类实现
当接口合并时,类需要实现合并后的所有成员:
interface Box {
height: number;
}
interface Box {
width: number;
}
class CardboardBox implements Box {
height: number = 0;
width: number = 0;
}
类表达式实现接口
类表达式也可以实现接口:
interface Runnable {
run(): void;
}
const MyRunner = class implements Runnable {
run() {
console.log("Running");
}
};
const runner = new MyRunner();
runner.run();
接口中的调用签名与构造签名
接口可以同时包含调用签名和构造签名:
interface CallOrConstruct {
new (s: string): Date;
(n?: number): number;
}
function getDate(): CallOrConstruct {
function buildDate(s: string) {
return new Date(s);
}
buildDate.now = function(n?: number) {
return n || Date.now();
};
return buildDate as CallOrConstruct;
}
const MyDate = getDate();
const d = new MyDate("2023-01-01");
const timestamp = MyDate();
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn