web-dev-qa-db-fra.com

Angular2 a lancé un résultat JSON sur une interface

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.

25
Don Chambers

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.

15
toskv

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:

  • Si vous savez que les données provenant de l'API sont de la bonne forme, et que vous cherchez simplement à donner à votre IDE/les informations du compilateur sur cette forme, vous pouvez caster selon la réponse de toskv.
  • Si vous n'êtes pas sûr de l'API et souhaitez que votre application lance si les données sont de la mauvaise forme, vous devrez implémenter votre propre vérification. C'est un peu de surcharge, mais cela en vaut la peine pour les applications plus grandes.

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é.

5
Matthew de Nobrega