-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix for "Outlier case in Excess Property detection in Union (a case that is -more- strict than it should be)" #44856 #49004
base: main
Are you sure you want to change the base?
Conversation
Changes to be committed: modified: src/compiler/checker.ts new file: tests/baselines/reference/_44856.js new file: tests/baselines/reference/_44856.symbols new file: tests/baselines/reference/_44856.types new file: tests/cases/compiler/_44856.ts - fix for issue microsoft#44856 - minor modifications to checker.ts - Preexisting algorithm: - In the case of checking for excess properties being assigned to a union, the logic forks: - If there is an index in the union whose type qualifies it as discriminant index, then don't allow excess properties (roughly) - otherwise, allow excess properites which satisfy some member of the union - Change: - Don't consider an index with a boolean type to qualify for being a discriminant index. - Before: - In *src/compiler/checker.ts*, in the function `createUnionOrIntersectionProperty` the preexisting code is ``` if ((isLiteralType(type) || isPatternLiteralType(type) || type === uniqueLiteralType) { checkFlags |= CheckFlags.HasLiteralType; } ``` - `isLiteralType(type)` returns true for a boolean type, and setting `checkFlags |= CheckFlags.HasLiteralType` results in a higher up decision to qualify the corresponding index as a discriminated index. - After: ``` if ((isLiteralType(type) && (!fromIsDiscriminantProperty || !(type.flags & TypeFlags.Boolean && type.flags & TypeFlags.Union))) || isPatternLiteralType(type) || type === uniqueLiteralType) { checkFlags |= CheckFlags.HasLiteralType; } ``` - the `fromIsDiscriminantProperty` is to provide the context in which `createUnionOrIntersectionProperty`. - That is necessary because `createUnionOrIntersectionProperty` is called in other contexts that require the existing behavior. - Here is one such scenario from `objectSpread.ts` ``` function f<T, U>(t: T, u: U) { return { ...t, ...u, id: 'id' } } let overwriteId: { id: string, a: number, c: number, d: string } = f({ a: 1, id: true }, { c: 1, d: 'no' }) ``` - Without introducing the condition `fromIsDiscriminantProperty`, overwriteId would have type never.
This PR doesn't have any linked issues. Please open an issue that references this PR. From there we can discuss and prioritise. |
@typescript-bot run dt |
Heya @sandersn, I've started to run the diff-based community code test suite on this PR at 78b9245. You can monitor the build here. Update: The results are in! |
@sandersn |
Changes to be committed:
modified: src/compiler/checker.ts
new file: tests/baselines/reference/_44856.js
new file: tests/baselines/reference/_44856.symbols
new file: tests/baselines/reference/_44856.types
new file: tests/cases/compiler/_44856.ts
fix for issue Outlier case in Excess Property detection in Union (a case that is -more- strict than it should be) #44856
minor modifications to checker.ts
Preexisting algorithm:
Change:
Before:
createUnionOrIntersectionProperty
the preexisting code isisLiteralType(type)
returns true for a boolean type, and settingcheckFlags |= CheckFlags.HasLiteralType
results in a higher up decision to qualify the corresponding index as a discriminated index.After:
fromIsDiscriminantProperty
is to provide the context in whichcreateUnionOrIntersectionProperty
.createUnionOrIntersectionProperty
is called in other contexts that require the existing behavior.objectSpread.ts
fromIsDiscriminantProperty
, overwriteId would have type never.Fixes #44856