Prevent spreading of promises, as it's likely not intended
See original GitHub issueSuggestion
Spreading a promise in an object is correct Javascript, and Typescript allows it. But it doesn’t do anything:
{ ...Promise.resolve({ key: 42 }) } // returns {}
Any time you’re trying to spread a promise, it’s much more likely that you have an async function that you forgot to await. The following code compiles.
const myAsyncFunc = () => Promise.resolve({ key: 42 });
const result = {
foo: 'bar',
...myAsyncFunc(),
};
While this is “correct”, it’s almost certainly not what the programmer intended.
🔍 Search Terms
Spreading promise.
✅ Viability 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, new syntax sugar for JS, etc.)
- This feature would agree with the rest of TypeScript’s Design Goals.
(I’m not sure about the first point. This would be a breaking change, but it should only affect code that likely contains a bug. The feature request does support the goal of “Statically identify constructs that are likely to be errors.”)
⭐ Suggestion
Prevent code that spreads promises from compiling.
📃 Motivating Example
As it’s almost certainly unintended, Typescript should prevent promises from being spread in objects.
💻 Use Cases
This would prevent a bug that I personally faced recently. I can’t think of any scenario where someone would intentionally want to spread a promise.
An IDE or a plugin could detect that you’re spreading a function marked as async
, but I’m not sure whether they would be able to detect that a function returns a promise, or that a function returns the result of another function call that returns a promise.
Issue Analytics
- State:
- Created a year ago
- Reactions:3
- Comments:8 (4 by maintainers)
I think the specific case of disallowing spreading a
Promise
is very unobjectionable – it’s extremely obviously a mistake, and a refactoring hazard when asyncifying a sync function.A rule of “disallow spreading if there are zero enumerable properties” is overbroad, because people will sometimes write something like
wherein
opts
gets subtype-reduced to{ }
and thus has zero enumerable properties.+1