Skip to content

Fixed an issue with mapped property symbol not displaying added | undefined when its origin symbol was optional#59957

Closed
Andarist wants to merge 12 commits intomicrosoft:mainfrom
Andarist:fix/mapped-prop-undefined-display
Closed

Fixed an issue with mapped property symbol not displaying added | undefined when its origin symbol was optional#59957
Andarist wants to merge 12 commits intomicrosoft:mainfrom
Andarist:fix/mapped-prop-undefined-display

Conversation

@Andarist
Copy link
Copy Markdown
Contributor

@Andarist Andarist commented Sep 13, 2024

fixes #59948
fixes #60411
fixes #62325

…defined` when its origin symbol was optional
@typescript-bot typescript-bot added the For Backlog Bug PRs that fix a backlog bug label Sep 13, 2024
Copilot AI review requested due to automatic review settings August 23, 2025 21:24
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR fixes an issue where mapped property symbols weren't displaying | undefined when their origin symbol was optional. The fix ensures that when TypeScript displays type information for mapped types, it correctly shows the union with undefined for properties that originated from optional properties.

  • Refactors the requiresAddingImplicitUndefined function to improve readability and fix the logic for determining when to add implicit undefined
  • Adds comprehensive test coverage with 5 new fourslash tests covering various scenarios of mapped types with optional properties

Reviewed Changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/compiler/checker.ts Refactors the logic in requiresAddingImplicitUndefined to use early returns and adds proper type checking for declared types
tests/cases/fourslash/quickInfoMappedPropertyUnionUndefined1.ts Tests mapped type behavior with exactOptionalPropertyTypes enabled
tests/cases/fourslash/quickInfoMappedPropertyUnionUndefined2.ts Tests mapped type behavior in standard strict mode
tests/cases/fourslash/quickInfoMappedPropertyUnionUndefined3.ts Tests nested mapped type transformations
tests/cases/fourslash/quickInfoMappedPropertyUnionUndefined4.ts Tests simple mapped type with required modifier
tests/cases/fourslash/quickInfoMappedPropertyUnionUndefined5.ts Tests RequiredKeys utility type scenario

Comment on lines +9 to +15
//// type Intermidiate/*1*/ = OptionalToUnionWithUndefined<{ a?: string }>;
//// type Literal/*2*/ = { a?: string | undefined };
////
//// type Res1/*3*/ = Required<Intermidiate>;
//// type Res2/*4*/ = Required<Literal>;

verify.quickInfoAt("1", `type Intermidiate = {
Copy link

Copilot AI Aug 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The type name 'Intermidiate' is misspelled. It should be 'Intermediate'.

Suggested change
//// type Intermidiate/*1*/ = OptionalToUnionWithUndefined<{ a?: string }>;
//// type Literal/*2*/ = { a?: string | undefined };
////
//// type Res1/*3*/ = Required<Intermidiate>;
//// type Res2/*4*/ = Required<Literal>;
verify.quickInfoAt("1", `type Intermidiate = {
//// type Intermediate/*1*/ = OptionalToUnionWithUndefined<{ a?: string }>;
//// type Literal/*2*/ = { a?: string | undefined };
////
//// type Res1/*3*/ = Required<Intermediate>;
//// type Res2/*4*/ = Required<Literal>;
verify.quickInfoAt("1", `type Intermediate = {

Copilot uses AI. Check for mistakes.
Comment on lines +9 to +15
//// type Intermidiate/*1*/ = OptionalToUnionWithUndefined<{ a?: string }>;
//// type Literal/*2*/ = { a?: string | undefined };
////
//// type Res1/*3*/ = Required<Intermidiate>;
//// type Res2/*4*/ = Required<Literal>;

verify.quickInfoAt("1", `type Intermidiate = {
Copy link

Copilot AI Aug 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The type name 'Intermidiate' is misspelled. It should be 'Intermediate'.

Suggested change
//// type Intermidiate/*1*/ = OptionalToUnionWithUndefined<{ a?: string }>;
//// type Literal/*2*/ = { a?: string | undefined };
////
//// type Res1/*3*/ = Required<Intermidiate>;
//// type Res2/*4*/ = Required<Literal>;
verify.quickInfoAt("1", `type Intermidiate = {
//// type Intermediate/*1*/ = OptionalToUnionWithUndefined<{ a?: string }>;
//// type Literal/*2*/ = { a?: string | undefined };
////
//// type Res1/*3*/ = Required<Intermediate>;
//// type Res2/*4*/ = Required<Literal>;
verify.quickInfoAt("1", `type Intermediate = {

Copilot uses AI. Check for mistakes.
Comment on lines +9 to +15
//// type Intermidiate/*1*/ = OptionalToUnionWithUndefined<{ a?: string }>;
//// type Literal/*2*/ = { a?: string | undefined };
////
//// type Res1/*3*/ = Required<Intermidiate>;
//// type Res2/*4*/ = Required<Literal>;

verify.quickInfoAt("1", `type Intermidiate = {
Copy link

Copilot AI Aug 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The type name 'Intermidiate' is misspelled. It should be 'Intermediate'.

Suggested change
//// type Intermidiate/*1*/ = OptionalToUnionWithUndefined<{ a?: string }>;
//// type Literal/*2*/ = { a?: string | undefined };
////
//// type Res1/*3*/ = Required<Intermidiate>;
//// type Res2/*4*/ = Required<Literal>;
verify.quickInfoAt("1", `type Intermidiate = {
//// type Intermediate/*1*/ = OptionalToUnionWithUndefined<{ a?: string }>;
//// type Literal/*2*/ = { a?: string | undefined };
////
//// type Res1/*3*/ = Required<Intermediate>;
//// type Res2/*4*/ = Required<Literal>;
verify.quickInfoAt("1", `type Intermediate = {

Copilot uses AI. Check for mistakes.
Comment on lines +12 to +18
//// type Intermidiate/*1*/ = OptionalToUnionWithUndefined<{ a?: string }>;
//// type Literal/*2*/ = { a?: string | undefined };
////
//// type Res1/*3*/ = Required<Intermidiate>;
//// type Res2/*4*/ = Required<Literal>;

verify.quickInfoAt("1", `type Intermidiate = {
Copy link

Copilot AI Aug 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The type name 'Intermidiate' is misspelled. It should be 'Intermediate'.

Suggested change
//// type Intermidiate/*1*/ = OptionalToUnionWithUndefined<{ a?: string }>;
//// type Literal/*2*/ = { a?: string | undefined };
////
//// type Res1/*3*/ = Required<Intermidiate>;
//// type Res2/*4*/ = Required<Literal>;
verify.quickInfoAt("1", `type Intermidiate = {
//// type Intermediate/*1*/ = OptionalToUnionWithUndefined<{ a?: string }>;
//// type Literal/*2*/ = { a?: string | undefined };
////
//// type Res1/*3*/ = Required<Intermediate>;
//// type Res2/*4*/ = Required<Literal>;
verify.quickInfoAt("1", `type Intermediate = {

Copilot uses AI. Check for mistakes.
Comment on lines +12 to +18
//// type Intermidiate/*1*/ = OptionalToUnionWithUndefined<{ a?: string }>;
//// type Literal/*2*/ = { a?: string | undefined };
////
//// type Res1/*3*/ = Required<Intermidiate>;
//// type Res2/*4*/ = Required<Literal>;

verify.quickInfoAt("1", `type Intermidiate = {
Copy link

Copilot AI Aug 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The type name 'Intermidiate' is misspelled. It should be 'Intermediate'.

Suggested change
//// type Intermidiate/*1*/ = OptionalToUnionWithUndefined<{ a?: string }>;
//// type Literal/*2*/ = { a?: string | undefined };
////
//// type Res1/*3*/ = Required<Intermidiate>;
//// type Res2/*4*/ = Required<Literal>;
verify.quickInfoAt("1", `type Intermidiate = {
//// type Intermediate/*1*/ = OptionalToUnionWithUndefined<{ a?: string }>;
//// type Literal/*2*/ = { a?: string | undefined };
////
//// type Res1/*3*/ = Required<Intermediate>;
//// type Res2/*4*/ = Required<Literal>;
verify.quickInfoAt("1", `type Intermediate = {

Copilot uses AI. Check for mistakes.
Comment on lines +12 to +18
//// type Intermidiate/*1*/ = OptionalToUnionWithUndefined<{ a?: string }>;
//// type Literal/*2*/ = { a?: string | undefined };
////
//// type Res1/*3*/ = Required<Intermidiate>;
//// type Res2/*4*/ = Required<Literal>;

verify.quickInfoAt("1", `type Intermidiate = {
Copy link

Copilot AI Aug 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The type name 'Intermidiate' is misspelled. It should be 'Intermediate'.

Suggested change
//// type Intermidiate/*1*/ = OptionalToUnionWithUndefined<{ a?: string }>;
//// type Literal/*2*/ = { a?: string | undefined };
////
//// type Res1/*3*/ = Required<Intermidiate>;
//// type Res2/*4*/ = Required<Literal>;
verify.quickInfoAt("1", `type Intermidiate = {
//// type Intermediate/*1*/ = OptionalToUnionWithUndefined<{ a?: string }>;
//// type Literal/*2*/ = { a?: string | undefined };
////
//// type Res1/*3*/ = Required<Intermediate>;
//// type Res2/*4*/ = Required<Literal>;
verify.quickInfoAt("1", `type Intermediate = {

Copilot uses AI. Check for mistakes.
@typescript-bot
Copy link
Copy Markdown
Collaborator

With 6.0 out as the final release vehicle for this codebase, we're closing all PRs that don't fit the merge criteria for post-6.0 patches. If you think this was a mistake and this PR fits the post-6.0 patch criteria, please post to the 6.0 iteration issue with details (specifically, which PR and which patch criteria it satisfies).

Next steps for PRs:

  • For crash bugfixes or language service improvements, PRs are currently accepted at the typescript-go repo
  • Changes to type system behavior should wait until after 7.0, at which point mainline TypeScript development will resume in this repository with the Go codebase
  • Library file updates (lib.d.ts etc) continue to live in this repo or the DOM Generator repo as appropriate

@github-project-automation github-project-automation bot moved this from Not started to Done in PR Backlog Mar 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

For Backlog Bug PRs that fix a backlog bug

Projects

Status: Done

4 participants