typescript - I Angular 9, hvordan tvinge datatypen for en egenskap i HTTP-klientens responssmodell?
Jeg jobber med et Angular 9-prosjekt, og en av responsene jeg mottar inneholder en egenskap av typen Date, men når jeg sender en forespørsel:
// MyModel
class MyModel {
prop: string;
myDate: Date;
}
// request sent like
this.http.get<MyModel>(url);
Responsen kommer korrekt, men egenskapen fylles som en string i ISO-format (f.eks: 2020-11-24T19:48:20.3637502) (fordi det i JSON ikke finnes noen type for Date). Det jeg trenger er at når jeg oppretter en instans av MyModel eller tildeler en verdi til myDate-egenskapen, skal det alltid være en Date.
Finnes det en måte å gjøre dette på annet enn å bruke en map etter å ha mottatt svaret?
Jeg prøvde dette, men det fungerte ikke:
class MyModel {
prop: string;
private _myDate: Date;
public get myDate() {
return this._myDate;
};
public set myDate(val) {
this._myDate = new Date(val);
};
}
Svar #1
Den enkleste måten er å kartlegge de returnerte dataene og gjøre endringen manuelt.
this.httpClient.get<DataModel>("/api/getData")
.pipe(
map((data)=>{
data.date1 = new Date(data.date1);
data.date2 = new Date(data.date2);
data.date3 = new Date(data.date3);
return data;
})
);
Merk at jeg jukser litt - Date-konstruktøren kan ta både streng og Date som parameter. Generelt kan resultatet av kartleggingssteget ha en annen type enn den mottatte responsen.
Alternativt kan du bruke en Http-interceptor.
Se datohåndtering i Angular-applikasjon (Del 2 - Angular Http Client og Ngx Datepicker)
I tillegg, som du la merke til, er ikke typen du spesifiserer for http get påtvunget på noen måte. Du mottar resultatet av en json-deserialisering.
Merk at dette er spesielt vanskelig hvis du bruker en class, ikke en type som din datamodell. Selv i tilfelle feltene du mottar er det du forventer, er ikke prototype-kjeden etablert, så ethvert metodekall på mottatt objekt vil resultere i en kjøretidsfeil.
Dette forklarer også hvorfor forsøket ditt med get og set mislyktes - objektet du mottar er ikke en instans av MyModel-klassen.
Mitt råd er å
- modellér responsdataene som en
type(ellerinterface) - transformer dataene om nødvendig via Observable.pipe
- hvis du trenger en klasse som en datamodell, kartlegg responsen til en klasse i forrige trinn.
