我惊讶地发现Typescript允许子类在覆盖方法时在参数列表中指定更窄的类型。我必须想象这不是监督,而是Typescript团队的故意选择。但为什么?允许这种模式有什么好处?
例如:
interface Vehicle {
model: string;
}
interface TowTruck extends Vehicle {
towing: Vehicle;
}
class VehicleHelper {
stringify(vehicle: Vehicle) {
return vehicle.model;
}
}
class TowTruckHelper extends VehicleHelper {
// override parameter to be more specific than "Vehicle"
stringify(towTruck: TowTruck) {
return (
super.stringify(towTruck)
+ ' towing a '
+ super.stringify(towTruck.towing)
);
}
}
const myHelper: VehicleHelper = new TowTruckHelper();
console.log(myHelper.stringify({ model: 'Camry' }));
没有报告Typescript错误,但是运行它会抛出Uncaught TypeError: Cannot read property 'model' of undefined
。
答案 0 :(得分:3)
我相信这是设计使然。 Clas方法是双变量相关的。最初,所有函数都是双变量相关的,但是strictFunctionTypes
加强了对于不是源自方法定义的函数签名:
更严格的检查适用于所有函数类型,但源于方法或构造函数声明的函数类型除外。专门排除了方法,以确保通用类和接口(例如Array)继续保持大多数协变关系。严格检查方法的影响将是一个重大突破,因为大量泛型类型将变为不变(即使如此,我们可能会继续探索这种更严格的模式)。
实际上,如果您使用函数字段而不是方法,则对strictFunctionTypes进行定义会出现错误:
interface Vehicle {
model: string;
}
interface TowTruck extends Vehicle {
towing: Vehicle;
}
class VehicleHelper {
stringify = function (vehicle: Vehicle) {
return vehicle.model;
}
}
class TowTruckHelper extends VehicleHelper {
// Property 'stringify' in type 'TowTruckHelper' is not assignable to the same property in base type 'VehicleHelper'.
stringify = function (this: TowTruckHelper, towTruck: TowTruck) {
return (
VehicleHelper.prototype.stringify.apply(this, towTruck)
+ ' towing a '
+ VehicleHelper.prototype.stringify.apply(this, towTruck.towing)
);
}
}
const myHelper: VehicleHelper = new TowTruckHelper();
console.log(myHelper.stringify({ model: 'Camry' }));
Here也是与您描述标记为按预期工作的确切行为相关的问题。