在 TypeScript 中,克隆一个类的实例是指创建一个与现有实例具有相同属性和方法的新对象。当类需要知道自己的类型时(即"具有自身类类型"),我们需要使用特定的模式来实现克隆功能。
this
类型和构造函数class Cloneable {
clone(): this {
const clone = new (this.constructor as new (...args: any[]) => this)();
Object.assign(clone, this);
return clone;
}
}
class Person extends Cloneable {
constructor(public name: string, public age: number) {
super();
}
greet() {
console.log(`Hello, my name is ${this.name}`);
}
}
const john = new Person("John", 30);
const johnClone = john.clone();
johnClone.greet(); // 输出: Hello, my name is John
abstract class Cloneable<T> {
abstract clone(): T;
}
class Animal extends Cloneable<Animal> {
constructor(public species: string) {
super();
}
clone(): Animal {
return new Animal(this.species);
}
}
const dog = new Animal("Dog");
const dogClone = dog.clone();
console.log(dogClone.species); // 输出: Dog
interface Cloneable<T> {
clone(): T;
}
class Car implements Cloneable<Car> {
constructor(public model: string, public year: number) {}
clone(): Car {
return new Car(this.model, this.year);
}
}
const tesla = new Car("Model S", 2022);
const teslaClone = tesla.clone();
console.log(teslaClone.model); // 输出: Model S
原因:没有正确使用 this
类型或泛型
解决方案:
class Shape {
clone(): this {
return new (this.constructor as any)();
}
}
class Circle extends Shape {
radius: number = 1;
}
const circle = new Circle();
const clonedCircle = circle.clone(); // 正确推断为 Circle 类型
原因:直接使用 Object.assign
或展开运算符可能不会复制原型方法
解决方案:
class Widget {
id: number;
constructor(id: number) {
this.id = id;
}
display() {
console.log(`Widget ${this.id}`);
}
clone(): this {
const clone = Object.create(Object.getPrototypeOf(this));
Object.assign(clone, this);
return clone;
}
}
原因:默认克隆通常是浅拷贝,嵌套对象会被共享
解决方案:
class DeepCloneable {
data: { nested: any };
clone(): this {
const clone = new (this.constructor as new (...args: any[]) => this)();
// 深拷贝嵌套对象
clone.data = JSON.parse(JSON.stringify(this.data));
return clone;
}
}
Object.assign
或展开运算符lodash.cloneDeep
进行深拷贝通过以上方法,你可以在 TypeScript 中有效地实现具有自身类类型的实例克隆功能。
没有搜到相关的文章