Bug compilation Typescript

Par larxenne, il y a 9 ans


Bonjour,

Je commence à utiliser typescript et je fais face à un problème qui commence à me rendre fou ...

Assignation d'un type au return d'une fonction

Voila, je ne comprends pas bien comment fonctionne l'assignation de type pour une promesse.
Je vous montre 2 morceaux de code

testP(): Promise<number> { return new Promise<string>((resolve, reject) => { resolve("string"); }); }

Ce code me renvoit bien une erreur de compilation, jusque la pas de problème.

En revanche, si je transforme mon code comme ceci

testP(): Promise<number> { return new Promise((resolve, reject) => { resolve("string"); }); }

La, pas de soucis, le code se compile alors que selon moi il devrait renvoyer la même erreur que précédemment.

Je me doute que je dois faire une erreur grossière, mais je bloque complètement ...
Des idées ?

Merci d'avance !

9 réponses

Defy, il y a 9 ans

ben tu dit que testP est de type Promise number et tu veut créer une promise string

Maenhyr, il y a 9 ans

Par defaut, new Promise() est de type Promise<any> qui passe donc la validation.

testP(): Promise<number> { return new Promise((resolve, reject) => { // equivalent a new Promise<any> resolve("string"); }); }

Dans la documentation de typescript, il est indiqué ceci pour any

We may need to describe the type of variables that we do not know when we are writing an application. These values may come from dynamic content, e.g. from the user or a 3rd party library. In these cases, we want to opt-out of type-checking and let the values pass through compile-time checks

larxenne, il y a 9 ans

Defy: oui, le premier code renvoit une erreur ce qui est normal, je ne comprends pas pourquoi le second n'en renvoit pas.

Prbaron: Oui, le type par défaut est bien "any", mais le problème ne change pas.

Pourquoi:

testP(): Promise<number> { return new Promise<any>((resolve, reject) => { resolve("string"); }); }

Ne renvoit pas d'erreur.

Mais:

testP(): Promise<number> { return new Promise<string>((resolve, reject) => { resolve("string"); }); }

En renvoit une.
Je dois apsser à coté de quelque chose ...

Maenhyr, il y a 9 ans

Dans la documentation de typescript, il est indiqué ceci pour any

We may need to describe the type of variables that we do not know when we are writing an application. These values may come from dynamic content, e.g. from the user or a 3rd party library. In these cases, we want to opt-out of type-checking and let the values pass through compile-time checks

Cela signifie que ton type n'est pas analysé et qu'il assume que tu va bien renvoyer un number.

larxenne, il y a 9 ans

Ok, merci beaucoup pour ta réponse !

Mais du coup il y a quelque chose que je ne comprends pas.
J'ai fais le tuto d'angular 2: https://angular.io/docs/ts/latest/tutorial/

Et il y a une chose que je ne comprends pas.

Voila un extrait du code

import 'rxjs/add/operator/toPromise'; export class Hero { id: number; name: string; } export class HeroService { private headers = new Headers({'Content-Type': 'application/json'}); private heroesUrl = 'app/heroes'; getHeroes(): Promise<Hero[]> { return this.http.get(this.heroesUrl) .toPromise() .then(response => response.json().data) .catch(this.handleError); } }

Et maintenant, imaginons que la requette http renvoie:

[ {id: 11, name: 'Mr. Nice'}, {id: "stringId", name: 'Narco'} ]

Je m'attend à ce que mon code est un bug car un des id est un string et pas un number.

Or, rien, pas de soucis tout roule.

Pourquoi ?

Maenhyr, il y a 9 ans

Voici la définition de toPromise in rxjs

export function toPromise<T>(PromiseCtor?: typeof Promise): Promise<T> { if (!PromiseCtor) { if (root.Rx && root.Rx.config && root.Rx.config.Promise) { PromiseCtor = root.Rx.config.Promise; } else if (root.Promise) { PromiseCtor = root.Promise; } } if (!PromiseCtor) { throw new Error('no Promise impl found'); } return new PromiseCtor((resolve, reject) => { let value: any; this.subscribe((x: T) => value = x, (err: any) => reject(err), () => resolve(value)); }); }

Je pense qu'il utilise root.Promise qui est l'implémentation de window.Promise et tu coup on en revient à la même explication que plus haut, cela crée une Promise<any>.

Ceci n'est qu'une déduction cependant.

PS : data est de type any et pas de type Hero[].

larxenne, il y a 9 ans

Ok, cela confirme ce que je pensais, à savoir que le toPromise() crée une Promise<any>.

Ma question: comment faire pour que cela me déclenche une erreur si je ne recoit pas un tableux de "Hero".

Rajouter cela:

getHeroes(): Promise<Hero[]> { return this.http.get(this.heroesUrl) .toPromise() .then(response => response.json().data as Hero[]) .catch(this.handleError); }

Ne change absolument rien.

Ps: Merci pour le temps passer à me répondre :)

Maenhyr, il y a 9 ans

Je pense qu'il faudrait plutot itérer sur ton response.json().data pour créer un new Hero(). Comme ça tu es sûr de ce que tu as dans ton objet.

larxenne, il y a 9 ans

Ok je vais chercher de ce coté la alors :)
Merci beaucoup en tout cas !