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 (eller interface)
  • transformer dataene om nødvendig via Observable.pipe
  • hvis du trenger en klasse som en datamodell, kartlegg responsen til en klasse i forrige trinn.

Relaterte artikler