在Typescript中,为什么对象不能在赋值时指定多余的属性,但是当使用相同的接口将其传递给函数时却可以指定?

时间:2018-09-08 09:42:11

标签: javascript typescript

我已经向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函数的对象上具有多余的属性,但是在将其分配给具有类型注释的变量时却是不允许的,它是相同的接口。

3 个答案:

答案 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类型的对象。