面试题答案
一键面试1. 设计继承体系
首先,我们定义一些基础类和混合类(Mixin)。
基础类
// 基础类A
class A {
name: string;
constructor(name: string) {
this.name = name;
}
getName(): string {
return this.name;
}
}
// 混合类(Mixin)
type Constructor<T = {}> = new (...args: any[]) => T;
function LoggingMixin<TBase extends Constructor>(Base: TBase) {
return class extends Base {
logMessage(message: string) {
console.log(`${this.getName()}: ${message}`);
}
};
}
// 继承类B,继承自A并使用LoggingMixin
class B extends LoggingMixin(A) {
age: number;
constructor(name: string, age: number) {
super(name);
this.age = age;
}
getAge(): number {
return this.age;
}
}
2. this类型注解思路和依据
A类中的方法
getName
方法:- 注解思路:由于
getName
方法只涉及到类A
自身的属性name
,所以this
类型默认指向A
类的实例。在TypeScript中,方法内部的this
类型会根据方法所属的类来推断,这里不需要额外显式注解this
类型。 - 依据:TypeScript的类型推断机制,当方法在类中定义时,它的
this
类型会被推断为该类的实例类型。
- 注解思路:由于
LoggingMixin中的方法
logMessage
方法:- 注解思路:
logMessage
方法调用了this.getName()
,而this
应该是继承自Base
类的实例。由于Base
类可能是任意符合Constructor
类型的类,这里this
的类型应该是Base
类实例类型。但TypeScript不能直接推断出this
的准确类型,所以需要通过类型断言来明确this
的类型。 - 依据:在混合类(Mixin)中,
this
的类型在编译时不能被准确推断,因为Mixin
是一个泛型类工厂。为了确保类型安全,需要显式断言this
的类型。例如:
- 注解思路:
function LoggingMixin<TBase extends Constructor>(Base: TBase) {
return class extends Base {
logMessage(message: string) {
const self = this as InstanceType<TBase>;
console.log(`${self.getName()}: ${message}`);
}
};
}
B类中的方法
getAge
方法:- 注解思路:
getAge
方法只涉及到类B
自身的属性age
,所以this
类型默认指向B
类的实例。和A
类中的方法类似,这里不需要额外显式注解this
类型。 - 依据:同样是基于TypeScript的类型推断机制,方法在类
B
中定义,this
类型会被推断为B
类的实例类型。
- 注解思路:
通过以上设计和对this
类型注解的说明,可以确保在复杂的TypeScript继承体系(包含多层继承和混合类)中,方法的行为一致性和类型安全性。