TypeScript-generics: vad händer om typerna för avvisning och upplösning i Promise skiljer sig?


En enkel och vanlig Angular2+-datatjänst som hanterar fel och använder Promises:

// imports skipped

class DataType {}

class Error {
  constructor(error: HttpResponse) {
    this.error = error.json()
  }
}


@Injectable()
export class MyService<DataType> {
  apiUrl = 'my/url';
  constructor(protected http) {}

  get(): Promise<DataType[] | Error> {
    return this.http
    .get(this.apiUrl)
    .toPromise()
    .then(response => response.json())
    .catch(this.handleError);
  }

  protected handleError(error: HttpResponse): Promise<Error> {
    console.error('An error occurred', error);
    return Promise.reject(new Error(error));  
  }
}

I den här klassen returnerar get-metoden ett Promise, som löses med en DataType[]-array och avvisas med typen Error.

När jag kompilerar den här koden får jag det här felet:

Typen 'Error | DataType[]' kan inte tilldelas typen 'DataType'. Typen 'Error' kan inte tilldelas typen 'DataType'.

Jag använder TypeScript version 2.4.2. Jag är säker på att detta började hända efter uppgraderingen av TypeScript, vilket gjorde typerkontrollerna mer strikta.

Jag vill veta hur man hanterar avslag med olika typer i den senaste versionen av TypeScript. Finns det olika metoder för att göra detta?

Uppdatering: Jag har hittat en motsvarande bugg-rapport, inte löst än https://github.com/Microsoft/TypeScript/issues/7588

UPPDATERING

Jag har skapat ett repo som demonstrerar problemet, med två commits. Första commit använder <TypeResolve | TypeReject>-metoden, den andra använder endast <TypeResolved>. Båda commits verkar inte kompilera i verkligheten.

Svar #1

Typ-parametern för Promise är endast typen för .resolve, inte för .reject. Typen för .reject är alltid any, eftersom typen inte kan vara känd vid kompileringstid. En av anledningarna till detta är att async-funktioner, som returnerar promises, potentiellt kan avvisa sina promises med vilket undantag som helst.

Du bör skriva Promise<DataType[]> istället, och kontrollera feltypen vid körning där du hanterar fel.

Relaterade artiklar