Mengembalikan sebuah promise dalam fungsi async di TypeScript


Pemahaman saya adalah bahwa kedua fungsi ini akan memiliki perilaku yang sama di JavaScript:

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

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

Tapi sepertinya TypeScript tidak menyukai yang kedua, itu mengatakan:

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

Apakah ini bug di TypeScript, atau apakah saya salah paham tentang fungsi async?

Jawaban #1

Ini rumit.

Pertama-tama, dalam kode ini

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

tipe dari p ditafsirkan sebagai Promise<{}>. Ada masalah terbuka tentang ini di GitHub TypeScript, jadi bisa dikatakan ini adalah bug, karena jelas (bagi manusia), p seharusnya Promise<number>.

Maka, Promise<{}> kompatibel dengan Promise<number>, karena pada dasarnya satu-satunya properti yang dimiliki oleh promise adalah metode then, dan then kompatibel dalam kedua tipe promise ini sesuai dengan aturan TypeScript untuk kompatibilitas tipe fungsi. Itulah mengapa tidak ada kesalahan pada whatever1.

Tapi tujuan dari async adalah untuk berpura-pura bahwa Anda sedang menangani nilai sebenarnya, bukan janji, dan kemudian Anda mendapatkan kesalahan di whatever2 karena {} jelas tidak kompatibel dengan number.

Jadi perilaku async tetap sama, tetapi saat ini diperlukan beberapa solusi sementara agar TypeScript dapat mengompilasinya. Anda bisa langsung memberikan argumen generik secara eksplisit saat membuat promise seperti ini:

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

Jawaban #2

Ketika Anda melakukan new Promise((resolve)... tipe yang ditafsirkan adalah Promise<{}> karena seharusnya Anda menggunakan new Promise<number>((resolve).

Menariknya, masalah ini baru disorot ketika kata kunci async ditambahkan. Saya akan menyarankan untuk melaporkan masalah ini ke tim TS di GitHub.

Ada banyak cara yang bisa Anda lakukan untuk mengatasi masalah ini. Semua fungsi berikut memiliki perilaku yang sama:

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

Di IDE Anda, Anda akan dapat melihat bahwa tipe yang diinferensikan untuk semua fungsi ini adalah () => Promise<number>.

Artikel terkait