让我们说我有两个从某个接口继承的类:(为简单起见,将其简化)
interface IVehicle {}
class Car implements IVehicle {
constructor(public color: string) {}
}
class Helicopter implements IVehicle {}
我现在有了一个给定实例(类型扩展为IVehicle
)的函数,该函数将返回相同类型的新实例
function clone<T extends IVehicle>(element: T): T {
if (element instanceof Car) {
return new Car(element.color);
}
...
return element;
}
clone(new Helicopter())
但是我在return new Car(...)
周围看到一条错误消息:
'Car' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'IVehicle'
哪个似乎不正确,因为instanceof
应该证明T
是子类型Car
正确吗?
之后,我尝试使用T
将返回类型转换为类型return new Car(element.color) as T;
。
但这现在会产生此错误:
Conversion of type 'Car' to type 'T' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
并包含第一个错误。
TypeScript是否遇到了合法的类型问题,或者这是错误?我是否缺少类型约束中的某些内容?如何解决此错误?
答案 0 :(得分:1)
如果您打算克隆IVehicle实例,我认为将此操作添加到接口本身是一个很好的解决方案。
interface IVehicle<ActualType> {
clone(): ActualType;
}
class Car implements IVehicle<Car> {
constructor(public color: string) {}
clone(): Car {
return new Car(this.color);
}
}
class Helicopter implements IVehicle<Helicopter> {
clone(): Helicopter {
return new Helicopter();
}
}
const h = new Helicopter();
const hClone = h.clone();
更新
如果您不能修改Vehicles的来源,并且子类形成一个封闭的集合,则可以使用方法重载
interface IVehicle {}
class Car implements IVehicle {
constructor(public color: string) {}
}
class Helicopter implements IVehicle {}
function clone(element: Car): Car;
function clone(element: Helicopter): Helicopter;
function clone(element: IVehicle): IVehicle {
if (element instanceof Car) {
return new Car(element.color);
} else if (element instanceof Helicopter) {
return new Helicopter();
} else {
throw new Error("Unknown subclass of IVehicle passed to clone " + element)
}
}
const h = new Helicopter();
const h1 = clone(h);