Skip to content

Ditch the requirement of wrapping async return type in a Promise #45387

Closed
@parzhitsky

Description

@parzhitsky

Originally posted by @parzhitsky in #33595 (comment)

Okay, so, if I understand correctly, you are saying that this is wrong (or weird at least):

async function doStuff(): string {

… and so is this:

async function doStuff(): string | Promise<string> {

But there are situations when you can’t really control the structure of the type union, since you don’t create it, like here:

import type ApiResponse from "some-library/types";
import { onlyAcceptsApiResponse } from "some-library";

declare function doStuff(): ApiResponse<string>;

onlyAcceptsApiResponse(doStuff());

… and if ApiResponse<string> in the example above turns out to resolve to string | Promise<string>, you cannot use async keyword anymore, and forced to fallback to .thens and .catches if working with promises.

But you also cannot do this:

type UnwrapPromise<Value> =
  Value extends PromiseLike<infer Bare> ? UnwrapPromise<Bare> : Value;

type PromiseOnly<Value> =
  Promise<UnwrapPromise<Value>>;

async function doStuff(): PromiseOnly<ApiResponse<string>> {

… because, while it works, it also requires for you to a) know the implementation of ApiResponse (which you shouldn’t know), and b) navigate your way through unreasonable TypeScript compiler errors that don’t bring any value.

Is this correct?

If it is, then I agree with the proposal. Not only that, I would actually go a bit further, and propose to remove the distinction between “bare” and promise-wrapped values in return signatures of async functions altogether. Meaning that these signatures:

async function doStuff(): string {
async function doStuff(): Promise<string> {

… should be considered indistinguishably identical.

Metadata

Metadata

Assignees

No one assigned

    Labels

    DuplicateAn existing issue was already created

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions