2017-02-23 4 views
1

Ich versuche Promise zu erhöhen, indem Sie eine zusätzliche Methode hinzufügen, wie in der TypeScript-Dokumentation beschrieben - Global augmentation.Erweiterung von Promise bricht Typ Rückschluss für neue Promise (...)

Und es funktioniert gut im Test 1. Aber aus irgendeinem Grund bricht es Typinferenz für das Versprechen in dem Test unter Verwendung Konstruktor erstellt 2. Typoskript Typ als Promise<boolean> stoppt Folgern und folgert sie als Promise<{}> statt. Wenn ich meine Erweiterung entferne, wird der generische Typ für Promise, der mit Konstruktor erstellt wurde, korrekt abgeleitet.

Irgendwelche Ideen, warum es passiert und wie man es repariert?

Hier ist ein vereinfachtes Beispiel dafür, was ich versuche zu tun: ist

// tsconfig.json 
{ 
    "compilerOptions": { 
     "module": "es6", 
     "target": "es6", 
     "baseUrl": "./src" 
    } 
} 

Fehler Ich erhalte:

src/test.ts(9,5): error TS2322: Type 'Promise<{}>' is not assignable to type 'Promise<boolean>'. 
    Type '{}' is not assignable to type 'boolean'. 

// src/test.ts 

// augmentation 
interface Promise<T> { 
    myCustomMethod(): T; 
} 

// test 1 
let data: number = Promise.resolve(42) 
    .then((value) => value + 4) 
    .myCustomMethod(); 

// test 2 
let p2: Promise<boolean> = new Promise((resolve) => { 
    resolve(true); 
}) 

Und meine Config UPD

Ich sehe, dass Typ immer als Promise<{}> für den Test abgeleitet wird 2. Aber jetzt kann ich nicht verstehen, warum dieser Fehler nicht ohne meine Augmentation gemeldet wird. Seit Type '{}' is not assignable to type 'boolean'., sollte dieser Fehler nicht auch ohne Vergrößerung erscheinen?

Ich versuche nur zu verstehen, ob es beabsichtigt ist oder sollte es an TypScript-Entwickler melden.

Antwort

1

Typoskript mit immer folgert Versprechen < {}> Typ für dieses Konstrukt auch ohne Ihre Augmentation:

new Promise((resolve, reject) => { 
    resolve(true); 
}) 

als durch Fehler nachgewiesen Nachricht für diese Aufgabe:

let z: void = new Promise((resolve, reject) => { 
    resolve(true); 
}) 

Typ ‚Versprechen < {}>‘ ist nicht übertragbar ‚VOID‘

So eingeben, wenn Sie myCustomMethod(): T;-Promise, als Nebeneffekt hinzufügen macht es Promise<{}> unvereinbar mit Promise<boolean>.

Entweder tun das nicht (wenn Sie myCustomMethod() auf ungelöste Versprechen nennen, wo es den T Wert bekommen es zurückgeben sollte?), Oder verwenden Sie explizite allgemeine Argument, wenn Ihr Versprechen Konstruktion:

let p2: Promise<boolean> = new Promise<boolean>((resolve) => { 
    resolve(true); 
}) 
+0

Vielen Dank für Du antwortest und machst Abhilfe. Bitte sehen Sie sich die aktualisierte Frage an. Können Sie erläutern, warum der Fehler nicht ohne meine Augmentation erscheint? –

+1

Da ohne Ihre Erweiterung "T" in "Promise" nur als Funktionsargumenttyp angezeigt wird und TypeScript über [Funktionskompatibilitätsregeln] verfügt (https://www.typescriptlang.org/docs/handbook/type-compatibility.html#) Funktion-Parameter-Bivarianz), die 'function (x: {})' kompatibel zu 'function (x: boolean)' macht, weil 'boolean' zu' {} 'zugewiesen werden kann. Wenn T als Rückgabewert verwendet wird, sind sie inkompatibel, da '{}' nicht 'boolean' zugeordnet werden kann. – artem

+1

Hier ist ein [Beispiel, das Kompatibilität für Funktionstypen demonstriert] (https://www.typescriptlang.org/play/#src=var%20f1%20%3D%20function%20 (x% 3A% 20boolean)% 3A% 20void % 20% 7B% 20% 7D% 3B% 0D% 0Avar% 20f2% 20% 3D% 20Funktion% 20 (x% 3A% 20% 7B% 7D)% 3A% 20Void% 20% 7B% 20% 7D% 3B% 0D% 0Af1% 20% 3D% 20f2% 3B% 20% 2F% 2F% 20Ok% 0D% 0Af2% 20% 3D% 20F1% 3B% 20% 2F% 2F% 20Ok% 0D% 0A% 0D% 0Avar% 20F3% 20% 3D% 20Funktion% 20()% 3A% 20Boolean% 20% 7B% 20Rückkehr% 20wahr% 7D% 3B% 0D% 0Avar% 20f4% 20% 3D% 20Funktion% 20()% 3A% 20% 7B% 7D% 20% 7B% 20Rückkehr% 20% 7B% 7D% 7D% 3B% 0D% 0Af3% 20% 3D% 20f4% 3B% 20% 2F% 2F% 20nicht% 20ok% 0D% 0Af4% 20% 3D% 20f3% 3B% 20% 2F% 2F% 20Ok% 0D% 0A) – artem

2

Der Compiler kann den Typ eines Generics aus dem Argument in einfachen Fällen wie Promise.resolve() mit einer Konstante in Promise.resolve(42) ableiten. Dies kann in komplexeren Situationen fehlschlagen, wenn der Typ nur in Ihrem Anruf bei resolve(true) sichtbar wird.

Dies ist in der TypeScript Handbook dokumentiert:

Während Typargument Inferenz ein hilfreiches Werkzeug Sie können Code kürzer und besser lesbar zu halten, müssen explizit in den Typ Argumente übergeben werden können, um, wie wir im vorigen tat Beispiel, wenn der Compiler den Typ nicht ableitet, wie es bei komplexeren Beispielen der Fall ist.

Sie können das Problem umgehen, indem

let p2: Promise<boolean> = new Promise<boolean>(resolve => { 
    resolve(true); 
});