镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

Add a new type Awaitable<T> = T | PromiseLike<T> #31394

Closed as not planned
Closed as not planned

Description

Search Terms

  • awaitable

Suggestion

Add an awaitable type for values that will be awaited.

type Awaitable<T> = T | PromiseLike<T>;

This is based on my question and a comment on StackOverflow

Use Cases

Two use cases come in mind immediately:

  1. A function accepts a callback that may either return a value synchronously, or may return a promise value. This will then probably be awaited.
  2. This is more of a specific version of 1, but this would be the return type of Promise.then() / Promise.catch / Promise.finally callbacks.

Also, this type could replace all 1334 occurrences that come up when running git grep '| Promise' in the current TypeScript code base.

Examples

Callback example:

async function logAnswer(getAnswer: () => Awaitable<number>): Promise<void> {
  const answer = await getAnswer();
  console.log(answer);
}

logAnswer(() => 42);
logAnswer(() => Promise.resolve(42));

Promise example:

Promise.resolve('Hello, world!').then(
  // This type annotation is silly. This is really just to show promise callbacks should accept `Awaitable<T>`.
  (hello): Awaitable<string> => {
    console.log(hello);
    return hello;
  },
);

Checklist

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
  • This feature would agree with the rest of TypeScript's Design Goals.

Activity

  1. fatcerberus commented on Jun 2, 2019

    @fatcerberus

    At first I didn't see the utility of this since everything in JavaScript is awaitable, but I just realized it's good for type inference:

    type Awaitable<T> = T | PromiseLike<T>;
    
    declare function foo<T>(callback: () => T): Promise<T>;
    declare function bar<T>(callback: () => Awaitable<T>): Promise<T>;
    
    const fun = () => Promise.resolve(812);
    let food = foo(fun);  // Promise<Promise<number>>, which is not actually a thing.
    let bard = bar(fun);  // Promise<number> - yes!
  2. fabiospampinato commented on Jul 2, 2019

    @fabiospampinato

    I think Promisable would be a better name than Awaitable.

    Since any value is awaitable in TS this name seems too generic to me, Promisable on the other hand says to me that the value could be actually a Promise (technically a PromiseLike, but PromiseLikeable or PromiseableLike sound awful to me).

  3. Vandivier commented on Apr 4, 2020

    @Vandivier

    I think Promisable and Awaitable are both fair, but I notice that ForAwaitable is another type under discussion and recommend that these two types are aligned regardless of the direction we go.

    #36153

  4. remcohaszing commented on Apr 6, 2020

    @remcohaszing
    Author

    Some feedback from future self: I have been using Promisable a lot. I really hope this will be a builtin type.

  5. remcohaszing commented on Nov 3, 2021

    @remcohaszing
    Author

    This was added in #45350 and will be part of TypeScript 4.5.

  6. remcohaszing commented on Nov 3, 2021

    @remcohaszing
    Author

    I misinterpreted it. It’s not the same.

  7. changed the title [-]Add a new type Awaitable[/-] [+]Add a new `type Awaitable<T> = T | PromiseLike<T>`[/+] on Nov 19, 2021
  8. MuTsunTsai commented on Nov 21, 2022

    @MuTsunTsai

    I've been using this exact definition in many of my projects for years. It will be great if this is built in.

  9. crookse commented on May 31, 2023

    @crookse

    Been using the same Promisable impl from #31394 (comment) since summertime last year. Hoping the same (it becoming a built-in)! It cuts down on a lot of code and improves the developer experience IMO.

  10. olivermrose commented on May 31, 2023

    @olivermrose

    Is this relevant anymore given #51841 (comment)?

  11. camsteffen commented on Mar 5, 2024

    @camsteffen

    I like Awaitable more than Promisable. The whole point of the type is that you can use await on the type to "unwrap" its generic type. It is a corollary to the Awaited type. Promisable to me conveys a semantic like PromiseLike which is not right.

  12. camsteffen commented on Mar 5, 2024

    @camsteffen

    Another name idea is PromiseOr<T>. The Dart language has the same concept but called FutureOr.

  13. remcohaszing commented on Mar 5, 2024

    @remcohaszing
    Author

    This issue predates that comment and its references. I still think a builtin Awaitable type would be useful, but the TypeScript team is free to close this issue if they feel otherwise.

  14. camsteffen commented on Mar 6, 2024

    @camsteffen

    I know this is closed, but I want to highlight one important argument for this type that hasn't been raised.

    The Awaitable type allows you to define function type that is "optionally async". Optionally async functions is a very widely useful pattern.

    type NumberCallback = () => Awaitable<number>;
    
    // these both work!
    const x: NumberCallback = () => 42;
    const y: NumberCallback = async () => 42;
  15. RyanCavanaugh commented on Mar 6, 2024

    @RyanCavanaugh
    Member

    The merits of an individual utility type aren't really relevant since our position is "No new utility types, at all". If the type is useful for you, you should definitely write it in your project with the definition you'd like it to have.

  16. btoo commented on Mar 27, 2024

    @btoo
    Contributor

    Ryan Cavanaugh (@RyanCavanaugh) thanks for the update - just for my own learning, is there a decision record rationalizing the "No new utility types, at all" position I can read up on? nevermind, I found it

  17. MuTsunTsai commented on Mar 29, 2024

    @MuTsunTsai

    btoo Not only that there's no such a record, they literally just added a new NoInfer utility type in v5.4 so I have no idea what he's talking about.

  18. ritschwumm commented on Mar 29, 2024

    @ritschwumm

    Mu-Tsun Tsai (@MuTsunTsai) i wouldn't call NoInfer a utility type as you cannot implement it yourself in library code.

  19. MuTsunTsai commented on Mar 29, 2024

    @MuTsunTsai

    ritschwumm Your opinion is irrelevant. They literally called it "The NoInfer Utility Type".

  20. locked as resolved and limited conversation to collaborators on Aug 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

Needs InvestigationThis issue needs a team member to investigate its status.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions