javascript - I Typescript, hvorfor er det slik at et objekt ikke kan spesifisere ekstra egenskaper ved tildeling, men det kan når det sendes til en funksjon, ved å bruke samme grensesnitt?
Jeg har lagt til koden som gir meg feilen i TypeScripts lekeplass, du vil se feilen ved objekttildelingen nederst.
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 jeg legger til denne koden:
let myCar2: Car = {
make: 'Honda',
model: 'Accord',
year: 1992,
color: 'red'
}
Jeg får denne feilen:
Type '{ make: string; model: string; year: number; color: string; }' kan ikke tildeles typen 'Car'. Objektlitteral kan bare spesifisere kjente egenskaper, og 'color' finnes ikke i typen 'Car'.
Jeg forstår ikke hvorfor det er tillatt å ha egenskapen 'excess' på objektet som sendes til funksjonen repairCar, men ikke når det blir tildelt en variabel som har en typeannotasjon, det er det samme grensesnittet.
Svar #1
Tenk deg at det ville fungere uten en feil:
let myCar2: Car = {
make: 'Honda',
model: 'Accord',
year: 1992,
color: 'red'
};
Da er fargeegenskapen helt meningsløs som:
console.log(myCar2.color);
vil ikke fungere siden farge ikke er en del av biltypen.
hvorfor er det [da] tillatt å ha overskytende egenskap på objektet som blir sendt til repairCar-funksjonen?
Fordi du kan sende videre et objekt med ekstra egenskaper til en funksjon uten noen bivirkninger, og fortsatt bruke fargeegenskapen andre steder:
repairCar(myCar);
console.log(myCar.color);
Eksempel fra den virkelige verden: Det gir ingen mening å kalle en fugl et dyr, fordi hvis det bare var et dyr, kunne det ikke fly, derfor kaller vi fugler fugler og ikke dyr. Men hvis du sier at et dyr kan bevege seg, kan en fugl også bevege seg ettersom den er et dyr.
Hvis du vil løse feilen, gjør fargen valgfri, eller bruk en supertype:
interface ColoredCar extends Car {
color: string;
}
// or
interface Car {
make: string,
model: string,
year: number
color?: string;
}
Svar #2
Objekter i Typescript har kun lov til å ha feltene spesifisert i typen. I motsetning til andre språk kan vi ikke definere en variabel for å lagre en underklasse. Derfor får vi en feil når vi skriver
interface Car = {
make: string,
model: string,
year: number
}
let myCar: Car = {
make: 'Honda',
model: 'Accord',
year: 1992,
color: 'red'
}
Imidlertid lar Typescript oss kalle metoder med objekter som har alle feltene som kreves av metoden. Å tillate dette vil ikke bryte metoden siden underklassen må implementere alle feltene som kreves av metoden. Vi kan derfor skrive
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);
