En utilisant Angular2 et TypeScript, j'ai le retour JSON d'un webApi et j'ai besoin de le mettre dans un tableau d'un certain type. Je n'arrive pas à comprendre comment convertir le json sur l'interface dont j'ai besoin.
Mon type est cette interface:
export interface Country {
Id: number;
Name: string;
}
Ma maquette renvoie ce tableau:
export var COUNTRIES: Country[] = [
{ "Id": 11, "Name": "US" },
{ "Id": 12, "Name": "England" },
{ "Id": 13, "Name": "Japan" }
];
Voici mon code: country.service.ts
@Injectable()
export class CountryService {
private _http = null;
constructor(http: Http) {
this._http = http;
}
getCountries() {
return Promise.resolve(COUNTRIES);
}
}
Ensuite, je l'appelle avec ceci:
export class CountryPickerComponent {
public countries: Country[];
constructor(private _countryService: CountryService) { }
getCountries() {
this._countryService.getCountries().then(data => this.setData(data));
}
setData(data) {
//this.countries = data;
this.countries = JSON.parse(data);
var q = 1;
}
ngOnInit() {
this.getCountries();
}
}
Comme vous pouvez le voir, j'ai une variable de classe appelée country qui est un tableau de l'interface Country. Cela fonctionne comme prévu. (Je sais que je n'ai pas besoin de cette méthode setData - c'est pour le débogage)
Ensuite, j'ai changé le service en un appel wepApi qui renvoie ce json.
"[{"name":"England","id":1},{"name":"France","id":2}]"
J'ai changé la méthode getCountries du service pour:
getCountries() {
return new Promise(resolve=>
this._http.get('http://localhost:63651/Api/membercountry')
.subscribe(data => resolve(data.json()))
);
}
En utilisant JSON.parse, je le convertis en un tableau que je peux ensuite utiliser dans angular2. Ça marche. Il crée le tableau avec les données. Mais ce n'est pas un tableau implémentant l'interface Country.
Notez que les noms de champ du JSON sont tous en minuscules, mais les propriétés de l'interface commencent par une majuscule et j'ai codé pour l'interface. Du coup, quand j'ai eu le vrai json ça ne marche pas. Existe-t-il un moyen de "diffuser" cela sur l'interface, ce qui devrait générer une erreur et me faire savoir que quelque chose ne va pas?
De nombreux exemples utilisent la carte dans le get comme indiqué ci-dessous:
getCountries() {
var retVal;
return new Promise(resolve=>
this._http.get('http://localhost:63651/Api/membercountry')
.map(ref => ref.json())
.subscribe(data => resolve(data.json()))
);
}
Je ne trouve pas de documentation à ce sujet. Quand je l'essaye, je n'ai jamais de données mais il n'y a pas d'erreur. Aucune erreur de compilation et aucune erreur d'exécution.
Vous pouvez faire une assertion de type à l'interface que vous attendez sur l'objet créé par JSON.parse.
this.http.get('http://localhost:4200/').subscribe((value: Response) => {
let hero = <ServerInfo>value.json();
});
Cependant, cela n'entraînera aucune erreur si le serveur vous envoie de mauvais objets pour 2 raisons.
Au moment de la compilation, le transpilateur ne sait pas ce que le serveur enverra.
Au moment de l'exécution, toutes les informations de type sont effacées car tout est compilé en javascript.
Viktor Savkin a une bibliothèque pour vérifier les types d'exécution pour ce genre de situation mais cela ne fonctionne pas avec les interfaces car TypeScript n'exporte pas les informations d'exécution sur les interfaces. Il y a une discussion à ce sujet ici .
Il y a deux solutions possibles:
En général, je vois les types de TypeScript comme des indices de compilation plus qu'un système de type rigoureux - il doit finalement être compilé dans un langage non typé.