Website-Suche

Ein Versprechen in einer asynchronen Funktion in TypeScript zurückgeben


Meines Wissens werden diese beiden Funktionen in JavaScript dasselbe Verhalten haben:

const whatever1 = (): Promise<number> => {
    return new Promise((resolve) => {
        resolve(4);
    });
};

const whatever2 = async (): Promise<number> => {
    return new Promise((resolve) => {
        resolve(4);
    });
};

Aber TypeScript scheint die zweite nicht zu mögen, es sagt:

Type '{}' is not assignable to type 'number'.

Ist das ein Fehler in TypeScript, oder verstehe ich etwas über asynchrone Funktionen falsch?

Antwort #1

Es ist kompliziert.

Zunächst einmal, in diesem Code

const p = new Promise((resolve) => {
    resolve(4);
});

Der Typ von p wird als Promise<{}> abgeleitet. Es gibt ein offenes Problem dazu auf GitHub von TypeScript, daher könnte man argumentieren, dass dies ein Fehler ist, weil p offensichtlich (für einen Menschen) Promise<number> sein sollte.

Dann ist Promise<{}> mit Promise<number> kompatibel, weil im Grunde die einzige Eigenschaft, die ein Promise hat, die then-Methode ist, und then in diesen beiden Promise-Typen gemäß den TypeScript-Regeln für die Kompatibilität von Funktionstypen kompatibel ist. Deshalb gibt es keinen Fehler in whatever1.

Aber der Zweck von async besteht darin, so zu tun, als würde man mit tatsächlichen Werten und nicht mit Promises umgehen, und dann erhält man den Fehler in whatever2, weil {} offensichtlich nicht mit number kompatibel ist.

Also ist das async-Verhalten dasselbe, aber momentan ist ein gewisser Workaround notwendig, um Typescript dazu zu bringen, es zu kompilieren. Sie könnten einfach ein explizites generisches Argument beim Erstellen eines Promises wie folgt angeben:

const whatever2 = async (): Promise<number> => {
    return new Promise<number>((resolve) => {
        resolve(4);
    });
};

Antwort #2

Wenn Sie new Promise((resolve)... schreiben, wurde der abgeleitete Typ Promise<{}>, weil Sie new Promise<number>((resolve) hätten verwenden sollen.

Es ist interessant, dass dieses Problem erst hervorgehoben wurde, als das async-Schlüsselwort hinzugefügt wurde. Ich würde empfehlen, dieses Problem dem TS-Team auf GitHub zu melden.

Es gibt viele Möglichkeiten, wie Sie dieses Problem umgehen können. Alle folgenden Funktionen haben dasselbe Verhalten:

const whatever1 = () => {
    return new Promise<number>((resolve) => {
        resolve(4);
    });
};

const whatever2 = async () => {
    return new Promise<number>((resolve) => {
        resolve(4);
    });
};

const whatever3 = async () => {
    return await new Promise<number>((resolve) => {
        resolve(4);
    });
};

const whatever4 = async () => {
    return Promise.resolve(4);
};

const whatever5 = async () => {
    return await Promise.resolve(4);
};

const whatever6 = async () => Promise.resolve(4);

const whatever7 = async () => await Promise.resolve(4);

In Ihrer IDE werden Sie sehen können, dass der abgeleitete Typ für all diese Funktionen () => Promise<number> ist.

Verwandte Artikel