microsoft / microsoft/TypeScript

Spreading object with optional property causes incorrect type inference when `exactOptionalPropertyTypes = false`

Open
#62,906 3 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Awaiting More Feedback Suggestion
Dominant language
Go
Stars
111k
Forks
14.3k
Avg merge
2d 4h
Merged PRs (30d)
132

Description

### 🔎 Search Terms

spread optional property undefined

### 🕗 Version & Regression Information

5.9.3 and others

### ⏯ Playground Link

https://www.typescriptlang.org/play/?ts=5.9.3#code/MYewdgzgLgBAhjAvDA3jAHgLhgFgEwwC+AsAFCiSwBGAjEqhtgK5gAmApgGYCWY7rRMhWgxgdZGgB00uABoY0ybSIwA9KphQAngAd2MEJ1F1uEGL07sATlf7wzaLDBYcefVgG4VAWk0ALOCgAcjNQG3ZgWEBQciFwCBAAG3ZJBJAAcwAKMQBKMljKGCo8bEcAfmwwJgBbKmsVCUZnNi5eO0I1DSg-UxhWEHYzMBBYHSsQViZgfTgwGGsxqxgAdz92WfZ0OEiAeR0obnA4BIAFMb0rbQAVXQHETiOIdnyRYAIGxTkFaSKVdU0bgxGV7mMwWeZ2OAORqVGrWLztXxdQIhZZjMBpeSQ0R4SToGAAfVM+KarlaAkAMuTPRLJVKZV65UhAA

### 💻 Code

```ts
const a = { x: 42 }
const b1 = { x: undefined }
const c1 = { ...a, ...b1 } // type of c1 is inferred as { x: undefined; } - that's correct ✅
console.log(c1)

const b2: { x?: number } = { x: undefined } // this does not produce an error when exactOptionalPropertyTypes=false
const c2 = { ...a, ...b2 } // type of c2 is inferred as { x: number; } - that's wrong, as c2.x _is_ undefined ❌
console.log(c2)
```

### 🙁 Actual behavior

I know that there have been several issues filed before like https://github.com/microsoft/TypeScript/issues/57086 / https://github.com/microsoft/TypeScript/issues/51755 / https://github.com/microsoft/TypeScript/issues/51253 / https://github.com/microsoft/TypeScript/issues/57408 and they all were closed referring to `exactOptionalPropertyTypes`.

However, reading the docs, the [description of `exactOptionalPropertyTypes`](https://www.typescriptlang.org/tsconfig/#exactOptionalPropertyTypes) says:

> exactOptionalPropertyTypes makes TypeScript truly enforce the definition provided as an optional property:
>
> const settings = getUserSettings();
> settings.colorThemeOverride = "dark";
> settings.colorThemeOverride = "light";
>
> // But not:
> settings.colorThemeOverride = undefined;
> > Type 'undefined' is not assignable to type '"dark" | "light"' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the type of the target.

So, the option changes the way, **how `?:` is defined** from "can be not present or undefined" to "can be not present, but not set to undefined".

But even when `exactOptionalPropertyTypes=false`, I don't see a reason why TS should infer an _invalid_ type in the example given above. It _knows_ that `x` can be undefined (or not present) and it _knows_ that `exactOptionalPropertyTypes=false`, so it should really infer in this case that the prop value _can_ be undefined. For me, that would appear to be a consistent implementation of the language semantics.

Or do I miss something?

### 🙂 Expected behavior

I want to rely on TS inferring correct types, also in this case.

### Additional information about the issue

Of course, this change would be a breaking change, so there could be another option to activate it.

We have a large project and there are many places (including JSON stored in customer DBs) that would need to be adjusted if we want to set `exactOptionalPropertyTypes` to true. So that's not a solution we can quickly implement.

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 TypeScript Playground example and compare its inferred types under different exactOptionalPropertyTypes settings. Read the related issues #57086, #51755, #51253, and #57408 to understand prior decisions. Done means the spread result in the reported case reflects that x may be undefined without requiring exactOptionalPropertyTypes to be enabled.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
compilers
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.