microsoft / microsoft/TypeScript
Type inference regression on function calls not saved to variables, due to #61668
- Dominant language
- Go
- Stars
- 111k
- Forks
- 14.3k
- PR merge metrics
- PR metrics pending
Description
### 🔎 Search Terms
61668 inference overload regression tuple
### 🕗 Version & Regression Information
- This changed in commit or PR #61668
### ⏯ Playground Link
https://www.typescriptlang.org/play/?ts=5.9.0-beta#code/PTAEGIDYEZMgOUBjAFgQwHYHMCmBnUAFxR1AEsMAzHAJxwyVMpoHsBbUAbQwFc2AjWgBpQeQjQpYAukRagAFLwG0APmInYAlJykAoACY4kAGzR1QlHg0JkWGULkIA5PvM0AuUAAVWbMnhwAHiVBGgA+AG4DI1NzS2tbe0cAZXE3Tx92fyD1SUjokzMmKyQbO1AeAIAVHgAHYxx5QjqGz24+UJFc7CkPUAA3FjJ9KKQ7MVBa0ABeb19sgDo6PBZjfsadTQXienk3GbC5rICFtGNjeU5HFzY3ERS0zV6tnYx5Spwa+pxNKKA
### 💻 Code
```ts
declare function getNum(): Promise;
declare function getStr(): Promise;
declare function useTuple(tuple: [number, string]): void;
const p = Promise.resolve([]).then(() => Promise.all([getNum(), getStr()])).then(useTuple);
```
### 🙁 Actual behavior
The `Promise.all` infers to `Promise<(number|string)[]>`.
### 🙂 Expected behavior
The `Promise.all` should infer `Promise<[number, string]>`.
### Additional information about the issue
This only happens when the `Promise.all` call is directly returned. If I instead write
```
const p = Promise.all([getNum(), getStr()]);
return p;
```
then it infers the tuple correctly again, even without doing anything that would suggest it should infer the type differently.
This PR also impacted inference of enums: in [another example](https://www.typescriptlang.org/play/?ts=5.9.0-beta#code/PTAEDkHkBUFEC5QHsBGBnApgJwG7baAJYEDGSAdgC5YCGONWhNVAUCQDY1oEDKArigBWGEpQA80AHygA3i1DJ02PFjSIAFOvrs+GRNACUoALzScSQgBMDAbQC6J0PYDc80GXJpqfUUizqAB0Z6SgxQAH1tXX0jGQBfFgSWDHI+AFtQAFkkSzC5BQBBRwByGmKAGjcAIRKUCsSWNk5uUB5lQhI8tzScjABCRH4hEXFs3MlXBNyOBjCAMz5yUUIKdywMGlDskgBrMUghSUCsJAC1WRsABSJyUB2MAE8kOdADwTsAfkQ3q7s4g0Q5isrjY602GG2ezauA6GCO+VAIAgMAQoGgAAtiDc5tgUp13OjmABzDCWG6gADEADYAIxUqkADm6vUQ5AwAHdWgJhKJ1GMMAA6AoGSr-EEeLygHq5RxszlDHmUPm9IUGVxIhSgAB6H1BGy2SF2YmhOFh8OlGDFLCAA), I pass `{mode: new Subject(Mode.A)}` into a function that fails because it infers `Subject` while if I save a temporary `const mode = new Subject(Mode.A);` then it infers `Subject` and passes.
Contributor guide
Research direction
Start with the linked TypeScript Playground reproduction and compare the inference change introduced by PR #61668. Trace the direct-return path for Promise.all and the contrasting temporary-variable case, then check the enum example as a second regression. Done means both examples infer the tuple and enum types as described without regressing existing behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100