Skip to content

Commit c83323b

Browse files
committed
Allow references to const enums when provably emitted via preserveConstEnums
1 parent 08ad5b3 commit c83323b

5 files changed

+26
-106
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:33 - 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 console.log(E); declare const x: E; console.log(E[x]);
77-
   ~
78-
79-
src/project/index.ts:5:71 - error TS2476: A const enum member can only be accessed using a string literal.
80-
81-
5 console.log(E); declare const x: E; console.log(E[x]);
82-
   ~
83-
84-
src/project/index.ts:7:33 - 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 console.log(E2); declare const y: E2; console.log(E2[y]);
87-
   ~~
88-
89-
src/project/index.ts:7:74 - error TS2476: A const enum member can only be accessed using a string literal.
90-
91-
7 console.log(E2); declare const y: E2; console.log(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: 0 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -385,19 +385,6 @@ Info seq [hh:mm:ss:mss] event:
385385
"code": 2584,
386386
"category": "error"
387387
},
388-
{
389-
"start": {
390-
"line": 5,
391-
"offset": 25
392-
},
393-
"end": {
394-
"line": 5,
395-
"offset": 26
396-
},
397-
"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.",
398-
"code": 2475,
399-
"category": "error"
400-
},
401388
{
402389
"start": {
403390
"line": 5,
@@ -411,19 +398,6 @@ Info seq [hh:mm:ss:mss] event:
411398
"code": 2584,
412399
"category": "error"
413400
},
414-
{
415-
"start": {
416-
"line": 5,
417-
"offset": 63
418-
},
419-
"end": {
420-
"line": 5,
421-
"offset": 64
422-
},
423-
"text": "A const enum member can only be accessed using a string literal.",
424-
"code": 2476,
425-
"category": "error"
426-
},
427401
{
428402
"start": {
429403
"line": 7,
@@ -437,19 +411,6 @@ Info seq [hh:mm:ss:mss] event:
437411
"code": 2584,
438412
"category": "error"
439413
},
440-
{
441-
"start": {
442-
"line": 7,
443-
"offset": 25
444-
},
445-
"end": {
446-
"line": 7,
447-
"offset": 27
448-
},
449-
"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.",
450-
"code": 2475,
451-
"category": "error"
452-
},
453414
{
454415
"start": {
455416
"line": 7,
@@ -462,19 +423,6 @@ Info seq [hh:mm:ss:mss] event:
462423
"text": "Cannot find name 'console'. Do you need to change your target library? Try changing the 'lib' compiler option to include 'dom'.",
463424
"code": 2584,
464425
"category": "error"
465-
},
466-
{
467-
"start": {
468-
"line": 7,
469-
"offset": 66
470-
},
471-
"end": {
472-
"line": 7,
473-
"offset": 67
474-
},
475-
"text": "A const enum member can only be accessed using a string literal.",
476-
"code": 2476,
477-
"category": "error"
478426
}
479427
]
480428
}

0 commit comments

Comments
 (0)