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


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

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
Auteur

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

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
Auteur

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 ?

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
Auteur

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 :)

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
Auteur

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