Skip to content

Commit 36042d8

Browse files
committed
Allow references to const enums when provably emitted via preserveConstEnums
1 parent 7f5299b commit 36042d8

5 files changed

+27
-108
lines changed

src/compiler/checker.ts

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33884,7 +33884,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3388433884
return objectType;
3388533885
}
3388633886

33887-
if (isConstEnumObjectType(objectType) && !isStringLiteralLike(indexExpression)) {
33887+
if (isConstEnumObjectType(objectType) && !isStringLiteralLike(indexExpression) && !isUseOfPreservedConstEnum(node, objectType)) {
3388833888
error(indexExpression, Diagnostics.A_const_enum_member_can_only_be_accessed_using_a_string_literal);
3388933889
return errorType;
3389033890
}
@@ -39815,18 +39815,32 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3981539815
(node.parent.kind === SyntaxKind.TypeQuery && (node.parent as TypeQueryNode).exprName === node)) ||
3981639816
(node.parent.kind === SyntaxKind.ExportSpecifier); // We allow reexporting const enums
3981739817

39818-
if (!ok) {
39819-
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);
39818+
if (!ok || getIsolatedModules(compilerOptions)) {
39819+
if (!isUseOfPreservedConstEnum(node, type)) {
39820+
if (!ok) {
39821+
// TODO(jakebailey): make error message mention const enum preservation
39822+
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);
39823+
}
39824+
else if (type.symbol.valueDeclaration!.flags & NodeFlags.Ambient && !isValidTypeOnlyAliasUseSite(node)) {
39825+
error(node, Diagnostics.Cannot_access_ambient_const_enums_when_0_is_enabled, isolatedModulesLikeFlagName);
39826+
}
39827+
}
3982039828
}
39829+
}
3982139830

39822-
if (getIsolatedModules(compilerOptions)) {
39823-
Debug.assert(!!(type.symbol.flags & SymbolFlags.ConstEnum));
39824-
const constEnumDeclaration = type.symbol.valueDeclaration as EnumDeclaration;
39825-
const redirect = host.getRedirectReferenceForResolutionFromSourceOfProject(getSourceFileOfNode(constEnumDeclaration).resolvedPath);
39826-
if (constEnumDeclaration.flags & NodeFlags.Ambient && !isValidTypeOnlyAliasUseSite(node) && (!redirect || !shouldPreserveConstEnums(redirect.commandLine.options))) {
39827-
error(node, Diagnostics.Cannot_access_ambient_const_enums_when_0_is_enabled, isolatedModulesLikeFlagName);
39831+
function isUseOfPreservedConstEnum(use: Node, enumType: Type) {
39832+
Debug.assert(!!(enumType.symbol.flags & SymbolFlags.ConstEnum));
39833+
const constEnumDeclaration = enumType.symbol.valueDeclaration as EnumDeclaration;
39834+
const otherFile = getSourceFileOfNode(constEnumDeclaration);
39835+
if (!otherFile.isDeclarationFile) {
39836+
// This file can only have come from the current project.
39837+
if (constEnumDeclaration.flags & NodeFlags.Ambient && !isValidTypeOnlyAliasUseSite(use)) {
39838+
return false;
3982839839
}
39840+
return shouldPreserveConstEnums(compilerOptions);
3982939841
}
39842+
const redirect = host.getRedirectReferenceForResolutionFromSourceOfProject(otherFile.resolvedPath);
39843+
return redirect && shouldPreserveConstEnums(redirect.commandLine.options);
3983039844
}
3983139845

3983239846
function checkParenthesizedExpression(node: ParenthesizedExpression, checkMode?: CheckMode): Type {

tests/baselines/reference/constEnumUsedAsValue(preserveconstenums=true).errors.txt

Lines changed: 0 additions & 19 deletions
This file was deleted.

tests/baselines/reference/constEnumUsedAsValue(preserveconstenums=true).types

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ E;
2727
> : ^^^^^^^^
2828

2929
E[x];
30-
>E[x] : any
31-
> : ^^^
30+
>E[x] : string
31+
> : ^^^^^^
3232
>E : typeof E
3333
> : ^^^^^^^^
3434
>x : E

tests/baselines/reference/tsc/projectReferences/referencing-ambient-const-enum-as-value-from-referenced-project-with-preserveConstEnums.js

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -71,30 +71,7 @@ export const enum E2 { A = 1 }
7171

7272
Output::
7373
/lib/tsc --p src/project
74-
src/project/index.ts:5:21 - error TS2475: '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.
75-
76-
5 E; declare const x: E; E[x];
77-
   ~
78-
79-
src/project/index.ts:5:46 - error TS2476: A const enum member can only be accessed using a string literal.
80-
81-
5 E; declare const x: E; E[x];
82-
   ~
83-
84-
src/project/index.ts:7:21 - error TS2475: '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.
85-
86-
7 E2; declare const y: E2; E2[y];
87-
   ~~
88-
89-
src/project/index.ts:7:49 - error TS2476: A const enum member can only be accessed using a string literal.
90-
91-
7 E2; declare const y: E2; E2[y];
92-
   ~
93-
94-
95-
Found 4 errors in the same file, starting at: src/project/index.ts:5
96-
97-
exitCode:: ExitStatus.DiagnosticsPresent_OutputsGenerated
74+
exitCode:: ExitStatus.Success
9875

9976

10077
//// [/src/project/index.js]

tests/baselines/reference/tsserver/projectReferences/referencing-const-enum-as-value-from-referenced-project-with-preserveConstEnums.js

Lines changed: 1 addition & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -371,60 +371,7 @@ Info seq [hh:mm:ss:mss] event:
371371
"event": "semanticDiag",
372372
"body": {
373373
"file": "/user/username/projects/project/src/project/index.ts",
374-
"diagnostics": [
375-
{
376-
"start": {
377-
"line": 5,
378-
"offset": 13
379-
},
380-
"end": {
381-
"line": 5,
382-
"offset": 14
383-
},
384-
"text": "'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.",
385-
"code": 2475,
386-
"category": "error"
387-
},
388-
{
389-
"start": {
390-
"line": 5,
391-
"offset": 38
392-
},
393-
"end": {
394-
"line": 5,
395-
"offset": 39
396-
},
397-
"text": "A const enum member can only be accessed using a string literal.",
398-
"code": 2476,
399-
"category": "error"
400-
},
401-
{
402-
"start": {
403-
"line": 7,
404-
"offset": 13
405-
},
406-
"end": {
407-
"line": 7,
408-
"offset": 15
409-
},
410-
"text": "'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.",
411-
"code": 2475,
412-
"category": "error"
413-
},
414-
{
415-
"start": {
416-
"line": 7,
417-
"offset": 41
418-
},
419-
"end": {
420-
"line": 7,
421-
"offset": 42
422-
},
423-
"text": "A const enum member can only be accessed using a string literal.",
424-
"code": 2476,
425-
"category": "error"
426-
}
427-
]
374+
"diagnostics": []
428375
}
429376
}
430377
After running Immedidate callback:: count: 1

0 commit comments

Comments
 (0)