Skip to content

Conversation

ahejlsberg
Copy link
Member

This PR modifies type relationship checking such that types with extra properties are never subtypes of fresh object literals. This in turn ensures that fresh object literal types are subtypes of regular object types with optional properties that aren't specified in the fresh object literal types. For example, with this PR the fresh object literal type { valid: boolean } is a subtype of the regular type { valid: boolean; msg?: undefined; }, but not vice-versa, where previously both were subtypes of each other.

Fixes #1742.

@Copilot Copilot AI review requested due to automatic review settings September 28, 2025 15:01
Copy link
Contributor

@Copilot 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 modifies type relationship checking to enforce that types with extra properties are never subtypes of fresh object literals. This ensures proper asymmetric subtyping relationships where fresh object literal types are subtypes of regular object types with optional properties, but not vice-versa.

Key changes:

  • Updated property relationship checking logic to only check for excess properties when the target is a fresh object literal
  • Removed the undefined type checking condition that was preventing proper subtype relationships
  • Added comprehensive test coverage for the fresh object literal subtype behavior

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
testdata/tests/cases/compiler/freshObjectLiteralSubtype.ts New test case demonstrating the fresh object literal subtype behavior and reproducing the issue from #1742
testdata/baselines/reference/compiler/freshObjectLiteralSubtype.types Expected type checking output for the new test case
testdata/baselines/reference/compiler/freshObjectLiteralSubtype.symbols Expected symbol resolution output for the new test case
internal/checker/relater.go Core logic change to restrict excess property checking to fresh object literals only

Comment on lines +4156 to 4165
if target.objectFlags&ObjectFlagsFreshLiteral != 0 {
for _, sourceProp := range excludeProperties(r.c.getPropertiesOfType(source), excludedProperties) {
if r.c.getPropertyOfObjectType(target, sourceProp.Name) == nil {
sourceType := r.c.getTypeOfSymbol(sourceProp)
if sourceType.flags&TypeFlagsUndefined == 0 {
if reportErrors {
r.reportError(diagnostics.Property_0_does_not_exist_on_type_1, r.c.symbolToString(sourceProp), r.c.TypeToString(target))
}
return TernaryFalse
if reportErrors {
r.reportError(diagnostics.Property_0_does_not_exist_on_type_1, r.c.symbolToString(sourceProp), r.c.TypeToString(target))
}
return TernaryFalse
}
}
}
Copy link
Preview

Copilot AI Sep 28, 2025

Choose a reason for hiding this comment

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

The excess property checking logic has been simplified but the removal of the undefined type check may be too broad. The previous logic if sourceType.flags&TypeFlagsUndefined == 0 ensured that undefined properties weren't considered excess properties, which might be important for optional property handling. Consider whether this check should be preserved to maintain correct behavior for optional properties.

Copilot uses AI. Check for mistakes.

Copy link
Member Author

Choose a reason for hiding this comment

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

This is intended.

@ahejlsberg ahejlsberg added this pull request to the merge queue Sep 28, 2025
ahejlsberg added a commit to microsoft/TypeScript that referenced this pull request Sep 28, 2025
Merged via the queue into main with commit 206bc9c Sep 28, 2025
22 checks passed
@ahejlsberg ahejlsberg deleted the fix-1742 branch September 28, 2025 21:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Different return type inference when union with common members is reduced
2 participants