我已经向TypeScript's playground添加了错误代码,您将在底部的对象分配处看到该错误。
interface Car {
make: string,
model: string,
year: number
}
function repairCar(car: Car) {
}
let myCar = {
make: 'Honda',
model: 'Accord',
year: 1992,
color: 'red'
}
repairCar(myCar);
但是当我添加以下代码时:
let myCar2: Car = {
make: 'Honda',
model: 'Accord',
year: 1992,
color: 'red'
}
我收到此错误:
输入'{make:string;型号:字符串;年:数字;颜色:字符串; }' 不可分配给“汽车”类型。对象文字只能指定 属性,并且“颜色”在“汽车”类型中不存在。
我不明白为什么允许在传递给repairCar函数的对象上具有多余的属性,但是在将其分配给具有类型注释的变量时却是不允许的,它是相同的接口。
答案 0 :(得分:2)
想象一下它可以正常工作:
let myCar2: Car = {
make: 'Honda',
model: 'Accord',
year: 1992,
color: 'red'
};
然后,color属性完全是毫无意义的:
console.log(myCar2.color);
不起作用,因为颜色不是Car类型的一部分。
为什么[然后]允许在传递给repairCar函数的对象上具有多余的属性?
因为您可以将具有其他属性的对象传递给函数而没有任何副作用,而仍然在其他地方使用color属性:
repairCar(myCar);
console.log(myCar.color);
来自现实世界的例子:将鸟称为动物是没有意义的,因为如果它只是一种动物,它就不会飞行,这就是为什么我们将鸟称为鸟而不是动物。但是,如果您说动物可以移动,那么鸟也可以像动物一样移动。
如果要解决错误,只需将颜色设为可选,或使用超类型:
interface ColoredCar extends Car {
color: string;
}
// or
interface Car {
make: string,
model: string,
year: number
color?: string;
}
答案 1 :(得分:0)
Typescript中的对象仅允许具有在类型中指定的字段。与其他语言不同,我们无法定义变量来存储子类。因此,我们在编写时遇到了错误
interface Car = {
make: string,
model: string,
year: number
}
let myCar: Car = {
make: 'Honda',
model: 'Accord',
year: 1992,
color: 'red'
}
但是,Typescript允许我们使用具有方法所需的所有字段的对象来调用方法。允许这样做不会破坏方法,因为子类必须实现该方法所需的所有字段。因此,我们可以写
interface ColoredCar extends Card {
color: string
}
let myColoredCar: ColoredCar = {
make: 'Honda',
model: 'Accord',
year: 1992,
color: 'red'
}
function repairCar(car: Car) {
// Implementation...
}
// Doesn't matter for the method repairCar if myColoredCar is a ColoredCar or a Car as
// long as make, model and year are defined
repairCar(myColoredCar);
答案 2 :(得分:0)
创建类型对象在编译时进行验证。对于任何静态类型语言,该部分都是正常的。 它正在对动态obj进行隐式转换,并且由于包含必需的字段而成功。但这不必是Car类型的对象。