javascript - I Typescript, varför är det så att ett objekt inte kan ange överflödiga egenskaper vid tilldelning men det kan när det skickas till en funktion, med samma Interface?


Jag har lagt till koden som ger mig felet i TypeScripts lekplats, du kommer att se felet vid objekttilldelningen längst ner.

interface Car {
    make: string,
    model: string,
    year: number
}

function repairCar(car: Car) {

}

let myCar = {
    make: 'Honda',
    model: 'Accord',
    year: 1992,
    color: 'red'
}

repairCar(myCar);

Men när jag lägger till denna kod:

let myCar2: Car = {
    make: 'Honda',
    model: 'Accord',
    year: 1992,
    color: 'red'
}

Jag får det här felet:

Typen '{ make: string; model: string; year: number; color: string; }' kan inte tilldelas typen 'Car'. Objektliteral kan endast ange kända egenskaper, och 'color' finns inte i typen 'Car'.

Jag förstår inte varför det är tillåtet att ha egenskapen 'excess' på objektet som skickas till funktionen repairCar men inte vid tillfället när det tilldelas en variabel som har en typannotering, det är samma gränssnitt.

Svar #1

Föreställ dig att det skulle fungera utan ett fel:

  let myCar2: Car = {
    make: 'Honda',
    model: 'Accord',
    year: 1992,
    color: 'red'
 };

Då är färgegenskapen helt meningslös eftersom:

 console.log(myCar2.color);

kommer inte att fungera eftersom färg inte är en del av biltypen.

varför är det [då] tillåtet att ha den extra egenskapen på objektet som skickas till funktionen repairCar?

Eftersom du kan vidarebefordra ett objekt med ytterligare egenskaper till en funktion utan några bieffekter, och fortfarande använda färgegenskapen någon annanstans:

 repairCar(myCar);
 console.log(myCar.color); 

Exempel från verkligheten: Det är inte logiskt att kalla en fågel för ett djur, eftersom om det bara är ett djur skulle den inte kunna flyga, därför kallar vi fåglar fåglar och inte djur. Men om du säger att ett djur kan röra sig, kan en fågel också röra sig eftersom det är ett djur.

Om du vill åtgärda felet kan du göra färgen valfri, eller använda en supertyp:

 interface ColoredCar extends Car {
   color: string;
 }

 // or

 interface Car {
  make: string,
  model: string,
  year: number
  color?: string;
 }

Svar #2

Objekt i Typescript får endast ha de fält som anges i typen. Till skillnad från andra språk kan vi inte definiera en variabel för att lagra en subklass. Därför får vi ett fel när vi skriver

interface Car = {
    make: string,
    model: string,
    year: number
}

let myCar: Car = {
    make: 'Honda',
    model: 'Accord',
    year: 1992,
    color: 'red'
}

Men Typescript tillåter oss att kalla på metoder med objekt som har alla fält som krävs av metoden. Att tillåta detta kommer inte att bryta metoden eftersom subklassen måste implementera alla fält som krävs av metoden. Vi kan därför skriva

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);

Relaterade artiklar