From 3aa4762ebfea564a5742b1b6e47a373de04d5f7c Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 2 Apr 2020 12:23:56 -0700 Subject: [PATCH 1/6] Elaborate on reasons for 'never' intersections --- src/compiler/checker.ts | 65 +++++++++++++++++++--------- src/compiler/diagnosticMessages.json | 12 +++-- src/compiler/types.ts | 4 +- 3 files changed, 55 insertions(+), 26 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8271e252304c8..6317839d9d7e0 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4150,7 +4150,9 @@ namespace ts { return undefined!; // TODO: GH#18217 } - type = getReducedType(type); + if (!(context.flags & NodeBuilderFlags.NoTypeReduction)) { + type = getReducedType(type); + } if (type.flags & TypeFlags.Any) { context.approximateLength += 3; @@ -8412,17 +8414,20 @@ namespace ts { error(baseTypeNode.expression, Diagnostics.No_base_constructor_has_the_specified_number_of_type_arguments); return type.resolvedBaseTypes = emptyArray; } - baseType = getReducedType(getReturnTypeOfSignature(constructors[0])); + baseType = getReturnTypeOfSignature(constructors[0]); } if (baseType === errorType) { return type.resolvedBaseTypes = emptyArray; } - if (!isValidBaseType(baseType)) { - error(baseTypeNode.expression, Diagnostics.Base_constructor_return_type_0_is_not_an_object_type_or_intersection_of_object_types_with_statically_known_members, typeToString(baseType)); + const reducedBaseType = getReducedType(baseType); + if (!isValidBaseType(reducedBaseType)) { + const elaboration = baseType.flags & TypeFlags.Intersection && reducedBaseType.flags & TypeFlags.Never ? elaborateNeverIntersection(/*errorInfo*/ undefined, baseType) : undefined; + const diagnostic = chainDiagnosticMessages(elaboration, Diagnostics.Base_constructor_return_type_0_is_not_an_object_type_or_intersection_of_object_types_with_statically_known_members, typeToString(reducedBaseType)); + diagnostics.add(createDiagnosticForNodeFromMessageChain(baseTypeNode.expression, diagnostic)); return type.resolvedBaseTypes = emptyArray; } - if (type === baseType || hasBaseType(baseType, type)) { + if (type === reducedBaseType || hasBaseType(reducedBaseType, type)) { error(type.symbol.valueDeclaration, Diagnostics.Type_0_recursively_references_itself_as_a_base_type, typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrayAsGenericType)); return type.resolvedBaseTypes = emptyArray; @@ -8434,7 +8439,7 @@ namespace ts { // partial instantiation of the members without the base types fully resolved type.members = undefined; } - return type.resolvedBaseTypes = [baseType]; + return type.resolvedBaseTypes = [reducedBaseType]; } function areAllOuterTypeParametersApplied(type: Type): boolean { // TODO: GH#18217 Shouldn't this take an InterfaceType? @@ -10409,7 +10414,7 @@ namespace ts { else if (type.flags & TypeFlags.Intersection) { if (!((type).objectFlags & ObjectFlags.IsNeverIntersectionComputed)) { (type).objectFlags |= ObjectFlags.IsNeverIntersectionComputed | - (some(getPropertiesOfUnionOrIntersectionType(type), isDiscriminantWithNeverType) ? ObjectFlags.IsNeverIntersection : 0); + (some(getPropertiesOfUnionOrIntersectionType(type), isNeverReducedProperty) ? ObjectFlags.IsNeverIntersection : 0); } return (type).objectFlags & ObjectFlags.IsNeverIntersection ? neverType : type; } @@ -10428,12 +10433,37 @@ namespace ts { return reduced; } + function isNeverReducedProperty(prop: Symbol) { + return isDiscriminantWithNeverType(prop) || isConflictingPrivateProperty(prop); + } + function isDiscriminantWithNeverType(prop: Symbol) { + // Return true for a synthetic non-optional property with non-uniform types, where at least one is + // a literal type and none is never, that reduces to never. return !(prop.flags & SymbolFlags.Optional) && (getCheckFlags(prop) & (CheckFlags.Discriminant | CheckFlags.HasNeverType)) === CheckFlags.Discriminant && !!(getTypeOfSymbol(prop).flags & TypeFlags.Never); } + function isConflictingPrivateProperty(prop: Symbol) { + // Return true for a synthetic property with multiple declarations, at least one of which is private. + return !prop.valueDeclaration && !!(getCheckFlags(prop) & CheckFlags.ContainsPrivate); + } + + function elaborateNeverIntersection(errorInfo: DiagnosticMessageChain | undefined, type: IntersectionType) { + const neverProp = find(getPropertiesOfUnionOrIntersectionType(type), isDiscriminantWithNeverType); + if (neverProp) { + return chainDiagnosticMessages(errorInfo, Diagnostics.The_intersection_0_was_reduced_to_never_because_property_1_has_conflicting_types_in_some_constituents, + typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.NoTypeReduction), symbolToString(neverProp)); + } + const privateProp = find(getPropertiesOfUnionOrIntersectionType(type), isConflictingPrivateProperty); + if (privateProp) { + return chainDiagnosticMessages(errorInfo, Diagnostics.The_intersection_0_was_reduced_to_never_because_property_1_exists_in_multiple_constituents_and_is_private_in_some, + typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.NoTypeReduction), symbolToString(privateProp)); + } + return errorInfo; + } + /** * Return the symbol for the property with the given name in the given type. Creates synthetic union properties when * necessary, maps primitive types and type parameters are to their apparent types, and augments with properties from @@ -15561,6 +15591,9 @@ namespace ts { return result; } } + else if (target.flags & TypeFlags.Never && originalTarget.flags & TypeFlags.Intersection) { + errorInfo = elaborateNeverIntersection(errorInfo, originalTarget); + } if (!headMessage && maybeSuppress) { lastSkippedInfo = [source, target]; // Used by, eg, missing property checking to replace the top-level message with a more informative one @@ -16442,14 +16475,7 @@ namespace ts { const sourcePropFlags = getDeclarationModifierFlagsFromSymbol(sourceProp); const targetPropFlags = getDeclarationModifierFlagsFromSymbol(targetProp); if (sourcePropFlags & ModifierFlags.Private || targetPropFlags & ModifierFlags.Private) { - const hasDifferingDeclarations = sourceProp.valueDeclaration !== targetProp.valueDeclaration; - if (getCheckFlags(sourceProp) & CheckFlags.ContainsPrivate && hasDifferingDeclarations) { - if (reportErrors) { - reportError(Diagnostics.Property_0_has_conflicting_declarations_and_is_inaccessible_in_type_1, symbolToString(sourceProp), typeToString(source)); - } - return Ternary.False; - } - if (hasDifferingDeclarations) { + if (sourceProp.valueDeclaration !== targetProp.valueDeclaration) { if (reportErrors) { if (sourcePropFlags & ModifierFlags.Private && targetPropFlags & ModifierFlags.Private) { reportError(Diagnostics.Types_have_separate_declarations_of_a_private_property_0, symbolToString(targetProp)); @@ -23585,12 +23611,6 @@ namespace ts { const flags = getDeclarationModifierFlagsFromSymbol(prop); const errorNode = node.kind === SyntaxKind.QualifiedName ? node.right : node.kind === SyntaxKind.ImportType ? node : node.name; - if (getCheckFlags(prop) & CheckFlags.ContainsPrivate) { - // Synthetic property with private constituent property - error(errorNode, Diagnostics.Property_0_has_conflicting_declarations_and_is_inaccessible_in_type_1, symbolToString(prop), typeToString(type)); - return false; - } - if (isSuper) { // TS 1.0 spec (April 2014): 4.8.2 // - In a constructor, instance member function, instance member accessor, or @@ -24086,6 +24106,9 @@ namespace ts { relatedInfo = suggestion.valueDeclaration && createDiagnosticForNode(suggestion.valueDeclaration, Diagnostics._0_is_declared_here, suggestedName); } else { + if (containingType.flags & TypeFlags.Intersection && getReducedType(containingType).flags & TypeFlags.Never) { + errorInfo = elaborateNeverIntersection(errorInfo, containingType); + } errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1, declarationNameToString(propNode), typeToString(containingType)); } } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index d1e13c777529d..892de11bf3a50 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2145,10 +2145,6 @@ "category": "Error", "code": 2545 }, - "Property '{0}' has conflicting declarations and is inaccessible in type '{1}'.": { - "category": "Error", - "code": 2546 - }, "The type returned by the '{0}()' method of an async iterator must be a promise for a type with a 'value' property.": { "category": "Error", "code": 2547 @@ -5708,5 +5704,13 @@ "An optional chain cannot contain private identifiers.": { "category": "Error", "code": 18030 + }, + "The intersection '{0}' was reduced to 'never' because property '{1}' has conflicting types in some constituents.": { + "category": "Error", + "code": 18031 + }, + "The intersection '{0}' was reduced to 'never' because property '{1}' exists in multiple constituents and is private in some.": { + "category": "Error", + "code": 18032 } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 3add4e354ae28..c1c6d97f6c76b 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3685,6 +3685,7 @@ namespace ts { OmitParameterModifiers = 1 << 13, // Omit modifiers on parameters UseAliasDefinedOutsideCurrentScope = 1 << 14, // Allow non-visible aliases UseSingleQuotesForStringLiteralType = 1 << 28, // Use single quotes for string literal type + NoTypeReduction = 1 << 29, // Don't call getReducedType // Error handling AllowThisInObjectLiteral = 1 << 15, @@ -3728,6 +3729,7 @@ namespace ts { UseAliasDefinedOutsideCurrentScope = 1 << 14, // For a `type T = ... ` defined in a different file, write `T` instead of its value, even though `T` can't be accessed in the current scope. UseSingleQuotesForStringLiteralType = 1 << 28, // Use single quotes for string literal type + NoTypeReduction = 1 << 29, // Don't call getReducedType // Error Handling AllowUniqueESSymbolType = 1 << 20, // This is bit 20 to align with the same bit in `NodeBuilderFlags` @@ -3747,7 +3749,7 @@ namespace ts { NodeBuilderFlagsMask = NoTruncation | WriteArrayAsGenericType | UseStructuralFallback | WriteTypeArgumentsOfSignature | UseFullyQualifiedType | SuppressAnyReturnType | MultilineObjectLiterals | WriteClassExpressionAsTypeLiteral | UseTypeOfFunction | OmitParameterModifiers | UseAliasDefinedOutsideCurrentScope | AllowUniqueESSymbolType | InTypeAlias | - UseSingleQuotesForStringLiteralType, + UseSingleQuotesForStringLiteralType | NoTypeReduction, } export const enum SymbolFormatFlags { From 7bf375fa121b7a22b3372980e46be2fafddbac34 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 2 Apr 2020 12:24:51 -0700 Subject: [PATCH 2/6] Accept new API baselines --- tests/baselines/reference/api/tsserverlibrary.d.ts | 4 +++- tests/baselines/reference/api/typescript.d.ts | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 0ba337629e70b..5e91796d88019 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -2135,6 +2135,7 @@ declare namespace ts { OmitParameterModifiers = 8192, UseAliasDefinedOutsideCurrentScope = 16384, UseSingleQuotesForStringLiteralType = 268435456, + NoTypeReduction = 536870912, AllowThisInObjectLiteral = 32768, AllowQualifedNameInPlaceOfIdentifier = 65536, AllowAnonymousIdentifier = 131072, @@ -2163,6 +2164,7 @@ declare namespace ts { OmitParameterModifiers = 8192, UseAliasDefinedOutsideCurrentScope = 16384, UseSingleQuotesForStringLiteralType = 268435456, + NoTypeReduction = 536870912, AllowUniqueESSymbolType = 1048576, AddUndefined = 131072, WriteArrowStyleSignature = 262144, @@ -2171,7 +2173,7 @@ declare namespace ts { InFirstTypeArgument = 4194304, InTypeAlias = 8388608, /** @deprecated */ WriteOwnNameForAnyLike = 0, - NodeBuilderFlagsMask = 277904747 + NodeBuilderFlagsMask = 814775659 } export enum SymbolFormatFlags { None = 0, diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 06e81bd224a91..bca7c4c4ab7f4 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -2135,6 +2135,7 @@ declare namespace ts { OmitParameterModifiers = 8192, UseAliasDefinedOutsideCurrentScope = 16384, UseSingleQuotesForStringLiteralType = 268435456, + NoTypeReduction = 536870912, AllowThisInObjectLiteral = 32768, AllowQualifedNameInPlaceOfIdentifier = 65536, AllowAnonymousIdentifier = 131072, @@ -2163,6 +2164,7 @@ declare namespace ts { OmitParameterModifiers = 8192, UseAliasDefinedOutsideCurrentScope = 16384, UseSingleQuotesForStringLiteralType = 268435456, + NoTypeReduction = 536870912, AllowUniqueESSymbolType = 1048576, AddUndefined = 131072, WriteArrowStyleSignature = 262144, @@ -2171,7 +2173,7 @@ declare namespace ts { InFirstTypeArgument = 4194304, InTypeAlias = 8388608, /** @deprecated */ WriteOwnNameForAnyLike = 0, - NodeBuilderFlagsMask = 277904747 + NodeBuilderFlagsMask = 814775659 } export enum SymbolFormatFlags { None = 0, From 3197c17923cca5a8ac09652de64881a195110955 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 2 Apr 2020 12:25:02 -0700 Subject: [PATCH 3/6] Accept new baselines --- ...rivateMemberOfGenericConstraint.errors.txt | 5 +- .../intersectionReduction.errors.txt | 2 + .../intersectionReductionStrict.errors.txt | 2 + .../reference/mixinAccessModifiers.errors.txt | 70 +++++----- .../reference/mixinAccessModifiers.symbols | 10 -- .../reference/mixinAccessModifiers.types | 56 ++++---- .../mixinPrivateAndProtected.errors.txt | 53 ++++++-- .../mixinPrivateAndProtected.symbols | 36 ------ .../reference/mixinPrivateAndProtected.types | 120 +++++++++--------- .../typeGuardsWithInstanceOf.errors.txt | 2 + 10 files changed, 172 insertions(+), 184 deletions(-) diff --git a/tests/baselines/reference/indexedAccessPrivateMemberOfGenericConstraint.errors.txt b/tests/baselines/reference/indexedAccessPrivateMemberOfGenericConstraint.errors.txt index 56bf43e77ac4d..778e2a91700de 100644 --- a/tests/baselines/reference/indexedAccessPrivateMemberOfGenericConstraint.errors.txt +++ b/tests/baselines/reference/indexedAccessPrivateMemberOfGenericConstraint.errors.txt @@ -1,10 +1,9 @@ tests/cases/compiler/indexedAccessPrivateMemberOfGenericConstraint.ts(9,24): error TS4105: Private or protected member 'a' cannot be accessed on a type parameter. tests/cases/compiler/indexedAccessPrivateMemberOfGenericConstraint.ts(9,32): error TS4105: Private or protected member 'a' cannot be accessed on a type parameter. tests/cases/compiler/indexedAccessPrivateMemberOfGenericConstraint.ts(10,27): error TS4105: Private or protected member 'a' cannot be accessed on a type parameter. -tests/cases/compiler/indexedAccessPrivateMemberOfGenericConstraint.ts(11,27): error TS4105: Private or protected member 'a' cannot be accessed on a type parameter. -==== tests/cases/compiler/indexedAccessPrivateMemberOfGenericConstraint.ts (4 errors) ==== +==== tests/cases/compiler/indexedAccessPrivateMemberOfGenericConstraint.ts (3 errors) ==== class A { private a: number; } @@ -22,6 +21,4 @@ tests/cases/compiler/indexedAccessPrivateMemberOfGenericConstraint.ts(11,27): er ~~~~~~ !!! error TS4105: Private or protected member 'a' cannot be accessed on a type parameter. type Z = T["a"]; - ~~~~~~ -!!! error TS4105: Private or protected member 'a' cannot be accessed on a type parameter. \ No newline at end of file diff --git a/tests/baselines/reference/intersectionReduction.errors.txt b/tests/baselines/reference/intersectionReduction.errors.txt index 7f979f3aeabe8..7026fcda0a918 100644 --- a/tests/baselines/reference/intersectionReduction.errors.txt +++ b/tests/baselines/reference/intersectionReduction.errors.txt @@ -1,4 +1,5 @@ tests/cases/conformance/types/intersection/intersectionReduction.ts(38,4): error TS2339: Property 'kind' does not exist on type 'never'. + The intersection 'A & B' was reduced to 'never' because property 'kind' has conflicting types in some constituents. tests/cases/conformance/types/intersection/intersectionReduction.ts(80,1): error TS2322: Type 'any' is not assignable to type 'never'. tests/cases/conformance/types/intersection/intersectionReduction.ts(81,1): error TS2322: Type 'any' is not assignable to type 'never'. @@ -44,6 +45,7 @@ tests/cases/conformance/types/intersection/intersectionReduction.ts(81,1): error ab.kind; // Error ~~~~ !!! error TS2339: Property 'kind' does not exist on type 'never'. +!!! error TS2339: The intersection 'A & B' was reduced to 'never' because property 'kind' has conflicting types in some constituents. declare let x: A | (B & C); // A let a: A = x; diff --git a/tests/baselines/reference/intersectionReductionStrict.errors.txt b/tests/baselines/reference/intersectionReductionStrict.errors.txt index fe3e67fdc2ea7..0c78ee1c9358a 100644 --- a/tests/baselines/reference/intersectionReductionStrict.errors.txt +++ b/tests/baselines/reference/intersectionReductionStrict.errors.txt @@ -1,4 +1,5 @@ tests/cases/conformance/types/intersection/intersectionReductionStrict.ts(38,4): error TS2339: Property 'kind' does not exist on type 'never'. + The intersection 'A & B' was reduced to 'never' because property 'kind' has conflicting types in some constituents. tests/cases/conformance/types/intersection/intersectionReductionStrict.ts(69,1): error TS2322: Type 'any' is not assignable to type 'never'. tests/cases/conformance/types/intersection/intersectionReductionStrict.ts(70,1): error TS2322: Type 'any' is not assignable to type 'never'. @@ -44,6 +45,7 @@ tests/cases/conformance/types/intersection/intersectionReductionStrict.ts(70,1): ab.kind; // Error ~~~~ !!! error TS2339: Property 'kind' does not exist on type 'never'. +!!! error TS2339: The intersection 'A & B' was reduced to 'never' because property 'kind' has conflicting types in some constituents. declare let x: A | (B & C); // A let a: A = x; diff --git a/tests/baselines/reference/mixinAccessModifiers.errors.txt b/tests/baselines/reference/mixinAccessModifiers.errors.txt index 05cd72cbb6bf7..7f5ef70469b69 100644 --- a/tests/baselines/reference/mixinAccessModifiers.errors.txt +++ b/tests/baselines/reference/mixinAccessModifiers.errors.txt @@ -1,25 +1,27 @@ -tests/cases/conformance/classes/mixinAccessModifiers.ts(38,4): error TS2546: Property 'p' has conflicting declarations and is inaccessible in type 'Private & Private2'. -tests/cases/conformance/classes/mixinAccessModifiers.ts(42,4): error TS2546: Property 'p' has conflicting declarations and is inaccessible in type 'Private & Protected'. -tests/cases/conformance/classes/mixinAccessModifiers.ts(46,4): error TS2546: Property 'p' has conflicting declarations and is inaccessible in type 'Private & Public'. +tests/cases/conformance/classes/mixinAccessModifiers.ts(38,4): error TS2339: Property 'p' does not exist on type 'never'. + The intersection 'Private & Private2' was reduced to 'never' because property 'p' exists in multiple constituents and is private in some. +tests/cases/conformance/classes/mixinAccessModifiers.ts(42,4): error TS2339: Property 'p' does not exist on type 'never'. + The intersection 'Private & Protected' was reduced to 'never' because property 'p' exists in multiple constituents and is private in some. +tests/cases/conformance/classes/mixinAccessModifiers.ts(46,4): error TS2339: Property 'p' does not exist on type 'never'. + The intersection 'Private & Public' was reduced to 'never' because property 'p' exists in multiple constituents and is private in some. tests/cases/conformance/classes/mixinAccessModifiers.ts(50,4): error TS2445: Property 'p' is protected and only accessible within class 'Protected & Protected2' and its subclasses. -tests/cases/conformance/classes/mixinAccessModifiers.ts(65,7): error TS2415: Class 'C1' incorrectly extends base class 'Private & Private2'. - Type 'C1' is not assignable to type 'Private'. - Property 'p' has conflicting declarations and is inaccessible in type 'C1'. -tests/cases/conformance/classes/mixinAccessModifiers.ts(66,7): error TS2415: Class 'C2' incorrectly extends base class 'Private & Protected'. - Type 'C2' is not assignable to type 'Private'. - Property 'p' has conflicting declarations and is inaccessible in type 'C2'. -tests/cases/conformance/classes/mixinAccessModifiers.ts(67,7): error TS2415: Class 'C3' incorrectly extends base class 'Private & Public'. - Type 'C3' is not assignable to type 'Private'. - Property 'p' has conflicting declarations and is inaccessible in type 'C3'. +tests/cases/conformance/classes/mixinAccessModifiers.ts(65,18): error TS2509: Base constructor return type 'never' is not an object type or intersection of object types with statically known members. + The intersection 'Private & Private2' was reduced to 'never' because property 'p' exists in multiple constituents and is private in some. +tests/cases/conformance/classes/mixinAccessModifiers.ts(66,18): error TS2509: Base constructor return type 'never' is not an object type or intersection of object types with statically known members. + The intersection 'Private & Protected' was reduced to 'never' because property 'p' exists in multiple constituents and is private in some. +tests/cases/conformance/classes/mixinAccessModifiers.ts(67,18): error TS2509: Base constructor return type 'never' is not an object type or intersection of object types with statically known members. + The intersection 'Private & Public' was reduced to 'never' because property 'p' exists in multiple constituents and is private in some. tests/cases/conformance/classes/mixinAccessModifiers.ts(84,6): error TS2445: Property 'p' is protected and only accessible within class 'C4' and its subclasses. tests/cases/conformance/classes/mixinAccessModifiers.ts(89,6): error TS2445: Property 's' is protected and only accessible within class 'typeof C4' and its subclasses. tests/cases/conformance/classes/mixinAccessModifiers.ts(97,6): error TS2445: Property 'p' is protected and only accessible within class 'C4' and its subclasses. tests/cases/conformance/classes/mixinAccessModifiers.ts(102,6): error TS2445: Property 's' is protected and only accessible within class 'typeof C4' and its subclasses. tests/cases/conformance/classes/mixinAccessModifiers.ts(119,4): error TS2341: Property 'privateMethod' is private and only accessible within class 'ProtectedGeneric'. tests/cases/conformance/classes/mixinAccessModifiers.ts(120,4): error TS2445: Property 'protectedMethod' is protected and only accessible within class 'ProtectedGeneric' and its subclasses. -tests/cases/conformance/classes/mixinAccessModifiers.ts(124,4): error TS2546: Property 'privateMethod' has conflicting declarations and is inaccessible in type 'ProtectedGeneric<{ a: void; }> & ProtectedGeneric2<{ a: void; b: void; }>'. -tests/cases/conformance/classes/mixinAccessModifiers.ts(125,4): error TS2445: Property 'protectedMethod' is protected and only accessible within class 'ProtectedGeneric<{ a: void; }> & ProtectedGeneric2<{ a: void; b: void; }>' and its subclasses. -tests/cases/conformance/classes/mixinAccessModifiers.ts(129,4): error TS2546: Property 'privateMethod' has conflicting declarations and is inaccessible in type 'ProtectedGeneric<{ a: void; }> & ProtectedGeneric<{ a: void; b: void; }>'. +tests/cases/conformance/classes/mixinAccessModifiers.ts(124,4): error TS2339: Property 'privateMethod' does not exist on type 'never'. + The intersection 'ProtectedGeneric<{ a: void; }> & ProtectedGeneric2<{ a: void; b: void; }>' was reduced to 'never' because property 'privateMethod' exists in multiple constituents and is private in some. +tests/cases/conformance/classes/mixinAccessModifiers.ts(125,4): error TS2339: Property 'protectedMethod' does not exist on type 'never'. + The intersection 'ProtectedGeneric<{ a: void; }> & ProtectedGeneric2<{ a: void; b: void; }>' was reduced to 'never' because property 'privateMethod' exists in multiple constituents and is private in some. +tests/cases/conformance/classes/mixinAccessModifiers.ts(129,4): error TS2341: Property 'privateMethod' is private and only accessible within class 'ProtectedGeneric'. tests/cases/conformance/classes/mixinAccessModifiers.ts(130,4): error TS2445: Property 'protectedMethod' is protected and only accessible within class 'ProtectedGeneric' and its subclasses. @@ -63,19 +65,22 @@ tests/cases/conformance/classes/mixinAccessModifiers.ts(130,4): error TS2445: Pr function f1(x: Private & Private2) { x.p; // Error, private constituent makes property inaccessible ~ -!!! error TS2546: Property 'p' has conflicting declarations and is inaccessible in type 'Private & Private2'. +!!! error TS2339: Property 'p' does not exist on type 'never'. +!!! error TS2339: The intersection 'Private & Private2' was reduced to 'never' because property 'p' exists in multiple constituents and is private in some. } function f2(x: Private & Protected) { x.p; // Error, private constituent makes property inaccessible ~ -!!! error TS2546: Property 'p' has conflicting declarations and is inaccessible in type 'Private & Protected'. +!!! error TS2339: Property 'p' does not exist on type 'never'. +!!! error TS2339: The intersection 'Private & Protected' was reduced to 'never' because property 'p' exists in multiple constituents and is private in some. } function f3(x: Private & Public) { x.p; // Error, private constituent makes property inaccessible ~ -!!! error TS2546: Property 'p' has conflicting declarations and is inaccessible in type 'Private & Public'. +!!! error TS2339: Property 'p' does not exist on type 'never'. +!!! error TS2339: The intersection 'Private & Public' was reduced to 'never' because property 'p' exists in multiple constituents and is private in some. } function f4(x: Protected & Protected2) { @@ -97,20 +102,17 @@ tests/cases/conformance/classes/mixinAccessModifiers.ts(130,4): error TS2445: Pr // Can't derive from type with inaccessible properties class C1 extends Mix(Private, Private2) {} - ~~ -!!! error TS2415: Class 'C1' incorrectly extends base class 'Private & Private2'. -!!! error TS2415: Type 'C1' is not assignable to type 'Private'. -!!! error TS2415: Property 'p' has conflicting declarations and is inaccessible in type 'C1'. + ~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2509: Base constructor return type 'never' is not an object type or intersection of object types with statically known members. +!!! error TS2509: The intersection 'Private & Private2' was reduced to 'never' because property 'p' exists in multiple constituents and is private in some. class C2 extends Mix(Private, Protected) {} - ~~ -!!! error TS2415: Class 'C2' incorrectly extends base class 'Private & Protected'. -!!! error TS2415: Type 'C2' is not assignable to type 'Private'. -!!! error TS2415: Property 'p' has conflicting declarations and is inaccessible in type 'C2'. + ~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2509: Base constructor return type 'never' is not an object type or intersection of object types with statically known members. +!!! error TS2509: The intersection 'Private & Protected' was reduced to 'never' because property 'p' exists in multiple constituents and is private in some. class C3 extends Mix(Private, Public) {} - ~~ -!!! error TS2415: Class 'C3' incorrectly extends base class 'Private & Public'. -!!! error TS2415: Type 'C3' is not assignable to type 'Private'. -!!! error TS2415: Property 'p' has conflicting declarations and is inaccessible in type 'C3'. + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS2509: Base constructor return type 'never' is not an object type or intersection of object types with statically known members. +!!! error TS2509: The intersection 'Private & Public' was reduced to 'never' because property 'p' exists in multiple constituents and is private in some. class C4 extends Mix(Protected, Protected2) { f(c4: C4, c5: C5, c6: C6) { @@ -181,16 +183,18 @@ tests/cases/conformance/classes/mixinAccessModifiers.ts(130,4): error TS2445: Pr function f8(x: ProtectedGeneric<{a: void;}> & ProtectedGeneric2<{a:void;b:void;}>) { x.privateMethod(); // Error, private constituent makes method inaccessible ~~~~~~~~~~~~~ -!!! error TS2546: Property 'privateMethod' has conflicting declarations and is inaccessible in type 'ProtectedGeneric<{ a: void; }> & ProtectedGeneric2<{ a: void; b: void; }>'. +!!! error TS2339: Property 'privateMethod' does not exist on type 'never'. +!!! error TS2339: The intersection 'ProtectedGeneric<{ a: void; }> & ProtectedGeneric2<{ a: void; b: void; }>' was reduced to 'never' because property 'privateMethod' exists in multiple constituents and is private in some. x.protectedMethod(); // Error, protected when all constituents are protected ~~~~~~~~~~~~~~~ -!!! error TS2445: Property 'protectedMethod' is protected and only accessible within class 'ProtectedGeneric<{ a: void; }> & ProtectedGeneric2<{ a: void; b: void; }>' and its subclasses. +!!! error TS2339: Property 'protectedMethod' does not exist on type 'never'. +!!! error TS2339: The intersection 'ProtectedGeneric<{ a: void; }> & ProtectedGeneric2<{ a: void; b: void; }>' was reduced to 'never' because property 'privateMethod' exists in multiple constituents and is private in some. } function f9(x: ProtectedGeneric<{a: void;}> & ProtectedGeneric<{a:void;b:void;}>) { x.privateMethod(); // Error, private constituent makes method inaccessible ~~~~~~~~~~~~~ -!!! error TS2546: Property 'privateMethod' has conflicting declarations and is inaccessible in type 'ProtectedGeneric<{ a: void; }> & ProtectedGeneric<{ a: void; b: void; }>'. +!!! error TS2341: Property 'privateMethod' is private and only accessible within class 'ProtectedGeneric'. x.protectedMethod(); // Error, protected when all constituents are protected ~~~~~~~~~~~~~~~ !!! error TS2445: Property 'protectedMethod' is protected and only accessible within class 'ProtectedGeneric' and its subclasses. diff --git a/tests/baselines/reference/mixinAccessModifiers.symbols b/tests/baselines/reference/mixinAccessModifiers.symbols index e0186264f937b..e7847dbcfd3bf 100644 --- a/tests/baselines/reference/mixinAccessModifiers.symbols +++ b/tests/baselines/reference/mixinAccessModifiers.symbols @@ -82,9 +82,7 @@ function f1(x: Private & Private2) { >Private2 : Symbol(Private2, Decl(mixinAccessModifiers.ts, 5, 1)) x.p; // Error, private constituent makes property inaccessible ->x.p : Symbol(p, Decl(mixinAccessModifiers.ts, 3, 32), Decl(mixinAccessModifiers.ts, 8, 32)) >x : Symbol(x, Decl(mixinAccessModifiers.ts, 36, 12)) ->p : Symbol(p, Decl(mixinAccessModifiers.ts, 3, 32), Decl(mixinAccessModifiers.ts, 8, 32)) } function f2(x: Private & Protected) { @@ -94,9 +92,7 @@ function f2(x: Private & Protected) { >Protected : Symbol(Protected, Decl(mixinAccessModifiers.ts, 10, 1)) x.p; // Error, private constituent makes property inaccessible ->x.p : Symbol(p, Decl(mixinAccessModifiers.ts, 3, 32), Decl(mixinAccessModifiers.ts, 13, 32)) >x : Symbol(x, Decl(mixinAccessModifiers.ts, 40, 12)) ->p : Symbol(p, Decl(mixinAccessModifiers.ts, 3, 32), Decl(mixinAccessModifiers.ts, 13, 32)) } function f3(x: Private & Public) { @@ -106,9 +102,7 @@ function f3(x: Private & Public) { >Public : Symbol(Public, Decl(mixinAccessModifiers.ts, 22, 1)) x.p; // Error, private constituent makes property inaccessible ->x.p : Symbol(p, Decl(mixinAccessModifiers.ts, 3, 32), Decl(mixinAccessModifiers.ts, 25, 32)) >x : Symbol(x, Decl(mixinAccessModifiers.ts, 44, 12)) ->p : Symbol(p, Decl(mixinAccessModifiers.ts, 3, 32), Decl(mixinAccessModifiers.ts, 25, 32)) } function f4(x: Protected & Protected2) { @@ -377,14 +371,10 @@ function f8(x: ProtectedGeneric<{a: void;}> & ProtectedGeneric2<{a:void;b:void;} >b : Symbol(b, Decl(mixinAccessModifiers.ts, 122, 72)) x.privateMethod(); // Error, private constituent makes method inaccessible ->x.privateMethod : Symbol(privateMethod, Decl(mixinAccessModifiers.ts, 107, 27), Decl(mixinAccessModifiers.ts, 112, 28)) >x : Symbol(x, Decl(mixinAccessModifiers.ts, 122, 12)) ->privateMethod : Symbol(privateMethod, Decl(mixinAccessModifiers.ts, 107, 27), Decl(mixinAccessModifiers.ts, 112, 28)) x.protectedMethod(); // Error, protected when all constituents are protected ->x.protectedMethod : Symbol(protectedMethod, Decl(mixinAccessModifiers.ts, 108, 27), Decl(mixinAccessModifiers.ts, 113, 27)) >x : Symbol(x, Decl(mixinAccessModifiers.ts, 122, 12)) ->protectedMethod : Symbol(protectedMethod, Decl(mixinAccessModifiers.ts, 108, 27), Decl(mixinAccessModifiers.ts, 113, 27)) } function f9(x: ProtectedGeneric<{a: void;}> & ProtectedGeneric<{a:void;b:void;}>) { diff --git a/tests/baselines/reference/mixinAccessModifiers.types b/tests/baselines/reference/mixinAccessModifiers.types index ffa7b2b1e717a..db61ccec85548 100644 --- a/tests/baselines/reference/mixinAccessModifiers.types +++ b/tests/baselines/reference/mixinAccessModifiers.types @@ -76,33 +76,33 @@ class Public2 { } function f1(x: Private & Private2) { ->f1 : (x: Private & Private2) => void ->x : Private & Private2 +>f1 : (x: never) => void +>x : never x.p; // Error, private constituent makes property inaccessible ->x.p : string ->x : Private & Private2 ->p : string +>x.p : any +>x : never +>p : any } function f2(x: Private & Protected) { ->f2 : (x: Private & Protected) => void ->x : Private & Protected +>f2 : (x: never) => void +>x : never x.p; // Error, private constituent makes property inaccessible ->x.p : string ->x : Private & Protected ->p : string +>x.p : any +>x : never +>p : any } function f3(x: Private & Public) { ->f3 : (x: Private & Public) => void ->x : Private & Public +>f3 : (x: never) => void +>x : never x.p; // Error, private constituent makes property inaccessible ->x.p : string ->x : Private & Public ->p : string +>x.p : any +>x : never +>p : any } function f4(x: Protected & Protected2) { @@ -144,21 +144,21 @@ declare function Mix(c1: T, c2: U): T & U; class C1 extends Mix(Private, Private2) {} >C1 : C1 ->Mix(Private, Private2) : Private & Private2 +>Mix(Private, Private2) : typeof Private & typeof Private2 >Mix : (c1: T, c2: U) => T & U >Private : typeof Private >Private2 : typeof Private2 class C2 extends Mix(Private, Protected) {} >C2 : C2 ->Mix(Private, Protected) : Private & Protected +>Mix(Private, Protected) : typeof Private & typeof Protected >Mix : (c1: T, c2: U) => T & U >Private : typeof Private >Protected : typeof Protected class C3 extends Mix(Private, Public) {} >C3 : C3 ->Mix(Private, Public) : Private & Public +>Mix(Private, Public) : typeof Private & typeof Public >Mix : (c1: T, c2: U) => T & U >Private : typeof Private >Public : typeof Public @@ -345,23 +345,23 @@ function f7(x: ProtectedGeneric<{}> & ProtectedGeneric<{}>) { } function f8(x: ProtectedGeneric<{a: void;}> & ProtectedGeneric2<{a:void;b:void;}>) { ->f8 : (x: ProtectedGeneric<{ a: void; }> & ProtectedGeneric2<{ a: void; b: void; }>) => void ->x : ProtectedGeneric<{ a: void; }> & ProtectedGeneric2<{ a: void; b: void; }> +>f8 : (x: never) => void +>x : never >a : void >a : void >b : void x.privateMethod(); // Error, private constituent makes method inaccessible ->x.privateMethod() : void ->x.privateMethod : (() => void) & (() => void) ->x : ProtectedGeneric<{ a: void; }> & ProtectedGeneric2<{ a: void; b: void; }> ->privateMethod : (() => void) & (() => void) +>x.privateMethod() : any +>x.privateMethod : any +>x : never +>privateMethod : any x.protectedMethod(); // Error, protected when all constituents are protected ->x.protectedMethod() : void ->x.protectedMethod : (() => void) & (() => void) ->x : ProtectedGeneric<{ a: void; }> & ProtectedGeneric2<{ a: void; b: void; }> ->protectedMethod : (() => void) & (() => void) +>x.protectedMethod() : any +>x.protectedMethod : any +>x : never +>protectedMethod : any } function f9(x: ProtectedGeneric<{a: void;}> & ProtectedGeneric<{a:void;b:void;}>) { diff --git a/tests/baselines/reference/mixinPrivateAndProtected.errors.txt b/tests/baselines/reference/mixinPrivateAndProtected.errors.txt index 131aff967d9b4..ca4c84f739a72 100644 --- a/tests/baselines/reference/mixinPrivateAndProtected.errors.txt +++ b/tests/baselines/reference/mixinPrivateAndProtected.errors.txt @@ -1,14 +1,26 @@ tests/cases/compiler/mixinPrivateAndProtected.ts(46,3): error TS2445: Property 'ptd' is protected and only accessible within class 'A' and its subclasses. tests/cases/compiler/mixinPrivateAndProtected.ts(47,3): error TS2341: Property 'pvt' is private and only accessible within class 'A'. -tests/cases/compiler/mixinPrivateAndProtected.ts(50,4): error TS2445: Property 'ptd' is protected and only accessible within class 'mixB.(Anonymous class) & A' and its subclasses. -tests/cases/compiler/mixinPrivateAndProtected.ts(51,4): error TS2546: Property 'pvt' has conflicting declarations and is inaccessible in type 'mixB.(Anonymous class) & A'. -tests/cases/compiler/mixinPrivateAndProtected.ts(54,5): error TS2445: Property 'ptd' is protected and only accessible within class 'mixC<{ new (...args: any[]): mixB.(Anonymous class); prototype: mixB.(Anonymous class); } & typeof A>.(Anonymous class) & mixB.(Anonymous class) & A' and its subclasses. -tests/cases/compiler/mixinPrivateAndProtected.ts(55,5): error TS2546: Property 'pvt' has conflicting declarations and is inaccessible in type 'mixC<{ new (...args: any[]): mixB.(Anonymous class); prototype: mixB.(Anonymous class); } & typeof A>.(Anonymous class) & mixB.(Anonymous class) & A'. -tests/cases/compiler/mixinPrivateAndProtected.ts(58,6): error TS2445: Property 'ptd' is protected and only accessible within class 'mixC<{ new (...args: any[]): mixB2.(Anonymous class); prototype: mixB2.(Anonymous class); } & typeof A>.(Anonymous class) & mixB2.(Anonymous class) & A' and its subclasses. -tests/cases/compiler/mixinPrivateAndProtected.ts(59,6): error TS2546: Property 'pvt' has conflicting declarations and is inaccessible in type 'mixC<{ new (...args: any[]): mixB2.(Anonymous class); prototype: mixB2.(Anonymous class); } & typeof A>.(Anonymous class) & mixB2.(Anonymous class) & A'. +tests/cases/compiler/mixinPrivateAndProtected.ts(49,4): error TS2339: Property 'pb' does not exist on type 'never'. + The intersection 'mixB.(Anonymous class) & A' was reduced to 'never' because property 'pvt' exists in multiple constituents and is private in some. +tests/cases/compiler/mixinPrivateAndProtected.ts(50,4): error TS2339: Property 'ptd' does not exist on type 'never'. + The intersection 'mixB.(Anonymous class) & A' was reduced to 'never' because property 'pvt' exists in multiple constituents and is private in some. +tests/cases/compiler/mixinPrivateAndProtected.ts(51,4): error TS2339: Property 'pvt' does not exist on type 'never'. + The intersection 'mixB.(Anonymous class) & A' was reduced to 'never' because property 'pvt' exists in multiple constituents and is private in some. +tests/cases/compiler/mixinPrivateAndProtected.ts(53,5): error TS2339: Property 'pb' does not exist on type 'never'. + The intersection 'mixC<{ new (...args: any[]): mixB.(Anonymous class); prototype: mixB.(Anonymous class); } & typeof A>.(Anonymous class) & mixB.(Anonymous class) & A' was reduced to 'never' because property 'pvt' exists in multiple constituents and is private in some. +tests/cases/compiler/mixinPrivateAndProtected.ts(54,5): error TS2339: Property 'ptd' does not exist on type 'never'. + The intersection 'mixC<{ new (...args: any[]): mixB.(Anonymous class); prototype: mixB.(Anonymous class); } & typeof A>.(Anonymous class) & mixB.(Anonymous class) & A' was reduced to 'never' because property 'pvt' exists in multiple constituents and is private in some. +tests/cases/compiler/mixinPrivateAndProtected.ts(55,5): error TS2339: Property 'pvt' does not exist on type 'never'. + The intersection 'mixC<{ new (...args: any[]): mixB.(Anonymous class); prototype: mixB.(Anonymous class); } & typeof A>.(Anonymous class) & mixB.(Anonymous class) & A' was reduced to 'never' because property 'pvt' exists in multiple constituents and is private in some. +tests/cases/compiler/mixinPrivateAndProtected.ts(57,6): error TS2339: Property 'pb' does not exist on type 'never'. + The intersection 'mixC<{ new (...args: any[]): mixB2.(Anonymous class); prototype: mixB2.(Anonymous class); } & typeof A>.(Anonymous class) & mixB2.(Anonymous class) & A' was reduced to 'never' because property 'pvt' exists in multiple constituents and is private in some. +tests/cases/compiler/mixinPrivateAndProtected.ts(58,6): error TS2339: Property 'ptd' does not exist on type 'never'. + The intersection 'mixC<{ new (...args: any[]): mixB2.(Anonymous class); prototype: mixB2.(Anonymous class); } & typeof A>.(Anonymous class) & mixB2.(Anonymous class) & A' was reduced to 'never' because property 'pvt' exists in multiple constituents and is private in some. +tests/cases/compiler/mixinPrivateAndProtected.ts(59,6): error TS2339: Property 'pvt' does not exist on type 'never'. + The intersection 'mixC<{ new (...args: any[]): mixB2.(Anonymous class); prototype: mixB2.(Anonymous class); } & typeof A>.(Anonymous class) & mixB2.(Anonymous class) & A' was reduced to 'never' because property 'pvt' exists in multiple constituents and is private in some. -==== tests/cases/compiler/mixinPrivateAndProtected.ts (8 errors) ==== +==== tests/cases/compiler/mixinPrivateAndProtected.ts (11 errors) ==== // Repro from #13830 type Constructor = new(...args: any[]) => T; @@ -62,28 +74,43 @@ tests/cases/compiler/mixinPrivateAndProtected.ts(59,6): error TS2546: Property ' !!! error TS2341: Property 'pvt' is private and only accessible within class 'A'. ab.pb.toFixed(); + ~~ +!!! error TS2339: Property 'pb' does not exist on type 'never'. +!!! error TS2339: The intersection 'mixB.(Anonymous class) & A' was reduced to 'never' because property 'pvt' exists in multiple constituents and is private in some. ab.ptd.toFixed(); // Error ~~~ -!!! error TS2445: Property 'ptd' is protected and only accessible within class 'mixB.(Anonymous class) & A' and its subclasses. +!!! error TS2339: Property 'ptd' does not exist on type 'never'. +!!! error TS2339: The intersection 'mixB.(Anonymous class) & A' was reduced to 'never' because property 'pvt' exists in multiple constituents and is private in some. ab.pvt.toFixed(); // Error ~~~ -!!! error TS2546: Property 'pvt' has conflicting declarations and is inaccessible in type 'mixB.(Anonymous class) & A'. +!!! error TS2339: Property 'pvt' does not exist on type 'never'. +!!! error TS2339: The intersection 'mixB.(Anonymous class) & A' was reduced to 'never' because property 'pvt' exists in multiple constituents and is private in some. abc.pb.toFixed(); + ~~ +!!! error TS2339: Property 'pb' does not exist on type 'never'. +!!! error TS2339: The intersection 'mixC<{ new (...args: any[]): mixB.(Anonymous class); prototype: mixB.(Anonymous class); } & typeof A>.(Anonymous class) & mixB.(Anonymous class) & A' was reduced to 'never' because property 'pvt' exists in multiple constituents and is private in some. abc.ptd.toFixed(); // Error ~~~ -!!! error TS2445: Property 'ptd' is protected and only accessible within class 'mixC<{ new (...args: any[]): mixB.(Anonymous class); prototype: mixB.(Anonymous class); } & typeof A>.(Anonymous class) & mixB.(Anonymous class) & A' and its subclasses. +!!! error TS2339: Property 'ptd' does not exist on type 'never'. +!!! error TS2339: The intersection 'mixC<{ new (...args: any[]): mixB.(Anonymous class); prototype: mixB.(Anonymous class); } & typeof A>.(Anonymous class) & mixB.(Anonymous class) & A' was reduced to 'never' because property 'pvt' exists in multiple constituents and is private in some. abc.pvt.toFixed(); // Error ~~~ -!!! error TS2546: Property 'pvt' has conflicting declarations and is inaccessible in type 'mixC<{ new (...args: any[]): mixB.(Anonymous class); prototype: mixB.(Anonymous class); } & typeof A>.(Anonymous class) & mixB.(Anonymous class) & A'. +!!! error TS2339: Property 'pvt' does not exist on type 'never'. +!!! error TS2339: The intersection 'mixC<{ new (...args: any[]): mixB.(Anonymous class); prototype: mixB.(Anonymous class); } & typeof A>.(Anonymous class) & mixB.(Anonymous class) & A' was reduced to 'never' because property 'pvt' exists in multiple constituents and is private in some. ab2c.pb.toFixed(); + ~~ +!!! error TS2339: Property 'pb' does not exist on type 'never'. +!!! error TS2339: The intersection 'mixC<{ new (...args: any[]): mixB2.(Anonymous class); prototype: mixB2.(Anonymous class); } & typeof A>.(Anonymous class) & mixB2.(Anonymous class) & A' was reduced to 'never' because property 'pvt' exists in multiple constituents and is private in some. ab2c.ptd.toFixed(); // Error ~~~ -!!! error TS2445: Property 'ptd' is protected and only accessible within class 'mixC<{ new (...args: any[]): mixB2.(Anonymous class); prototype: mixB2.(Anonymous class); } & typeof A>.(Anonymous class) & mixB2.(Anonymous class) & A' and its subclasses. +!!! error TS2339: Property 'ptd' does not exist on type 'never'. +!!! error TS2339: The intersection 'mixC<{ new (...args: any[]): mixB2.(Anonymous class); prototype: mixB2.(Anonymous class); } & typeof A>.(Anonymous class) & mixB2.(Anonymous class) & A' was reduced to 'never' because property 'pvt' exists in multiple constituents and is private in some. ab2c.pvt.toFixed(); // Error ~~~ -!!! error TS2546: Property 'pvt' has conflicting declarations and is inaccessible in type 'mixC<{ new (...args: any[]): mixB2.(Anonymous class); prototype: mixB2.(Anonymous class); } & typeof A>.(Anonymous class) & mixB2.(Anonymous class) & A'. +!!! error TS2339: Property 'pvt' does not exist on type 'never'. +!!! error TS2339: The intersection 'mixC<{ new (...args: any[]): mixB2.(Anonymous class); prototype: mixB2.(Anonymous class); } & typeof A>.(Anonymous class) & mixB2.(Anonymous class) & A' was reduced to 'never' because property 'pvt' exists in multiple constituents and is private in some. // Repro from #13924 diff --git a/tests/baselines/reference/mixinPrivateAndProtected.symbols b/tests/baselines/reference/mixinPrivateAndProtected.symbols index e9a9b08eb7392..fd8d676d86346 100644 --- a/tests/baselines/reference/mixinPrivateAndProtected.symbols +++ b/tests/baselines/reference/mixinPrivateAndProtected.symbols @@ -136,67 +136,31 @@ a.pvt.toFixed(); // Error >toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) ab.pb.toFixed(); ->ab.pb.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) ->ab.pb : Symbol(A.pb, Decl(mixinPrivateAndProtected.ts, 4, 9)) >ab : Symbol(ab, Decl(mixinPrivateAndProtected.ts, 39, 16)) ->pb : Symbol(A.pb, Decl(mixinPrivateAndProtected.ts, 4, 9)) ->toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) ab.ptd.toFixed(); // Error ->ab.ptd.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) ->ab.ptd : Symbol(ptd, Decl(mixinPrivateAndProtected.ts, 11, 30), Decl(mixinPrivateAndProtected.ts, 5, 26)) >ab : Symbol(ab, Decl(mixinPrivateAndProtected.ts, 39, 16)) ->ptd : Symbol(ptd, Decl(mixinPrivateAndProtected.ts, 11, 30), Decl(mixinPrivateAndProtected.ts, 5, 26)) ->toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) ab.pvt.toFixed(); // Error ->ab.pvt.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) ->ab.pvt : Symbol(pvt, Decl(mixinPrivateAndProtected.ts, 12, 35), Decl(mixinPrivateAndProtected.ts, 6, 30)) >ab : Symbol(ab, Decl(mixinPrivateAndProtected.ts, 39, 16)) ->pvt : Symbol(pvt, Decl(mixinPrivateAndProtected.ts, 12, 35), Decl(mixinPrivateAndProtected.ts, 6, 30)) ->toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) abc.pb.toFixed(); ->abc.pb.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) ->abc.pb : Symbol(A.pb, Decl(mixinPrivateAndProtected.ts, 4, 9)) >abc : Symbol(abc, Decl(mixinPrivateAndProtected.ts, 40, 18)) ->pb : Symbol(A.pb, Decl(mixinPrivateAndProtected.ts, 4, 9)) ->toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) abc.ptd.toFixed(); // Error ->abc.ptd.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) ->abc.ptd : Symbol(ptd, Decl(mixinPrivateAndProtected.ts, 28, 30), Decl(mixinPrivateAndProtected.ts, 11, 30), Decl(mixinPrivateAndProtected.ts, 5, 26)) >abc : Symbol(abc, Decl(mixinPrivateAndProtected.ts, 40, 18)) ->ptd : Symbol(ptd, Decl(mixinPrivateAndProtected.ts, 28, 30), Decl(mixinPrivateAndProtected.ts, 11, 30), Decl(mixinPrivateAndProtected.ts, 5, 26)) ->toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) abc.pvt.toFixed(); // Error ->abc.pvt.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) ->abc.pvt : Symbol(pvt, Decl(mixinPrivateAndProtected.ts, 29, 36), Decl(mixinPrivateAndProtected.ts, 12, 35), Decl(mixinPrivateAndProtected.ts, 6, 30)) >abc : Symbol(abc, Decl(mixinPrivateAndProtected.ts, 40, 18)) ->pvt : Symbol(pvt, Decl(mixinPrivateAndProtected.ts, 29, 36), Decl(mixinPrivateAndProtected.ts, 12, 35), Decl(mixinPrivateAndProtected.ts, 6, 30)) ->toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) ab2c.pb.toFixed(); ->ab2c.pb.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) ->ab2c.pb : Symbol(A.pb, Decl(mixinPrivateAndProtected.ts, 4, 9)) >ab2c : Symbol(ab2c, Decl(mixinPrivateAndProtected.ts, 41, 20)) ->pb : Symbol(A.pb, Decl(mixinPrivateAndProtected.ts, 4, 9)) ->toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) ab2c.ptd.toFixed(); // Error ->ab2c.ptd.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) ->ab2c.ptd : Symbol(ptd, Decl(mixinPrivateAndProtected.ts, 28, 30), Decl(mixinPrivateAndProtected.ts, 18, 30), Decl(mixinPrivateAndProtected.ts, 5, 26)) >ab2c : Symbol(ab2c, Decl(mixinPrivateAndProtected.ts, 41, 20)) ->ptd : Symbol(ptd, Decl(mixinPrivateAndProtected.ts, 28, 30), Decl(mixinPrivateAndProtected.ts, 18, 30), Decl(mixinPrivateAndProtected.ts, 5, 26)) ->toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) ab2c.pvt.toFixed(); // Error ->ab2c.pvt.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) ->ab2c.pvt : Symbol(pvt, Decl(mixinPrivateAndProtected.ts, 29, 36), Decl(mixinPrivateAndProtected.ts, 6, 30)) >ab2c : Symbol(ab2c, Decl(mixinPrivateAndProtected.ts, 41, 20)) ->pvt : Symbol(pvt, Decl(mixinPrivateAndProtected.ts, 29, 36), Decl(mixinPrivateAndProtected.ts, 6, 30)) ->toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) // Repro from #13924 diff --git a/tests/baselines/reference/mixinPrivateAndProtected.types b/tests/baselines/reference/mixinPrivateAndProtected.types index ea89e7c7ac34e..c226c23e6868a 100644 --- a/tests/baselines/reference/mixinPrivateAndProtected.types +++ b/tests/baselines/reference/mixinPrivateAndProtected.types @@ -107,18 +107,18 @@ const >A : typeof A ab = new AB(), ->ab : mixB.(Anonymous class) & A ->new AB() : mixB.(Anonymous class) & A +>ab : never +>new AB() : never >AB : { new (...args: any[]): mixB.(Anonymous class); prototype: mixB.(Anonymous class); } & typeof A abc = new ABC(), ->abc : mixC<{ new (...args: any[]): mixB.(Anonymous class); prototype: mixB.(Anonymous class); } & typeof A>.(Anonymous class) & mixB.(Anonymous class) & A ->new ABC() : mixC<{ new (...args: any[]): mixB.(Anonymous class); prototype: mixB.(Anonymous class); } & typeof A>.(Anonymous class) & mixB.(Anonymous class) & A +>abc : never +>new ABC() : never >ABC : { new (...args: any[]): mixC<{ new (...args: any[]): mixB.(Anonymous class); prototype: mixB.(Anonymous class); } & typeof A>.(Anonymous class); prototype: mixC.(Anonymous class); } & { new (...args: any[]): mixB.(Anonymous class); prototype: mixB.(Anonymous class); } & typeof A ab2c = new AB2C(); ->ab2c : mixC<{ new (...args: any[]): mixB2.(Anonymous class); prototype: mixB2.(Anonymous class); } & typeof A>.(Anonymous class) & mixB2.(Anonymous class) & A ->new AB2C() : mixC<{ new (...args: any[]): mixB2.(Anonymous class); prototype: mixB2.(Anonymous class); } & typeof A>.(Anonymous class) & mixB2.(Anonymous class) & A +>ab2c : never +>new AB2C() : never >AB2C : { new (...args: any[]): mixC<{ new (...args: any[]): mixB2.(Anonymous class); prototype: mixB2.(Anonymous class); } & typeof A>.(Anonymous class); prototype: mixC.(Anonymous class); } & { new (...args: any[]): mixB2.(Anonymous class); prototype: mixB2.(Anonymous class); } & typeof A a.pb.toFixed(); @@ -146,76 +146,76 @@ a.pvt.toFixed(); // Error >toFixed : (fractionDigits?: number) => string ab.pb.toFixed(); ->ab.pb.toFixed() : string ->ab.pb.toFixed : (fractionDigits?: number) => string ->ab.pb : number ->ab : mixB.(Anonymous class) & A ->pb : number ->toFixed : (fractionDigits?: number) => string +>ab.pb.toFixed() : any +>ab.pb.toFixed : any +>ab.pb : any +>ab : never +>pb : any +>toFixed : any ab.ptd.toFixed(); // Error ->ab.ptd.toFixed() : string ->ab.ptd.toFixed : (fractionDigits?: number) => string ->ab.ptd : number ->ab : mixB.(Anonymous class) & A ->ptd : number ->toFixed : (fractionDigits?: number) => string +>ab.ptd.toFixed() : any +>ab.ptd.toFixed : any +>ab.ptd : any +>ab : never +>ptd : any +>toFixed : any ab.pvt.toFixed(); // Error ->ab.pvt.toFixed() : string ->ab.pvt.toFixed : (fractionDigits?: number) => string ->ab.pvt : number ->ab : mixB.(Anonymous class) & A ->pvt : number ->toFixed : (fractionDigits?: number) => string +>ab.pvt.toFixed() : any +>ab.pvt.toFixed : any +>ab.pvt : any +>ab : never +>pvt : any +>toFixed : any abc.pb.toFixed(); ->abc.pb.toFixed() : string ->abc.pb.toFixed : (fractionDigits?: number) => string ->abc.pb : number ->abc : mixC<{ new (...args: any[]): mixB.(Anonymous class); prototype: mixB.(Anonymous class); } & typeof A>.(Anonymous class) & mixB.(Anonymous class) & A ->pb : number ->toFixed : (fractionDigits?: number) => string +>abc.pb.toFixed() : any +>abc.pb.toFixed : any +>abc.pb : any +>abc : never +>pb : any +>toFixed : any abc.ptd.toFixed(); // Error ->abc.ptd.toFixed() : string ->abc.ptd.toFixed : (fractionDigits?: number) => string ->abc.ptd : number ->abc : mixC<{ new (...args: any[]): mixB.(Anonymous class); prototype: mixB.(Anonymous class); } & typeof A>.(Anonymous class) & mixB.(Anonymous class) & A ->ptd : number ->toFixed : (fractionDigits?: number) => string +>abc.ptd.toFixed() : any +>abc.ptd.toFixed : any +>abc.ptd : any +>abc : never +>ptd : any +>toFixed : any abc.pvt.toFixed(); // Error ->abc.pvt.toFixed() : string ->abc.pvt.toFixed : (fractionDigits?: number) => string ->abc.pvt : number ->abc : mixC<{ new (...args: any[]): mixB.(Anonymous class); prototype: mixB.(Anonymous class); } & typeof A>.(Anonymous class) & mixB.(Anonymous class) & A ->pvt : number ->toFixed : (fractionDigits?: number) => string +>abc.pvt.toFixed() : any +>abc.pvt.toFixed : any +>abc.pvt : any +>abc : never +>pvt : any +>toFixed : any ab2c.pb.toFixed(); ->ab2c.pb.toFixed() : string ->ab2c.pb.toFixed : (fractionDigits?: number) => string ->ab2c.pb : number ->ab2c : mixC<{ new (...args: any[]): mixB2.(Anonymous class); prototype: mixB2.(Anonymous class); } & typeof A>.(Anonymous class) & mixB2.(Anonymous class) & A ->pb : number ->toFixed : (fractionDigits?: number) => string +>ab2c.pb.toFixed() : any +>ab2c.pb.toFixed : any +>ab2c.pb : any +>ab2c : never +>pb : any +>toFixed : any ab2c.ptd.toFixed(); // Error ->ab2c.ptd.toFixed() : string ->ab2c.ptd.toFixed : (fractionDigits?: number) => string ->ab2c.ptd : number ->ab2c : mixC<{ new (...args: any[]): mixB2.(Anonymous class); prototype: mixB2.(Anonymous class); } & typeof A>.(Anonymous class) & mixB2.(Anonymous class) & A ->ptd : number ->toFixed : (fractionDigits?: number) => string +>ab2c.ptd.toFixed() : any +>ab2c.ptd.toFixed : any +>ab2c.ptd : any +>ab2c : never +>ptd : any +>toFixed : any ab2c.pvt.toFixed(); // Error ->ab2c.pvt.toFixed() : string ->ab2c.pvt.toFixed : (fractionDigits?: number) => string ->ab2c.pvt : number ->ab2c : mixC<{ new (...args: any[]): mixB2.(Anonymous class); prototype: mixB2.(Anonymous class); } & typeof A>.(Anonymous class) & mixB2.(Anonymous class) & A ->pvt : number ->toFixed : (fractionDigits?: number) => string +>ab2c.pvt.toFixed() : any +>ab2c.pvt.toFixed : any +>ab2c.pvt : any +>ab2c : never +>pvt : any +>toFixed : any // Repro from #13924 diff --git a/tests/baselines/reference/typeGuardsWithInstanceOf.errors.txt b/tests/baselines/reference/typeGuardsWithInstanceOf.errors.txt index dfcb8a598dae5..56a6973582f20 100644 --- a/tests/baselines/reference/typeGuardsWithInstanceOf.errors.txt +++ b/tests/baselines/reference/typeGuardsWithInstanceOf.errors.txt @@ -1,4 +1,5 @@ tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOf.ts(7,20): error TS2339: Property 'global' does not exist on type 'never'. + The intersection 'I & RegExp' was reduced to 'never' because property 'global' has conflicting types in some constituents. ==== tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOf.ts (1 errors) ==== @@ -11,4 +12,5 @@ tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOf.ts(7,20) } else if (!result.global) { ~~~~~~ !!! error TS2339: Property 'global' does not exist on type 'never'. +!!! error TS2339: The intersection 'I & RegExp' was reduced to 'never' because property 'global' has conflicting types in some constituents. } \ No newline at end of file From a3b90b80aa4876aa5b5154ab3fd4df7d05093811 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 2 Apr 2020 12:35:42 -0700 Subject: [PATCH 4/6] Add tests --- ...rsectionWithConflictingPrivates.errors.txt | 70 ++++++++ .../intersectionWithConflictingPrivates.js | 104 ++++++++++++ ...ntersectionWithConflictingPrivates.symbols | 141 ++++++++++++++++ .../intersectionWithConflictingPrivates.types | 153 ++++++++++++++++++ .../intersectionWithConflictingPrivates.ts | 59 +++++++ 5 files changed, 527 insertions(+) create mode 100644 tests/baselines/reference/intersectionWithConflictingPrivates.errors.txt create mode 100644 tests/baselines/reference/intersectionWithConflictingPrivates.js create mode 100644 tests/baselines/reference/intersectionWithConflictingPrivates.symbols create mode 100644 tests/baselines/reference/intersectionWithConflictingPrivates.types create mode 100644 tests/cases/compiler/intersectionWithConflictingPrivates.ts diff --git a/tests/baselines/reference/intersectionWithConflictingPrivates.errors.txt b/tests/baselines/reference/intersectionWithConflictingPrivates.errors.txt new file mode 100644 index 0000000000000..89badbd16e264 --- /dev/null +++ b/tests/baselines/reference/intersectionWithConflictingPrivates.errors.txt @@ -0,0 +1,70 @@ +tests/cases/compiler/intersectionWithConflictingPrivates.ts(5,4): error TS2339: Property 'y' does not exist on type 'never'. + The intersection 'A & B' was reduced to 'never' because property 'x' exists in multiple constituents and is private in some. +tests/cases/compiler/intersectionWithConflictingPrivates.ts(6,1): error TS2322: Type '{}' is not assignable to type 'never'. + The intersection 'A & B' was reduced to 'never' because property 'x' exists in multiple constituents and is private in some. + + +==== tests/cases/compiler/intersectionWithConflictingPrivates.ts (2 errors) ==== + class A { private x: unknown; y?: string; } + class B { private x: unknown; y?: string; } + + declare let ab: A & B; + ab.y = 'hello'; + ~ +!!! error TS2339: Property 'y' does not exist on type 'never'. +!!! error TS2339: The intersection 'A & B' was reduced to 'never' because property 'x' exists in multiple constituents and is private in some. + ab = {}; + ~~ +!!! error TS2322: Type '{}' is not assignable to type 'never'. +!!! error TS2322: The intersection 'A & B' was reduced to 'never' because property 'x' exists in multiple constituents and is private in some. + + function f1(node: A | B) { + if (node instanceof A || node instanceof A) { + node; // A + } + else { + node; // B + } + node; // A | B + } + + // Repro from #37659 + + abstract class ViewNode { } + abstract class ViewRefNode extends ViewNode { } + abstract class ViewRefFileNode extends ViewRefNode { } + + class CommitFileNode extends ViewRefFileNode { + private _id: any; + } + + class ResultsFileNode extends ViewRefFileNode { + private _id: any; + } + + class StashFileNode extends CommitFileNode { + private _id2: any; + } + + class StatusFileNode extends ViewNode { + private _id: any; + } + + class Foo { + private async foo(node: CommitFileNode | ResultsFileNode | StashFileNode) { + if ( + !(node instanceof CommitFileNode) && + !(node instanceof StashFileNode) && + !(node instanceof ResultsFileNode) + ) { + return; + } + + await this.bar(node); + } + + private async bar(node: CommitFileNode | ResultsFileNode | StashFileNode | StatusFileNode, options?: {}) { + return Promise.resolve(undefined); + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/intersectionWithConflictingPrivates.js b/tests/baselines/reference/intersectionWithConflictingPrivates.js new file mode 100644 index 0000000000000..05f91d7aa5f23 --- /dev/null +++ b/tests/baselines/reference/intersectionWithConflictingPrivates.js @@ -0,0 +1,104 @@ +//// [intersectionWithConflictingPrivates.ts] +class A { private x: unknown; y?: string; } +class B { private x: unknown; y?: string; } + +declare let ab: A & B; +ab.y = 'hello'; +ab = {}; + +function f1(node: A | B) { + if (node instanceof A || node instanceof A) { + node; // A + } + else { + node; // B + } + node; // A | B +} + +// Repro from #37659 + +abstract class ViewNode { } +abstract class ViewRefNode extends ViewNode { } +abstract class ViewRefFileNode extends ViewRefNode { } + +class CommitFileNode extends ViewRefFileNode { + private _id: any; +} + +class ResultsFileNode extends ViewRefFileNode { + private _id: any; +} + +class StashFileNode extends CommitFileNode { + private _id2: any; +} + +class StatusFileNode extends ViewNode { + private _id: any; +} + +class Foo { + private async foo(node: CommitFileNode | ResultsFileNode | StashFileNode) { + if ( + !(node instanceof CommitFileNode) && + !(node instanceof StashFileNode) && + !(node instanceof ResultsFileNode) + ) { + return; + } + + await this.bar(node); + } + + private async bar(node: CommitFileNode | ResultsFileNode | StashFileNode | StatusFileNode, options?: {}) { + return Promise.resolve(undefined); + } +} + + +//// [intersectionWithConflictingPrivates.js] +"use strict"; +class A { +} +class B { +} +ab.y = 'hello'; +ab = {}; +function f1(node) { + if (node instanceof A || node instanceof A) { + node; // A + } + else { + node; // B + } + node; // A | B +} +// Repro from #37659 +class ViewNode { +} +class ViewRefNode extends ViewNode { +} +class ViewRefFileNode extends ViewRefNode { +} +class CommitFileNode extends ViewRefFileNode { +} +class ResultsFileNode extends ViewRefFileNode { +} +class StashFileNode extends CommitFileNode { +} +class StatusFileNode extends ViewNode { +} +class Foo { + async foo(node) { + if (!(node instanceof CommitFileNode) && + !(node instanceof StashFileNode) && + !(node instanceof ResultsFileNode)) { + return; + } + await this.bar(node); + } + async bar(node, options) { + return Promise.resolve(undefined); + } +} diff --git a/tests/baselines/reference/intersectionWithConflictingPrivates.symbols b/tests/baselines/reference/intersectionWithConflictingPrivates.symbols new file mode 100644 index 0000000000000..a59fe008c244b --- /dev/null +++ b/tests/baselines/reference/intersectionWithConflictingPrivates.symbols @@ -0,0 +1,141 @@ +=== tests/cases/compiler/intersectionWithConflictingPrivates.ts === +class A { private x: unknown; y?: string; } +>A : Symbol(A, Decl(intersectionWithConflictingPrivates.ts, 0, 0)) +>x : Symbol(A.x, Decl(intersectionWithConflictingPrivates.ts, 0, 9)) +>y : Symbol(A.y, Decl(intersectionWithConflictingPrivates.ts, 0, 29)) + +class B { private x: unknown; y?: string; } +>B : Symbol(B, Decl(intersectionWithConflictingPrivates.ts, 0, 43)) +>x : Symbol(B.x, Decl(intersectionWithConflictingPrivates.ts, 1, 9)) +>y : Symbol(B.y, Decl(intersectionWithConflictingPrivates.ts, 1, 29)) + +declare let ab: A & B; +>ab : Symbol(ab, Decl(intersectionWithConflictingPrivates.ts, 3, 11)) +>A : Symbol(A, Decl(intersectionWithConflictingPrivates.ts, 0, 0)) +>B : Symbol(B, Decl(intersectionWithConflictingPrivates.ts, 0, 43)) + +ab.y = 'hello'; +>ab : Symbol(ab, Decl(intersectionWithConflictingPrivates.ts, 3, 11)) + +ab = {}; +>ab : Symbol(ab, Decl(intersectionWithConflictingPrivates.ts, 3, 11)) + +function f1(node: A | B) { +>f1 : Symbol(f1, Decl(intersectionWithConflictingPrivates.ts, 5, 8)) +>node : Symbol(node, Decl(intersectionWithConflictingPrivates.ts, 7, 12)) +>A : Symbol(A, Decl(intersectionWithConflictingPrivates.ts, 0, 0)) +>B : Symbol(B, Decl(intersectionWithConflictingPrivates.ts, 0, 43)) + + if (node instanceof A || node instanceof A) { +>node : Symbol(node, Decl(intersectionWithConflictingPrivates.ts, 7, 12)) +>A : Symbol(A, Decl(intersectionWithConflictingPrivates.ts, 0, 0)) +>node : Symbol(node, Decl(intersectionWithConflictingPrivates.ts, 7, 12)) +>A : Symbol(A, Decl(intersectionWithConflictingPrivates.ts, 0, 0)) + + node; // A +>node : Symbol(node, Decl(intersectionWithConflictingPrivates.ts, 7, 12)) + } + else { + node; // B +>node : Symbol(node, Decl(intersectionWithConflictingPrivates.ts, 7, 12)) + } + node; // A | B +>node : Symbol(node, Decl(intersectionWithConflictingPrivates.ts, 7, 12)) +} + +// Repro from #37659 + +abstract class ViewNode { } +>ViewNode : Symbol(ViewNode, Decl(intersectionWithConflictingPrivates.ts, 15, 1)) + +abstract class ViewRefNode extends ViewNode { } +>ViewRefNode : Symbol(ViewRefNode, Decl(intersectionWithConflictingPrivates.ts, 19, 27)) +>ViewNode : Symbol(ViewNode, Decl(intersectionWithConflictingPrivates.ts, 15, 1)) + +abstract class ViewRefFileNode extends ViewRefNode { } +>ViewRefFileNode : Symbol(ViewRefFileNode, Decl(intersectionWithConflictingPrivates.ts, 20, 47)) +>ViewRefNode : Symbol(ViewRefNode, Decl(intersectionWithConflictingPrivates.ts, 19, 27)) + +class CommitFileNode extends ViewRefFileNode { +>CommitFileNode : Symbol(CommitFileNode, Decl(intersectionWithConflictingPrivates.ts, 21, 54)) +>ViewRefFileNode : Symbol(ViewRefFileNode, Decl(intersectionWithConflictingPrivates.ts, 20, 47)) + + private _id: any; +>_id : Symbol(CommitFileNode._id, Decl(intersectionWithConflictingPrivates.ts, 23, 46)) +} + +class ResultsFileNode extends ViewRefFileNode { +>ResultsFileNode : Symbol(ResultsFileNode, Decl(intersectionWithConflictingPrivates.ts, 25, 1)) +>ViewRefFileNode : Symbol(ViewRefFileNode, Decl(intersectionWithConflictingPrivates.ts, 20, 47)) + + private _id: any; +>_id : Symbol(ResultsFileNode._id, Decl(intersectionWithConflictingPrivates.ts, 27, 47)) +} + +class StashFileNode extends CommitFileNode { +>StashFileNode : Symbol(StashFileNode, Decl(intersectionWithConflictingPrivates.ts, 29, 1)) +>CommitFileNode : Symbol(CommitFileNode, Decl(intersectionWithConflictingPrivates.ts, 21, 54)) + + private _id2: any; +>_id2 : Symbol(StashFileNode._id2, Decl(intersectionWithConflictingPrivates.ts, 31, 44)) +} + +class StatusFileNode extends ViewNode { +>StatusFileNode : Symbol(StatusFileNode, Decl(intersectionWithConflictingPrivates.ts, 33, 1)) +>ViewNode : Symbol(ViewNode, Decl(intersectionWithConflictingPrivates.ts, 15, 1)) + + private _id: any; +>_id : Symbol(StatusFileNode._id, Decl(intersectionWithConflictingPrivates.ts, 35, 39)) +} + +class Foo { +>Foo : Symbol(Foo, Decl(intersectionWithConflictingPrivates.ts, 37, 1)) + + private async foo(node: CommitFileNode | ResultsFileNode | StashFileNode) { +>foo : Symbol(Foo.foo, Decl(intersectionWithConflictingPrivates.ts, 39, 11)) +>node : Symbol(node, Decl(intersectionWithConflictingPrivates.ts, 40, 20)) +>CommitFileNode : Symbol(CommitFileNode, Decl(intersectionWithConflictingPrivates.ts, 21, 54)) +>ResultsFileNode : Symbol(ResultsFileNode, Decl(intersectionWithConflictingPrivates.ts, 25, 1)) +>StashFileNode : Symbol(StashFileNode, Decl(intersectionWithConflictingPrivates.ts, 29, 1)) + + if ( + !(node instanceof CommitFileNode) && +>node : Symbol(node, Decl(intersectionWithConflictingPrivates.ts, 40, 20)) +>CommitFileNode : Symbol(CommitFileNode, Decl(intersectionWithConflictingPrivates.ts, 21, 54)) + + !(node instanceof StashFileNode) && +>node : Symbol(node, Decl(intersectionWithConflictingPrivates.ts, 40, 20)) +>StashFileNode : Symbol(StashFileNode, Decl(intersectionWithConflictingPrivates.ts, 29, 1)) + + !(node instanceof ResultsFileNode) +>node : Symbol(node, Decl(intersectionWithConflictingPrivates.ts, 40, 20)) +>ResultsFileNode : Symbol(ResultsFileNode, Decl(intersectionWithConflictingPrivates.ts, 25, 1)) + + ) { + return; + } + + await this.bar(node); +>this.bar : Symbol(Foo.bar, Decl(intersectionWithConflictingPrivates.ts, 50, 2)) +>this : Symbol(Foo, Decl(intersectionWithConflictingPrivates.ts, 37, 1)) +>bar : Symbol(Foo.bar, Decl(intersectionWithConflictingPrivates.ts, 50, 2)) +>node : Symbol(node, Decl(intersectionWithConflictingPrivates.ts, 40, 20)) + } + + private async bar(node: CommitFileNode | ResultsFileNode | StashFileNode | StatusFileNode, options?: {}) { +>bar : Symbol(Foo.bar, Decl(intersectionWithConflictingPrivates.ts, 50, 2)) +>node : Symbol(node, Decl(intersectionWithConflictingPrivates.ts, 52, 20)) +>CommitFileNode : Symbol(CommitFileNode, Decl(intersectionWithConflictingPrivates.ts, 21, 54)) +>ResultsFileNode : Symbol(ResultsFileNode, Decl(intersectionWithConflictingPrivates.ts, 25, 1)) +>StashFileNode : Symbol(StashFileNode, Decl(intersectionWithConflictingPrivates.ts, 29, 1)) +>StatusFileNode : Symbol(StatusFileNode, Decl(intersectionWithConflictingPrivates.ts, 33, 1)) +>options : Symbol(options, Decl(intersectionWithConflictingPrivates.ts, 52, 92)) + + return Promise.resolve(undefined); +>Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --)) +>resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>undefined : Symbol(undefined) + } +} + diff --git a/tests/baselines/reference/intersectionWithConflictingPrivates.types b/tests/baselines/reference/intersectionWithConflictingPrivates.types new file mode 100644 index 0000000000000..c92dce4af4b8b --- /dev/null +++ b/tests/baselines/reference/intersectionWithConflictingPrivates.types @@ -0,0 +1,153 @@ +=== tests/cases/compiler/intersectionWithConflictingPrivates.ts === +class A { private x: unknown; y?: string; } +>A : A +>x : unknown +>y : string | undefined + +class B { private x: unknown; y?: string; } +>B : B +>x : unknown +>y : string | undefined + +declare let ab: A & B; +>ab : never + +ab.y = 'hello'; +>ab.y = 'hello' : "hello" +>ab.y : any +>ab : never +>y : any +>'hello' : "hello" + +ab = {}; +>ab = {} : {} +>ab : never +>{} : {} + +function f1(node: A | B) { +>f1 : (node: A | B) => void +>node : A | B + + if (node instanceof A || node instanceof A) { +>node instanceof A || node instanceof A : boolean +>node instanceof A : boolean +>node : A | B +>A : typeof A +>node instanceof A : boolean +>node : B +>A : typeof A + + node; // A +>node : A + } + else { + node; // B +>node : B + } + node; // A | B +>node : A | B +} + +// Repro from #37659 + +abstract class ViewNode { } +>ViewNode : ViewNode + +abstract class ViewRefNode extends ViewNode { } +>ViewRefNode : ViewRefNode +>ViewNode : ViewNode + +abstract class ViewRefFileNode extends ViewRefNode { } +>ViewRefFileNode : ViewRefFileNode +>ViewRefNode : ViewRefNode + +class CommitFileNode extends ViewRefFileNode { +>CommitFileNode : CommitFileNode +>ViewRefFileNode : ViewRefFileNode + + private _id: any; +>_id : any +} + +class ResultsFileNode extends ViewRefFileNode { +>ResultsFileNode : ResultsFileNode +>ViewRefFileNode : ViewRefFileNode + + private _id: any; +>_id : any +} + +class StashFileNode extends CommitFileNode { +>StashFileNode : StashFileNode +>CommitFileNode : CommitFileNode + + private _id2: any; +>_id2 : any +} + +class StatusFileNode extends ViewNode { +>StatusFileNode : StatusFileNode +>ViewNode : ViewNode + + private _id: any; +>_id : any +} + +class Foo { +>Foo : Foo + + private async foo(node: CommitFileNode | ResultsFileNode | StashFileNode) { +>foo : (node: CommitFileNode | ResultsFileNode | StashFileNode) => Promise +>node : CommitFileNode | ResultsFileNode | StashFileNode + + if ( + !(node instanceof CommitFileNode) && +>!(node instanceof CommitFileNode) && !(node instanceof StashFileNode) && !(node instanceof ResultsFileNode) : boolean +>!(node instanceof CommitFileNode) && !(node instanceof StashFileNode) : boolean +>!(node instanceof CommitFileNode) : boolean +>(node instanceof CommitFileNode) : boolean +>node instanceof CommitFileNode : boolean +>node : CommitFileNode | ResultsFileNode | StashFileNode +>CommitFileNode : typeof CommitFileNode + + !(node instanceof StashFileNode) && +>!(node instanceof StashFileNode) : boolean +>(node instanceof StashFileNode) : boolean +>node instanceof StashFileNode : boolean +>node : ResultsFileNode +>StashFileNode : typeof StashFileNode + + !(node instanceof ResultsFileNode) +>!(node instanceof ResultsFileNode) : boolean +>(node instanceof ResultsFileNode) : boolean +>node instanceof ResultsFileNode : boolean +>node : ResultsFileNode +>ResultsFileNode : typeof ResultsFileNode + + ) { + return; + } + + await this.bar(node); +>await this.bar(node) : undefined +>this.bar(node) : Promise +>this.bar : (node: CommitFileNode | ResultsFileNode | StashFileNode | StatusFileNode, options?: {} | undefined) => Promise +>this : this +>bar : (node: CommitFileNode | ResultsFileNode | StashFileNode | StatusFileNode, options?: {} | undefined) => Promise +>node : CommitFileNode | ResultsFileNode + } + + private async bar(node: CommitFileNode | ResultsFileNode | StashFileNode | StatusFileNode, options?: {}) { +>bar : (node: CommitFileNode | ResultsFileNode | StashFileNode | StatusFileNode, options?: {} | undefined) => Promise +>node : CommitFileNode | ResultsFileNode | StashFileNode | StatusFileNode +>options : {} | undefined + + return Promise.resolve(undefined); +>Promise.resolve(undefined) : Promise +>Promise.resolve : { (value: T | PromiseLike): Promise; (): Promise; } +>Promise : PromiseConstructor +>resolve : { (value: T | PromiseLike): Promise; (): Promise; } +>undefined : undefined + } +} + diff --git a/tests/cases/compiler/intersectionWithConflictingPrivates.ts b/tests/cases/compiler/intersectionWithConflictingPrivates.ts new file mode 100644 index 0000000000000..e9aa08b2799b4 --- /dev/null +++ b/tests/cases/compiler/intersectionWithConflictingPrivates.ts @@ -0,0 +1,59 @@ +// @strict: true +// @target: esnext + +class A { private x: unknown; y?: string; } +class B { private x: unknown; y?: string; } + +declare let ab: A & B; +ab.y = 'hello'; +ab = {}; + +function f1(node: A | B) { + if (node instanceof A || node instanceof A) { + node; // A + } + else { + node; // B + } + node; // A | B +} + +// Repro from #37659 + +abstract class ViewNode { } +abstract class ViewRefNode extends ViewNode { } +abstract class ViewRefFileNode extends ViewRefNode { } + +class CommitFileNode extends ViewRefFileNode { + private _id: any; +} + +class ResultsFileNode extends ViewRefFileNode { + private _id: any; +} + +class StashFileNode extends CommitFileNode { + private _id2: any; +} + +class StatusFileNode extends ViewNode { + private _id: any; +} + +class Foo { + private async foo(node: CommitFileNode | ResultsFileNode | StashFileNode) { + if ( + !(node instanceof CommitFileNode) && + !(node instanceof StashFileNode) && + !(node instanceof ResultsFileNode) + ) { + return; + } + + await this.bar(node); + } + + private async bar(node: CommitFileNode | ResultsFileNode | StashFileNode | StatusFileNode, options?: {}) { + return Promise.resolve(undefined); + } +} From 88708389874642e3080d6f7fd02b67db2008243f Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 2 Apr 2020 12:54:34 -0700 Subject: [PATCH 5/6] Accept new baselines --- tests/baselines/reference/mixinAccessModifiers.types | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/baselines/reference/mixinAccessModifiers.types b/tests/baselines/reference/mixinAccessModifiers.types index ac174d27a23b4..9b4cb432ab2e2 100644 --- a/tests/baselines/reference/mixinAccessModifiers.types +++ b/tests/baselines/reference/mixinAccessModifiers.types @@ -76,7 +76,7 @@ class Public2 { } function f1(x: Private & Private2) { ->f1 : (x: never) => void +>f1 : (x: Private & Private2) => void >x : never x.p; // Error, private constituent makes property inaccessible @@ -86,7 +86,7 @@ function f1(x: Private & Private2) { } function f2(x: Private & Protected) { ->f2 : (x: never) => void +>f2 : (x: Private & Protected) => void >x : never x.p; // Error, private constituent makes property inaccessible @@ -96,7 +96,7 @@ function f2(x: Private & Protected) { } function f3(x: Private & Public) { ->f3 : (x: never) => void +>f3 : (x: Private & Public) => void >x : never x.p; // Error, private constituent makes property inaccessible @@ -345,7 +345,7 @@ function f7(x: ProtectedGeneric<{}> & ProtectedGeneric<{}>) { } function f8(x: ProtectedGeneric<{a: void;}> & ProtectedGeneric2<{a:void;b:void;}>) { ->f8 : (x: never) => void +>f8 : (x: ProtectedGeneric<{ a: void;}> & ProtectedGeneric2<{ a: void; b: void;}>) => void >x : never >a : void >a : void From 85db315ee4e0e4aca84b8383108c3fcc9dc93fc0 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 2 Apr 2020 17:39:09 -0700 Subject: [PATCH 6/6] Address CR feedback --- src/compiler/checker.ts | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8aac84fe8288f..808172111b095 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8470,7 +8470,7 @@ namespace ts { } const reducedBaseType = getReducedType(baseType); if (!isValidBaseType(reducedBaseType)) { - const elaboration = baseType.flags & TypeFlags.Intersection && reducedBaseType.flags & TypeFlags.Never ? elaborateNeverIntersection(/*errorInfo*/ undefined, baseType) : undefined; + const elaboration = elaborateNeverIntersection(/*errorInfo*/ undefined, baseType); const diagnostic = chainDiagnosticMessages(elaboration, Diagnostics.Base_constructor_return_type_0_is_not_an_object_type_or_intersection_of_object_types_with_statically_known_members, typeToString(reducedBaseType)); diagnostics.add(createDiagnosticForNodeFromMessageChain(baseTypeNode.expression, diagnostic)); return type.resolvedBaseTypes = emptyArray; @@ -10498,16 +10498,18 @@ namespace ts { return !prop.valueDeclaration && !!(getCheckFlags(prop) & CheckFlags.ContainsPrivate); } - function elaborateNeverIntersection(errorInfo: DiagnosticMessageChain | undefined, type: IntersectionType) { - const neverProp = find(getPropertiesOfUnionOrIntersectionType(type), isDiscriminantWithNeverType); - if (neverProp) { - return chainDiagnosticMessages(errorInfo, Diagnostics.The_intersection_0_was_reduced_to_never_because_property_1_has_conflicting_types_in_some_constituents, - typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.NoTypeReduction), symbolToString(neverProp)); - } - const privateProp = find(getPropertiesOfUnionOrIntersectionType(type), isConflictingPrivateProperty); - if (privateProp) { - return chainDiagnosticMessages(errorInfo, Diagnostics.The_intersection_0_was_reduced_to_never_because_property_1_exists_in_multiple_constituents_and_is_private_in_some, - typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.NoTypeReduction), symbolToString(privateProp)); + function elaborateNeverIntersection(errorInfo: DiagnosticMessageChain | undefined, type: Type) { + if (getObjectFlags(type) & ObjectFlags.IsNeverIntersection) { + const neverProp = find(getPropertiesOfUnionOrIntersectionType(type), isDiscriminantWithNeverType); + if (neverProp) { + return chainDiagnosticMessages(errorInfo, Diagnostics.The_intersection_0_was_reduced_to_never_because_property_1_has_conflicting_types_in_some_constituents, + typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.NoTypeReduction), symbolToString(neverProp)); + } + const privateProp = find(getPropertiesOfUnionOrIntersectionType(type), isConflictingPrivateProperty); + if (privateProp) { + return chainDiagnosticMessages(errorInfo, Diagnostics.The_intersection_0_was_reduced_to_never_because_property_1_exists_in_multiple_constituents_and_is_private_in_some, + typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.NoTypeReduction), symbolToString(privateProp)); + } } return errorInfo; } @@ -15639,8 +15641,8 @@ namespace ts { return result; } } - else if (target.flags & TypeFlags.Never && originalTarget.flags & TypeFlags.Intersection) { - errorInfo = elaborateNeverIntersection(errorInfo, originalTarget); + else { + errorInfo = elaborateNeverIntersection(errorInfo, originalTarget); } if (!headMessage && maybeSuppress) { lastSkippedInfo = [source, target]; @@ -24154,10 +24156,7 @@ namespace ts { relatedInfo = suggestion.valueDeclaration && createDiagnosticForNode(suggestion.valueDeclaration, Diagnostics._0_is_declared_here, suggestedName); } else { - if (containingType.flags & TypeFlags.Intersection && getReducedType(containingType).flags & TypeFlags.Never) { - errorInfo = elaborateNeverIntersection(errorInfo, containingType); - } - errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1, declarationNameToString(propNode), typeToString(containingType)); + errorInfo = chainDiagnosticMessages(elaborateNeverIntersection(errorInfo, containingType), Diagnostics.Property_0_does_not_exist_on_type_1, declarationNameToString(propNode), typeToString(containingType)); } } }