microsoft / microsoft/TypeScript

Object properties are inferred in the wrong order: should infer properties with `NoInfer<T>` AFTER properties with `T`

Open
#63,378 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Domain: check: Type Inference Possible Improvement
Dominant language
Go
Stars
111k
Forks
14.3k
Avg merge
2d 4h
Merged PRs (30d)
132

Description

### 🔎 Search Terms

NoInfer
brittle inference
object properties

Related issues:
- https://github.com/microsoft/TypeScript/issues/56297 : inference depends on the order of the properties. This explains the inconsistency in my issue.

### 🕗 Version & Regression Information

Tested in 6.0.2 and nightly.

### ⏯ Playground Link

[Playground Link](https://www.typescriptlang.org/play/?noUnusedLocals=true&noUnusedParameters=true&exactOptionalPropertyTypes=true&noPropertyAccessFromIndexSignature=false&ts=6.0.0-dev.20260401#code/KYDwDg9gTgLgBDAnmYcASEIGsDOd8C8cASsAMbQAmAPDjFAJYB2A5gDRwAUAdLwIZQWOAFxw+TRAG0AugEo4BAHxiJigNwAoDUhRwA6gxgALDNhzUAKnFAxgTSnlO5lRAN5HMuURYC+mnagA4sAwTuZWNnYO+oYmnubiiIqKGviEcBEgtvZ4BsZh1MwAZsBQ6MoA-OhwokzAAG6lanBaAejxAExo4pQANqXmaNZZUY7xLnCuqWmSANJwzHBYwIgQRdV8eAAGACSuswBkdIysPlvSomhz0tP4APR3C+sA7qhQwAC2EI1ieEpwlAgcCYEHgz2gWBUiC+724Gj8WlAkFgCyYtigRT4ZFQAGEIGioBBev0oJZhtlomFlFM0nAPGZvJofBoyL1NngAFqTW50+IKSZFTCiTgAfQYogAzAAWWT-Vw+BHM7TIXH4+hEkkABUJ9QYlFK1BxAHkAHIWYhGgAyloAosRyaM4HiCRqDYlkvzODzaT7fX7fTABCwQpcLABZW39D52eAPJ5wV5wd5fH6GBZgiE4OH+nO5uDyf7Gs0W612xHgaDwNoANQYwGeADEsTBoIgAIKCcxF81W232yI5J1qwnEt2qCY0v0UF2jqDa7560qiZ3q2fz3X60ndkt9xRsHk+OAHbnetJ8GCBshGFcjkkVYWnvN+uMMF5vT7fVCGDiA4A4JgAOQZlAWDZk+ebTquJKiCaEAAJJMCUW6mj2pbECk4F+gWyj1BAer7rSh7HpqAgwAwfC9NQwShD0JI4A2hIfNQsEIUhhooTudrJBhaQvm+SYfj8JGwORlHKMYdgLPydSNGUnB6BYDYVLIrQqnA1HdPYdEMRATHbr2doOoON6uqS7o8ekYRdLRAxUSEBT6WhySaLSfEJqgACuOBBPZ8TscWBnoQoygMPyiRcApSkqRoSKVgCwCYh5vTwEUHlMGQZH4nAZDvOewC1vWOJsjg5iPphaSOX2RnRCZs7UO6ZVPooXpPiKQYiHABWNs2rYdkI-mobuZXyPKWh3AAVONdxaDlwB5V1RXspwk73I8r7uXAYAefAaZ8EU6JiBeWLXsOpmcLIHBpr+-5AQmEJgatd0gXg62Jt58BIr0DBkIYvSIAgRioG0axwCKZAPdlp1rjqi5QMKYPYcC9ZwBy537jybmJsmn7pnA0CbdtuN7QdgoQGjuPXYBwGgTy56XidM4kqKABeI0+ARaSk6KDBs-CshqEAA)

### 💻 Code

See playground for the full example.
```ts
type fooArgs = {
a: (_: A) => X,
// note: NoInfer> better than Y>, doesn't change this issue though
b: NoInfer>
}

function foo(args: fooArgs) {}

foo({
a: (_) => ...,
b: ... // inference of the value given to b is VERY brittle.
});
```

### 🙁 Actual behavior

Sometimes, `b` is inferred before `a`.

Then, as `a` is the one used to infer the generic parameter `T`, the value given to `b` doesn't have the correct type (because inferred before `a`).
This is likely due to the fact that the value given to `a` is a callback with a parameter we didn't specify the type (`(_) => ...`). Therefore, TS has first to look at `fooArgs` to infer the callback's parameter type (i.e. the type of `_`).

Due to that, `b` is sometime inferred before `a` has been properly inferred. This behavior depends on the order of the object properties (cf related issue). It is also influenced by other defined properties, and how they are defined. Making the inference quite chaotic.

### 🙂 Expected behavior

TS should infer `NoInfer` properties AFTER `T` properties, in order to prevent such issues.

### Additional information about the issue

The fact that the order of the inference changes is quite troublesome, hiding the issue in some cases.

Could be nice to have a kind of tool/flag to detect such kind of potential issues, and to help debugging.

_EDIT:_ A possible workaround:

```ts
type fooArgs = {
b: Y
}

function foo(a: (_: A) => X, args: NoInfer>) {}

foo(
a: (_) => ..., {
b: ...
});
```

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the linked Playground and the reduced fooArgs/foo example, varying object-property order and callback parameter annotation. Compare the behavior with related issue #56297 while tracing how NoInfer properties are inferred. Done means the example consistently infers T from T-bearing properties before NoInfer properties, with the reported order-dependent behavior addressed.

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
Quiet
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.