Skip to content

Conversation

@Andarist
Copy link
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

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.
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: Not started

2 participants