mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
* Cherry-pick PR #38101 into release-3.9
Component commits:
f0aeef14bf Skip comparing optional property flag when comparing against discriminant properties
* Update LKG
Co-authored-by: Wesley Wigham <t-weswig@microsoft.com>
Co-authored-by: typescript-bot <typescript@microsoft.com>
This commit is contained in:
co-authored by
Wesley Wigham
typescript-bot
parent
cefa5f4b05
commit
f2c93987c2
+4
-4
@@ -41603,7 +41603,7 @@ var ts;
|
||||
return "continue-outer";
|
||||
if (sourceProperty === targetProperty)
|
||||
return "continue";
|
||||
var related = propertyRelatedTo(source, target, sourceProperty, targetProperty, function (_) { return combination[i]; }, false, 0);
|
||||
var related = propertyRelatedTo(source, target, sourceProperty, targetProperty, function (_) { return combination[i]; }, false, 0, strictNullChecks || relation === comparableRelation);
|
||||
if (!related) {
|
||||
return "continue-outer";
|
||||
}
|
||||
@@ -41702,7 +41702,7 @@ var ts;
|
||||
return isRelatedTo(source, addOptionality(getTypeOfSymbol(targetProp), targetIsOptional), reportErrors, undefined, intersectionState);
|
||||
}
|
||||
}
|
||||
function propertyRelatedTo(source, target, sourceProp, targetProp, getTypeOfSourceProperty, reportErrors, intersectionState) {
|
||||
function propertyRelatedTo(source, target, sourceProp, targetProp, getTypeOfSourceProperty, reportErrors, intersectionState, skipOptional) {
|
||||
var sourcePropFlags = ts.getDeclarationModifierFlagsFromSymbol(sourceProp);
|
||||
var targetPropFlags = ts.getDeclarationModifierFlagsFromSymbol(targetProp);
|
||||
if (sourcePropFlags & 8 || targetPropFlags & 8) {
|
||||
@@ -41739,7 +41739,7 @@ var ts;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (relation !== comparableRelation && sourceProp.flags & 16777216 && !(targetProp.flags & 16777216)) {
|
||||
if (!skipOptional && sourceProp.flags & 16777216 && !(targetProp.flags & 16777216)) {
|
||||
if (reportErrors) {
|
||||
reportError(ts.Diagnostics.Property_0_is_optional_in_type_1_but_required_in_type_2, symbolToString(targetProp), typeToString(source), typeToString(target));
|
||||
}
|
||||
@@ -41853,7 +41853,7 @@ var ts;
|
||||
if (!(targetProp.flags & 4194304) && (!numericNamesOnly || isNumericLiteralName(name) || name === "length")) {
|
||||
var sourceProp = getPropertyOfType(source, name);
|
||||
if (sourceProp && sourceProp !== targetProp) {
|
||||
var related = propertyRelatedTo(source, target, sourceProp, targetProp, getTypeOfSymbol, reportErrors, intersectionState);
|
||||
var related = propertyRelatedTo(source, target, sourceProp, targetProp, getTypeOfSymbol, reportErrors, intersectionState, relation === comparableRelation);
|
||||
if (!related) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
+4
-4
@@ -49915,7 +49915,7 @@ var ts;
|
||||
if (sourceProperty === targetProperty)
|
||||
return "continue";
|
||||
// We compare the source property to the target in the context of a single discriminant type.
|
||||
var related = propertyRelatedTo(source, target, sourceProperty, targetProperty, function (_) { return combination[i]; }, /*reportErrors*/ false, 0 /* None */);
|
||||
var related = propertyRelatedTo(source, target, sourceProperty, targetProperty, function (_) { return combination[i]; }, /*reportErrors*/ false, 0 /* None */, /*skipOptional*/ strictNullChecks || relation === comparableRelation);
|
||||
// If the target property could not be found, or if the properties were not related,
|
||||
// then this constituent is not a match.
|
||||
if (!related) {
|
||||
@@ -50023,7 +50023,7 @@ var ts;
|
||||
return isRelatedTo(source, addOptionality(getTypeOfSymbol(targetProp), targetIsOptional), reportErrors, /*headMessage*/ undefined, intersectionState);
|
||||
}
|
||||
}
|
||||
function propertyRelatedTo(source, target, sourceProp, targetProp, getTypeOfSourceProperty, reportErrors, intersectionState) {
|
||||
function propertyRelatedTo(source, target, sourceProp, targetProp, getTypeOfSourceProperty, reportErrors, intersectionState, skipOptional) {
|
||||
var sourcePropFlags = ts.getDeclarationModifierFlagsFromSymbol(sourceProp);
|
||||
var targetPropFlags = ts.getDeclarationModifierFlagsFromSymbol(targetProp);
|
||||
if (sourcePropFlags & 8 /* Private */ || targetPropFlags & 8 /* Private */) {
|
||||
@@ -50062,7 +50062,7 @@ var ts;
|
||||
return 0 /* False */;
|
||||
}
|
||||
// When checking for comparability, be more lenient with optional properties.
|
||||
if (relation !== comparableRelation && sourceProp.flags & 16777216 /* Optional */ && !(targetProp.flags & 16777216 /* Optional */)) {
|
||||
if (!skipOptional && sourceProp.flags & 16777216 /* Optional */ && !(targetProp.flags & 16777216 /* Optional */)) {
|
||||
// TypeScript 1.0 spec (April 2014): 3.8.3
|
||||
// S is a subtype of a type T, and T is a supertype of S if ...
|
||||
// S' and T are object types and, for each member M in T..
|
||||
@@ -50187,7 +50187,7 @@ var ts;
|
||||
if (!(targetProp.flags & 4194304 /* Prototype */) && (!numericNamesOnly || isNumericLiteralName(name) || name === "length")) {
|
||||
var sourceProp = getPropertyOfType(source, name);
|
||||
if (sourceProp && sourceProp !== targetProp) {
|
||||
var related = propertyRelatedTo(source, target, sourceProp, targetProp, getTypeOfSymbol, reportErrors, intersectionState);
|
||||
var related = propertyRelatedTo(source, target, sourceProp, targetProp, getTypeOfSymbol, reportErrors, intersectionState, relation === comparableRelation);
|
||||
if (!related) {
|
||||
return 0 /* False */;
|
||||
}
|
||||
|
||||
@@ -50065,7 +50065,7 @@ var ts;
|
||||
if (sourceProperty === targetProperty)
|
||||
return "continue";
|
||||
// We compare the source property to the target in the context of a single discriminant type.
|
||||
var related = propertyRelatedTo(source, target, sourceProperty, targetProperty, function (_) { return combination[i]; }, /*reportErrors*/ false, 0 /* None */);
|
||||
var related = propertyRelatedTo(source, target, sourceProperty, targetProperty, function (_) { return combination[i]; }, /*reportErrors*/ false, 0 /* None */, /*skipOptional*/ strictNullChecks || relation === comparableRelation);
|
||||
// If the target property could not be found, or if the properties were not related,
|
||||
// then this constituent is not a match.
|
||||
if (!related) {
|
||||
@@ -50173,7 +50173,7 @@ var ts;
|
||||
return isRelatedTo(source, addOptionality(getTypeOfSymbol(targetProp), targetIsOptional), reportErrors, /*headMessage*/ undefined, intersectionState);
|
||||
}
|
||||
}
|
||||
function propertyRelatedTo(source, target, sourceProp, targetProp, getTypeOfSourceProperty, reportErrors, intersectionState) {
|
||||
function propertyRelatedTo(source, target, sourceProp, targetProp, getTypeOfSourceProperty, reportErrors, intersectionState, skipOptional) {
|
||||
var sourcePropFlags = ts.getDeclarationModifierFlagsFromSymbol(sourceProp);
|
||||
var targetPropFlags = ts.getDeclarationModifierFlagsFromSymbol(targetProp);
|
||||
if (sourcePropFlags & 8 /* Private */ || targetPropFlags & 8 /* Private */) {
|
||||
@@ -50212,7 +50212,7 @@ var ts;
|
||||
return 0 /* False */;
|
||||
}
|
||||
// When checking for comparability, be more lenient with optional properties.
|
||||
if (relation !== comparableRelation && sourceProp.flags & 16777216 /* Optional */ && !(targetProp.flags & 16777216 /* Optional */)) {
|
||||
if (!skipOptional && sourceProp.flags & 16777216 /* Optional */ && !(targetProp.flags & 16777216 /* Optional */)) {
|
||||
// TypeScript 1.0 spec (April 2014): 3.8.3
|
||||
// S is a subtype of a type T, and T is a supertype of S if ...
|
||||
// S' and T are object types and, for each member M in T..
|
||||
@@ -50337,7 +50337,7 @@ var ts;
|
||||
if (!(targetProp.flags & 4194304 /* Prototype */) && (!numericNamesOnly || isNumericLiteralName(name) || name === "length")) {
|
||||
var sourceProp = getPropertyOfType(source, name);
|
||||
if (sourceProp && sourceProp !== targetProp) {
|
||||
var related = propertyRelatedTo(source, target, sourceProp, targetProp, getTypeOfSymbol, reportErrors, intersectionState);
|
||||
var related = propertyRelatedTo(source, target, sourceProp, targetProp, getTypeOfSymbol, reportErrors, intersectionState, relation === comparableRelation);
|
||||
if (!related) {
|
||||
return 0 /* False */;
|
||||
}
|
||||
|
||||
+4
-4
@@ -50065,7 +50065,7 @@ var ts;
|
||||
if (sourceProperty === targetProperty)
|
||||
return "continue";
|
||||
// We compare the source property to the target in the context of a single discriminant type.
|
||||
var related = propertyRelatedTo(source, target, sourceProperty, targetProperty, function (_) { return combination[i]; }, /*reportErrors*/ false, 0 /* None */);
|
||||
var related = propertyRelatedTo(source, target, sourceProperty, targetProperty, function (_) { return combination[i]; }, /*reportErrors*/ false, 0 /* None */, /*skipOptional*/ strictNullChecks || relation === comparableRelation);
|
||||
// If the target property could not be found, or if the properties were not related,
|
||||
// then this constituent is not a match.
|
||||
if (!related) {
|
||||
@@ -50173,7 +50173,7 @@ var ts;
|
||||
return isRelatedTo(source, addOptionality(getTypeOfSymbol(targetProp), targetIsOptional), reportErrors, /*headMessage*/ undefined, intersectionState);
|
||||
}
|
||||
}
|
||||
function propertyRelatedTo(source, target, sourceProp, targetProp, getTypeOfSourceProperty, reportErrors, intersectionState) {
|
||||
function propertyRelatedTo(source, target, sourceProp, targetProp, getTypeOfSourceProperty, reportErrors, intersectionState, skipOptional) {
|
||||
var sourcePropFlags = ts.getDeclarationModifierFlagsFromSymbol(sourceProp);
|
||||
var targetPropFlags = ts.getDeclarationModifierFlagsFromSymbol(targetProp);
|
||||
if (sourcePropFlags & 8 /* Private */ || targetPropFlags & 8 /* Private */) {
|
||||
@@ -50212,7 +50212,7 @@ var ts;
|
||||
return 0 /* False */;
|
||||
}
|
||||
// When checking for comparability, be more lenient with optional properties.
|
||||
if (relation !== comparableRelation && sourceProp.flags & 16777216 /* Optional */ && !(targetProp.flags & 16777216 /* Optional */)) {
|
||||
if (!skipOptional && sourceProp.flags & 16777216 /* Optional */ && !(targetProp.flags & 16777216 /* Optional */)) {
|
||||
// TypeScript 1.0 spec (April 2014): 3.8.3
|
||||
// S is a subtype of a type T, and T is a supertype of S if ...
|
||||
// S' and T are object types and, for each member M in T..
|
||||
@@ -50337,7 +50337,7 @@ var ts;
|
||||
if (!(targetProp.flags & 4194304 /* Prototype */) && (!numericNamesOnly || isNumericLiteralName(name) || name === "length")) {
|
||||
var sourceProp = getPropertyOfType(source, name);
|
||||
if (sourceProp && sourceProp !== targetProp) {
|
||||
var related = propertyRelatedTo(source, target, sourceProp, targetProp, getTypeOfSymbol, reportErrors, intersectionState);
|
||||
var related = propertyRelatedTo(source, target, sourceProp, targetProp, getTypeOfSymbol, reportErrors, intersectionState, relation === comparableRelation);
|
||||
if (!related) {
|
||||
return 0 /* False */;
|
||||
}
|
||||
|
||||
@@ -50065,7 +50065,7 @@ var ts;
|
||||
if (sourceProperty === targetProperty)
|
||||
return "continue";
|
||||
// We compare the source property to the target in the context of a single discriminant type.
|
||||
var related = propertyRelatedTo(source, target, sourceProperty, targetProperty, function (_) { return combination[i]; }, /*reportErrors*/ false, 0 /* None */);
|
||||
var related = propertyRelatedTo(source, target, sourceProperty, targetProperty, function (_) { return combination[i]; }, /*reportErrors*/ false, 0 /* None */, /*skipOptional*/ strictNullChecks || relation === comparableRelation);
|
||||
// If the target property could not be found, or if the properties were not related,
|
||||
// then this constituent is not a match.
|
||||
if (!related) {
|
||||
@@ -50173,7 +50173,7 @@ var ts;
|
||||
return isRelatedTo(source, addOptionality(getTypeOfSymbol(targetProp), targetIsOptional), reportErrors, /*headMessage*/ undefined, intersectionState);
|
||||
}
|
||||
}
|
||||
function propertyRelatedTo(source, target, sourceProp, targetProp, getTypeOfSourceProperty, reportErrors, intersectionState) {
|
||||
function propertyRelatedTo(source, target, sourceProp, targetProp, getTypeOfSourceProperty, reportErrors, intersectionState, skipOptional) {
|
||||
var sourcePropFlags = ts.getDeclarationModifierFlagsFromSymbol(sourceProp);
|
||||
var targetPropFlags = ts.getDeclarationModifierFlagsFromSymbol(targetProp);
|
||||
if (sourcePropFlags & 8 /* Private */ || targetPropFlags & 8 /* Private */) {
|
||||
@@ -50212,7 +50212,7 @@ var ts;
|
||||
return 0 /* False */;
|
||||
}
|
||||
// When checking for comparability, be more lenient with optional properties.
|
||||
if (relation !== comparableRelation && sourceProp.flags & 16777216 /* Optional */ && !(targetProp.flags & 16777216 /* Optional */)) {
|
||||
if (!skipOptional && sourceProp.flags & 16777216 /* Optional */ && !(targetProp.flags & 16777216 /* Optional */)) {
|
||||
// TypeScript 1.0 spec (April 2014): 3.8.3
|
||||
// S is a subtype of a type T, and T is a supertype of S if ...
|
||||
// S' and T are object types and, for each member M in T..
|
||||
@@ -50337,7 +50337,7 @@ var ts;
|
||||
if (!(targetProp.flags & 4194304 /* Prototype */) && (!numericNamesOnly || isNumericLiteralName(name) || name === "length")) {
|
||||
var sourceProp = getPropertyOfType(source, name);
|
||||
if (sourceProp && sourceProp !== targetProp) {
|
||||
var related = propertyRelatedTo(source, target, sourceProp, targetProp, getTypeOfSymbol, reportErrors, intersectionState);
|
||||
var related = propertyRelatedTo(source, target, sourceProp, targetProp, getTypeOfSymbol, reportErrors, intersectionState, relation === comparableRelation);
|
||||
if (!related) {
|
||||
return 0 /* False */;
|
||||
}
|
||||
|
||||
@@ -49904,7 +49904,7 @@ var ts;
|
||||
if (sourceProperty === targetProperty)
|
||||
return "continue";
|
||||
// We compare the source property to the target in the context of a single discriminant type.
|
||||
var related = propertyRelatedTo(source, target, sourceProperty, targetProperty, function (_) { return combination[i]; }, /*reportErrors*/ false, 0 /* None */);
|
||||
var related = propertyRelatedTo(source, target, sourceProperty, targetProperty, function (_) { return combination[i]; }, /*reportErrors*/ false, 0 /* None */, /*skipOptional*/ strictNullChecks || relation === comparableRelation);
|
||||
// If the target property could not be found, or if the properties were not related,
|
||||
// then this constituent is not a match.
|
||||
if (!related) {
|
||||
@@ -50012,7 +50012,7 @@ var ts;
|
||||
return isRelatedTo(source, addOptionality(getTypeOfSymbol(targetProp), targetIsOptional), reportErrors, /*headMessage*/ undefined, intersectionState);
|
||||
}
|
||||
}
|
||||
function propertyRelatedTo(source, target, sourceProp, targetProp, getTypeOfSourceProperty, reportErrors, intersectionState) {
|
||||
function propertyRelatedTo(source, target, sourceProp, targetProp, getTypeOfSourceProperty, reportErrors, intersectionState, skipOptional) {
|
||||
var sourcePropFlags = ts.getDeclarationModifierFlagsFromSymbol(sourceProp);
|
||||
var targetPropFlags = ts.getDeclarationModifierFlagsFromSymbol(targetProp);
|
||||
if (sourcePropFlags & 8 /* Private */ || targetPropFlags & 8 /* Private */) {
|
||||
@@ -50051,7 +50051,7 @@ var ts;
|
||||
return 0 /* False */;
|
||||
}
|
||||
// When checking for comparability, be more lenient with optional properties.
|
||||
if (relation !== comparableRelation && sourceProp.flags & 16777216 /* Optional */ && !(targetProp.flags & 16777216 /* Optional */)) {
|
||||
if (!skipOptional && sourceProp.flags & 16777216 /* Optional */ && !(targetProp.flags & 16777216 /* Optional */)) {
|
||||
// TypeScript 1.0 spec (April 2014): 3.8.3
|
||||
// S is a subtype of a type T, and T is a supertype of S if ...
|
||||
// S' and T are object types and, for each member M in T..
|
||||
@@ -50176,7 +50176,7 @@ var ts;
|
||||
if (!(targetProp.flags & 4194304 /* Prototype */) && (!numericNamesOnly || isNumericLiteralName(name) || name === "length")) {
|
||||
var sourceProp = getPropertyOfType(source, name);
|
||||
if (sourceProp && sourceProp !== targetProp) {
|
||||
var related = propertyRelatedTo(source, target, sourceProp, targetProp, getTypeOfSymbol, reportErrors, intersectionState);
|
||||
var related = propertyRelatedTo(source, target, sourceProp, targetProp, getTypeOfSymbol, reportErrors, intersectionState, relation === comparableRelation);
|
||||
if (!related) {
|
||||
return 0 /* False */;
|
||||
}
|
||||
|
||||
@@ -16639,7 +16639,7 @@ namespace ts {
|
||||
if (!targetProperty) continue outer;
|
||||
if (sourceProperty === targetProperty) continue;
|
||||
// We compare the source property to the target in the context of a single discriminant type.
|
||||
const related = propertyRelatedTo(source, target, sourceProperty, targetProperty, _ => combination[i], /*reportErrors*/ false, IntersectionState.None);
|
||||
const related = propertyRelatedTo(source, target, sourceProperty, targetProperty, _ => combination[i], /*reportErrors*/ false, IntersectionState.None, /*skipOptional*/ strictNullChecks || relation === comparableRelation);
|
||||
// If the target property could not be found, or if the properties were not related,
|
||||
// then this constituent is not a match.
|
||||
if (!related) {
|
||||
@@ -16737,7 +16737,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function propertyRelatedTo(source: Type, target: Type, sourceProp: Symbol, targetProp: Symbol, getTypeOfSourceProperty: (sym: Symbol) => Type, reportErrors: boolean, intersectionState: IntersectionState): Ternary {
|
||||
function propertyRelatedTo(source: Type, target: Type, sourceProp: Symbol, targetProp: Symbol, getTypeOfSourceProperty: (sym: Symbol) => Type, reportErrors: boolean, intersectionState: IntersectionState, skipOptional: boolean): Ternary {
|
||||
const sourcePropFlags = getDeclarationModifierFlagsFromSymbol(sourceProp);
|
||||
const targetPropFlags = getDeclarationModifierFlagsFromSymbol(targetProp);
|
||||
if (sourcePropFlags & ModifierFlags.Private || targetPropFlags & ModifierFlags.Private) {
|
||||
@@ -16780,7 +16780,7 @@ namespace ts {
|
||||
return Ternary.False;
|
||||
}
|
||||
// When checking for comparability, be more lenient with optional properties.
|
||||
if (relation !== comparableRelation && sourceProp.flags & SymbolFlags.Optional && !(targetProp.flags & SymbolFlags.Optional)) {
|
||||
if (!skipOptional && sourceProp.flags & SymbolFlags.Optional && !(targetProp.flags & SymbolFlags.Optional)) {
|
||||
// TypeScript 1.0 spec (April 2014): 3.8.3
|
||||
// S is a subtype of a type T, and T is a supertype of S if ...
|
||||
// S' and T are object types and, for each member M in T..
|
||||
@@ -16910,7 +16910,7 @@ namespace ts {
|
||||
if (!(targetProp.flags & SymbolFlags.Prototype) && (!numericNamesOnly || isNumericLiteralName(name) || name === "length")) {
|
||||
const sourceProp = getPropertyOfType(source, name);
|
||||
if (sourceProp && sourceProp !== targetProp) {
|
||||
const related = propertyRelatedTo(source, target, sourceProp, targetProp, getTypeOfSymbol, reportErrors, intersectionState);
|
||||
const related = propertyRelatedTo(source, target, sourceProp, targetProp, getTypeOfSymbol, reportErrors, intersectionState, relation === comparableRelation);
|
||||
if (!related) {
|
||||
return Ternary.False;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
//// [unionRelationshipCheckPasses.ts]
|
||||
const item: { foo?: undefined } | { foo: number } = null as any as { foo?: number | undefined };
|
||||
|
||||
|
||||
//// [unionRelationshipCheckPasses.js]
|
||||
"use strict";
|
||||
var item = null;
|
||||
@@ -0,0 +1,7 @@
|
||||
=== tests/cases/compiler/unionRelationshipCheckPasses.ts ===
|
||||
const item: { foo?: undefined } | { foo: number } = null as any as { foo?: number | undefined };
|
||||
>item : Symbol(item, Decl(unionRelationshipCheckPasses.ts, 0, 5))
|
||||
>foo : Symbol(foo, Decl(unionRelationshipCheckPasses.ts, 0, 13))
|
||||
>foo : Symbol(foo, Decl(unionRelationshipCheckPasses.ts, 0, 35))
|
||||
>foo : Symbol(foo, Decl(unionRelationshipCheckPasses.ts, 0, 68))
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
=== tests/cases/compiler/unionRelationshipCheckPasses.ts ===
|
||||
const item: { foo?: undefined } | { foo: number } = null as any as { foo?: number | undefined };
|
||||
>item : { foo?: undefined; } | { foo: number; }
|
||||
>foo : undefined
|
||||
>foo : number
|
||||
>null as any as { foo?: number | undefined } : { foo?: number | undefined; }
|
||||
>null as any : any
|
||||
>null : null
|
||||
>foo : number | undefined
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
// @strict: true
|
||||
const item: { foo?: undefined } | { foo: number } = null as any as { foo?: number | undefined };
|
||||
Reference in New Issue
Block a user