diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e24c707d2d..1e54b5d784 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -22567,23 +22567,35 @@ namespace ts { } if (isConstEnumObjectType(type)) { - // enum object type for const enums are only permitted in: - // - 'left' in property access - // - 'object' in indexed access - // - target in rhs of import statement - const ok = - (node.parent.kind === SyntaxKind.PropertyAccessExpression && (node.parent).expression === node) || - (node.parent.kind === SyntaxKind.ElementAccessExpression && (node.parent).expression === node) || - ((node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.QualifiedName) && isInRightSideOfImportOrExportAssignment(node) || - (node.parent.kind === SyntaxKind.TypeQuery && (node.parent).exprName === node)); - - if (!ok) { - error(node, Diagnostics.const_enums_can_only_be_used_in_property_or_index_access_expressions_or_the_right_hand_side_of_an_import_declaration_or_export_assignment_or_type_query); - } + checkConstEnumAccess(node, type); } return type; } + function checkConstEnumAccess(node: Expression | QualifiedName, type: Type) { + // enum object type for const enums are only permitted in: + // - 'left' in property access + // - 'object' in indexed access + // - target in rhs of import statement + const ok = + (node.parent.kind === SyntaxKind.PropertyAccessExpression && (node.parent).expression === node) || + (node.parent.kind === SyntaxKind.ElementAccessExpression && (node.parent).expression === node) || + ((node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.QualifiedName) && isInRightSideOfImportOrExportAssignment(node) || + (node.parent.kind === SyntaxKind.TypeQuery && (node.parent).exprName === node)); + + if (!ok) { + error(node, Diagnostics.const_enums_can_only_be_used_in_property_or_index_access_expressions_or_the_right_hand_side_of_an_import_declaration_or_export_assignment_or_type_query); + } + + if (compilerOptions.isolatedModules) { + Debug.assert(!!(type.symbol.flags & SymbolFlags.ConstEnum)); + const constEnumDeclaration = type.symbol.valueDeclaration as EnumDeclaration; + if (constEnumDeclaration.flags & NodeFlags.Ambient) { + error(node, Diagnostics.Cannot_access_ambient_const_enums_when_the_isolatedModules_flag_is_provided); + } + } + } + function checkParenthesizedExpression(node: ParenthesizedExpression, checkMode?: CheckMode): Type { const tag = isInJSFile(node) ? getJSDocTypeTag(node) : undefined; if (tag) { @@ -26721,11 +26733,6 @@ namespace ts { computeEnumMemberValues(node); - const enumIsConst = isEnumConst(node); - if (compilerOptions.isolatedModules && enumIsConst && node.flags & NodeFlags.Ambient) { - error(node.name, Diagnostics.Ambient_const_enums_are_not_allowed_when_the_isolatedModules_flag_is_provided); - } - // Spec 2014 - Section 9.3: // It isn't possible for one enum declaration to continue the automatic numbering sequence of another, // and when an enum type has multiple declarations, only one declaration is permitted to omit a value @@ -26736,6 +26743,7 @@ namespace ts { const firstDeclaration = getDeclarationOfKind(enumSymbol, node.kind); if (node === firstDeclaration) { if (enumSymbol.declarations.length > 1) { + const enumIsConst = isEnumConst(node); // check that const is placed\omitted on all enum declarations forEach(enumSymbol.declarations, decl => { if (isEnumDeclaration(decl) && isEnumConst(decl) !== enumIsConst) { diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 3ba74f0307..f593a49398 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -659,10 +659,6 @@ "category": "Error", "code": 1208 }, - "Ambient const enums are not allowed when the '--isolatedModules' flag is provided.": { - "category": "Error", - "code": 1209 - }, "Invalid use of '{0}'. Class definitions are automatically in strict mode.": { "category": "Error", "code": 1210 @@ -2513,6 +2509,10 @@ "category": "Message", "code": 2738 }, + "Cannot access ambient const enums when the '--isolatedModules' flag is provided.": { + "category": "Error", + "code": 2739 + }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", diff --git a/tests/baselines/reference/isolatedModulesAmbientConstEnum.errors.txt b/tests/baselines/reference/isolatedModulesAmbientConstEnum.errors.txt index 642e38cc6e..c4569f2ac3 100644 --- a/tests/baselines/reference/isolatedModulesAmbientConstEnum.errors.txt +++ b/tests/baselines/reference/isolatedModulesAmbientConstEnum.errors.txt @@ -1,8 +1,9 @@ -tests/cases/compiler/file1.ts(1,20): error TS1209: Ambient const enums are not allowed when the '--isolatedModules' flag is provided. +tests/cases/compiler/file1.ts(2,16): error TS2739: Cannot access ambient const enums when the '--isolatedModules' flag is provided. ==== tests/cases/compiler/file1.ts (1 errors) ==== declare const enum E { X = 1} - ~ -!!! error TS1209: Ambient const enums are not allowed when the '--isolatedModules' flag is provided. - export var y; \ No newline at end of file + export var y = E.X; + ~ +!!! error TS2739: Cannot access ambient const enums when the '--isolatedModules' flag is provided. + \ No newline at end of file diff --git a/tests/baselines/reference/isolatedModulesAmbientConstEnum.js b/tests/baselines/reference/isolatedModulesAmbientConstEnum.js index 44b6e1c1d7..2977c8ab82 100644 --- a/tests/baselines/reference/isolatedModulesAmbientConstEnum.js +++ b/tests/baselines/reference/isolatedModulesAmbientConstEnum.js @@ -1,6 +1,7 @@ //// [file1.ts] declare const enum E { X = 1} -export var y; +export var y = E.X; + //// [file1.js] -export var y; +export var y = E.X; diff --git a/tests/baselines/reference/isolatedModulesAmbientConstEnum.symbols b/tests/baselines/reference/isolatedModulesAmbientConstEnum.symbols index 2da04dbdf0..828f79379b 100644 --- a/tests/baselines/reference/isolatedModulesAmbientConstEnum.symbols +++ b/tests/baselines/reference/isolatedModulesAmbientConstEnum.symbols @@ -3,6 +3,9 @@ declare const enum E { X = 1} >E : Symbol(E, Decl(file1.ts, 0, 0)) >X : Symbol(E.X, Decl(file1.ts, 0, 22)) -export var y; +export var y = E.X; >y : Symbol(y, Decl(file1.ts, 1, 10)) +>E.X : Symbol(E.X, Decl(file1.ts, 0, 22)) +>E : Symbol(E, Decl(file1.ts, 0, 0)) +>X : Symbol(E.X, Decl(file1.ts, 0, 22)) diff --git a/tests/baselines/reference/isolatedModulesAmbientConstEnum.types b/tests/baselines/reference/isolatedModulesAmbientConstEnum.types index 8b714d98f6..bb4212895f 100644 --- a/tests/baselines/reference/isolatedModulesAmbientConstEnum.types +++ b/tests/baselines/reference/isolatedModulesAmbientConstEnum.types @@ -4,6 +4,9 @@ declare const enum E { X = 1} >X : E.X >1 : 1 -export var y; ->y : any +export var y = E.X; +>y : E +>E.X : E +>E : typeof E +>X : E diff --git a/tests/cases/compiler/isolatedModulesAmbientConstEnum.ts b/tests/cases/compiler/isolatedModulesAmbientConstEnum.ts index 59fcdcd1fe..993235c2c0 100644 --- a/tests/cases/compiler/isolatedModulesAmbientConstEnum.ts +++ b/tests/cases/compiler/isolatedModulesAmbientConstEnum.ts @@ -4,4 +4,4 @@ // @filename: file1.ts declare const enum E { X = 1} -export var y; \ No newline at end of file +export var y = E.X;