Skip to content

Contextually type 'await ...' whose value is unused to 'void | PromiseLike<void>' #40162

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
4 of 5 tasks
rbuckton opened this issue Aug 21, 2020 · 1 comment
Open
4 of 5 tasks
Assignees
Labels
Experimentation Needed Someone needs to try this out to see what happens Suggestion An idea for TypeScript

Comments

@rbuckton
Copy link
Member

Search Terms

contextual type await void

Suggestion

When contextually typing an await whose expression is unused, we should use the contextual type of void:

// "today" assumes https://github.com/microsoft/TypeScript/pull/39817
async function foo() {
  // today: Promise<unknown>
  // proposed: Promise<void>
  await new Promise(resolve => {
    // today: (value: unknown) => void
    // proposed: (value: void) => void
    resolve();
  });
}

A statement like await new Promise(...) is commonly used to adapt a callback-based API where the result isn't value (such as Node's fs.writeFile). Once #39817 merges, the value argument for the resolve callback will no longer be optional unless it contains void. Since the result of the await expression above is unused, we should use void as the contextual type for the await, so that the contextual type for its operand becomes void | PromiseLike<void>, thus contextually typing the Promise construction.

Checklist

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript/JavaScript code:
    • This will require testing to verify
  • 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.
@RyanCavanaugh RyanCavanaugh added Experimentation Needed Someone needs to try this out to see what happens Suggestion An idea for TypeScript labels Sep 3, 2020
@glasser
Copy link

glasser commented Oct 21, 2021

This would be super nice! For example, we have docs that encourage the pattern await new Promise(resolve => server.listen(PORT, resolve)). It would be nice if this worked without <void>, especially because it would enable the same code to work in JS and TS.

glasser added a commit to apollographql/apollo-server that referenced this issue Oct 21, 2021
TypeScript does not infer `Promise<void>` for `await new Promise(...)`
(see microsoft/TypeScript#40162) which means
that this idiom requires us to write `await new Promise<void>(...)`. But
that's not valid JS.

Fortunately @trevorblades has gifted us with a magical MultiCodeBlock
component which lets us write TypeScript and make it available to users
as both TS and JS! It runs Babel and Prettier on it but doesn't do any
type checking.

I've found all the examples that use `await new Promise` in the docs
(and the other examples on the "which package" page for consistency) and
changed them to use MultiCodeBlock.

I made some minor formatting changes to minimize the diff between the TS
and JS versions. Note that I am leaving them in apollo-server's
preferred Prettier style (single quotes, trailing commas) even though
the component runs Prettier with default options; @trevorblades says we
can get the ability to override Prettier options soon, so that can be a
follow-up PR.

Fixes #5822.
glasser added a commit to apollographql/apollo-server that referenced this issue Oct 21, 2021
TypeScript does not infer `Promise<void>` for `await new Promise(...)`
(see microsoft/TypeScript#40162) which means
that this idiom requires us to write `await new Promise<void>(...)`. But
that's not valid JS.

Fortunately @trevorblades has gifted us with a magical MultiCodeBlock
component which lets us write TypeScript and make it available to users
as both TS and JS! It runs Babel and Prettier on it but doesn't do any
type checking.

I've found all the examples that use `await new Promise` in the docs
(and the other examples on the "which package" page for consistency) and
changed them to use MultiCodeBlock.

I made some minor formatting changes to minimize the diff between the TS
and JS versions. Note that I am leaving them in apollo-server's
preferred Prettier style (single quotes, trailing commas) even though
the component runs Prettier with default options; @trevorblades says we
can get the ability to override Prettier options soon, so that can be a
follow-up PR.

Fixes #5822.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Experimentation Needed Someone needs to try this out to see what happens Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

3 participants