Skip to content

Commit b682ed4

Browse files
authored
Lock down computed names in object literals and classes under --isolatedDeclarations (microsoft#58596)
1 parent 9370347 commit b682ed4

15 files changed

+342
-77
lines changed

src/compiler/checker.ts

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1504,7 +1504,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
15041504
var syntacticNodeBuilder = createSyntacticTypeNodeBuilder(compilerOptions, {
15051505
isEntityNameVisible,
15061506
isExpandoFunctionDeclaration,
1507-
isNonNarrowedBindableName,
15081507
getAllAccessorDeclarations: getAllAccessorDeclarationsForDeclaration,
15091508
requiresAddingImplicitUndefined,
15101509
isUndefinedIdentifierExpression(node: Identifier) {
@@ -49118,25 +49117,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
4911849117
}
4911949118
return false;
4912049119
}
49121-
function isNonNarrowedBindableName(node: ComputedPropertyName) {
49122-
if (!hasBindableName(node.parent)) {
49123-
return false;
49124-
}
49125-
49126-
const expression = node.expression;
49127-
if (!isEntityNameExpression(expression)) {
49128-
return true;
49129-
}
49130-
49131-
const type = getTypeOfExpression(expression);
49132-
const symbol = getSymbolAtLocation(expression);
49133-
if (!symbol) {
49134-
return false;
49135-
}
49136-
// Ensure not type narrowing
49137-
const declaredType = getTypeOfSymbol(symbol);
49138-
return declaredType === type;
49139-
}
4914049120

4914149121
function literalTypeToNode(type: FreshableType, enclosing: Node, tracker: SymbolTracker): Expression {
4914249122
const enumResult = type.flags & TypeFlags.EnumLike ? nodeBuilder.symbolToExpression(type.symbol, SymbolFlags.Value, enclosing, /*flags*/ undefined, tracker)
@@ -49262,7 +49242,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
4926249242
return node && getExternalModuleFileFromDeclaration(node);
4926349243
},
4926449244
isLiteralConstDeclaration,
49265-
isNonNarrowedBindableName,
4926649245
isLateBound: (nodeIn: Declaration): nodeIn is LateBoundDeclaration => {
4926749246
const node = getParseTreeNode(nodeIn, isDeclaration);
4926849247
const symbol = node && getSymbolOfDeclaration(node);

src/compiler/diagnosticMessages.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7014,6 +7014,10 @@
70147014
"category": "Error",
70157015
"code": 9037
70167016
},
7017+
"Computed property names on class or object literals cannot be inferred with --isolatedDeclarations.": {
7018+
"category": "Error",
7019+
"code": 9038
7020+
},
70177021
"JSX attributes must only be assigned a non-empty 'expression'.": {
70187022
"category": "Error",
70197023
"code": 17000

src/compiler/emitter.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1123,7 +1123,6 @@ export const notImplementedResolver: EmitResolver = {
11231123
isArgumentsLocalBinding: notImplemented,
11241124
getExternalModuleFileFromDeclaration: notImplemented,
11251125
isLiteralConstDeclaration: notImplemented,
1126-
isNonNarrowedBindableName: notImplemented,
11271126
getJsxFactoryEntity: notImplemented,
11281127
getJsxFragmentFactoryEntity: notImplemented,
11291128
isBindingCapturedByNode: notImplemented,

src/compiler/expressionToTypeNode.ts

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ import {
2626
isBlock,
2727
isConstTypeReference,
2828
isDeclarationReadonly,
29-
isEntityNameExpression,
3029
isGetAccessor,
3130
isIdentifier,
3231
isJSDocTypeAssertion,
@@ -55,7 +54,6 @@ import {
5554
PropertySignature,
5655
SetAccessorDeclaration,
5756
SignatureDeclaration,
58-
SymbolAccessibility,
5957
SyntacticTypeNodeBuilderContext,
6058
SyntacticTypeNodeBuilderResolver,
6159
SyntaxKind,
@@ -351,7 +349,7 @@ export function createSyntacticTypeNodeBuilder(options: CompilerOptions, resolve
351349
}
352350
else if (prop.name.kind === SyntaxKind.ComputedPropertyName) {
353351
const expression = prop.name.expression;
354-
if (!isPrimitiveLiteralValue(expression, /*includeBigInt*/ false) && !isEntityNameExpression(expression)) {
352+
if (!isPrimitiveLiteralValue(expression, /*includeBigInt*/ false)) {
355353
context.tracker.reportInferenceFallback(prop.name);
356354
result = false;
357355
}
@@ -367,17 +365,6 @@ export function createSyntacticTypeNodeBuilder(options: CompilerOptions, resolve
367365
Debug.assert(!isShorthandPropertyAssignment(prop) && !isSpreadAssignment(prop));
368366

369367
const name = prop.name;
370-
if (prop.name.kind === SyntaxKind.ComputedPropertyName) {
371-
if (!resolver.isNonNarrowedBindableName(prop.name)) {
372-
context.tracker.reportInferenceFallback(prop.name);
373-
}
374-
else if (isEntityNameExpression(prop.name.expression)) {
375-
const visibilityResult = resolver.isEntityNameVisible(prop.name.expression, context.enclosingDeclaration!, /*shouldComputeAliasToMakeVisible*/ false);
376-
if (visibilityResult.accessibility !== SymbolAccessibility.Accessible) {
377-
context.tracker.reportInferenceFallback(prop.name);
378-
}
379-
}
380-
}
381368
switch (prop.kind) {
382369
case SyntaxKind.MethodDeclaration:
383370
canInferObjectLiteral = !!typeFromObjectLiteralMethod(prop, name, context) && canInferObjectLiteral;

src/compiler/transformers/declarations.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ import {
139139
isTupleTypeNode,
140140
isTypeAliasDeclaration,
141141
isTypeElement,
142+
isTypeLiteralNode,
142143
isTypeNode,
143144
isTypeParameterDeclaration,
144145
isTypeQueryNode,
@@ -995,16 +996,20 @@ export function transformDeclarations(context: TransformationContext) {
995996
if (shouldStripInternal(input)) return;
996997
if (isDeclaration(input)) {
997998
if (isDeclarationAndNotVisible(input)) return;
998-
if (hasDynamicName(input) && !resolver.isLateBound(getParseTreeNode(input) as Declaration)) {
999+
if (hasDynamicName(input)) {
9991000
if (
10001001
isolatedDeclarations
1001-
// Classes usually elide properties with computed names that are not of a literal type
1002+
// Classes and object literals usually elide properties with computed names that are not of a literal type
10021003
// In isolated declarations TSC needs to error on these as we don't know the type in a DTE.
1003-
&& isClassDeclaration(input.parent)
1004-
&& isEntityNameExpression(input.name.expression)
1005-
// If the symbol is not accessible we get another TS error no need to add to that
1006-
&& resolver.isEntityNameVisible(input.name.expression, input.parent).accessibility === SymbolAccessibility.Accessible
1007-
&& !resolver.isNonNarrowedBindableName(input.name)
1004+
&& (isClassDeclaration(input.parent) || isObjectLiteralExpression(input.parent))
1005+
) {
1006+
context.addDiagnostic(createDiagnosticForNode(input, Diagnostics.Computed_property_names_on_class_or_object_literals_cannot_be_inferred_with_isolatedDeclarations));
1007+
}
1008+
if (
1009+
isolatedDeclarations
1010+
// Type declarations just need to double-check that the input computed name is an entity name expression
1011+
&& (isInterfaceDeclaration(input.parent) || isTypeLiteralNode(input.parent))
1012+
&& !isEntityNameExpression(input.name.expression)
10081013
) {
10091014
context.addDiagnostic(createDiagnosticForNode(input, Diagnostics.Computed_properties_must_be_number_or_string_literals_variables_or_dotted_expressions_with_isolatedDeclarations));
10101015
}

src/compiler/transformers/declarations/diagnostics.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -623,7 +623,7 @@ export function createGetIsolatedDeclarationErrors(resolver: EmitResolver) {
623623
[SyntaxKind.VariableDeclaration]: Diagnostics.Variable_must_have_an_explicit_type_annotation_with_isolatedDeclarations,
624624
[SyntaxKind.PropertyDeclaration]: Diagnostics.Property_must_have_an_explicit_type_annotation_with_isolatedDeclarations,
625625
[SyntaxKind.PropertySignature]: Diagnostics.Property_must_have_an_explicit_type_annotation_with_isolatedDeclarations,
626-
[SyntaxKind.ComputedPropertyName]: Diagnostics.Computed_properties_must_be_number_or_string_literals_variables_or_dotted_expressions_with_isolatedDeclarations,
626+
[SyntaxKind.ComputedPropertyName]: Diagnostics.Computed_property_names_on_class_or_object_literals_cannot_be_inferred_with_isolatedDeclarations,
627627
[SyntaxKind.SpreadAssignment]: Diagnostics.Objects_that_contain_spread_assignments_can_t_be_inferred_with_isolatedDeclarations,
628628
[SyntaxKind.ShorthandPropertyAssignment]: Diagnostics.Objects_that_contain_shorthand_properties_can_t_be_inferred_with_isolatedDeclarations,
629629
[SyntaxKind.ArrayLiteralExpression]: Diagnostics.Only_const_arrays_can_be_inferred_with_isolatedDeclarations,

src/compiler/types.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5754,7 +5754,6 @@ export enum TypeReferenceSerializationKind {
57545754

57555755
/** @internal */
57565756
export interface EmitResolver {
5757-
isNonNarrowedBindableName(node: ComputedPropertyName): boolean;
57585757
hasGlobalName(name: string): boolean;
57595758
getReferencedExportContainer(node: Identifier, prefixLocals?: boolean): SourceFile | ModuleDeclaration | EnumDeclaration | undefined;
57605759
getReferencedImportDeclaration(node: Identifier): Declaration | undefined;
@@ -10291,7 +10290,6 @@ export interface SyntacticTypeNodeBuilderContext {
1029110290
/** @internal */
1029210291
export interface SyntacticTypeNodeBuilderResolver {
1029310292
isUndefinedIdentifierExpression(name: Identifier): boolean;
10294-
isNonNarrowedBindableName(name: ComputedPropertyName): boolean;
1029510293
isExpandoFunctionDeclaration(name: FunctionDeclaration | VariableDeclaration): boolean;
1029610294
getAllAccessorDeclarations(declaration: AccessorDeclaration): AllAccessorDeclarations;
1029710295
isEntityNameVisible(entityName: EntityNameOrEntityNameExpression, enclosingDeclaration: Node, shouldComputeAliasToMakeVisible?: boolean): SymbolVisibilityResult;

src/services/codefixes/fixMissingTypeAnnotationOnExports.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ const errorCodes = [
121121
Diagnostics.Property_must_have_an_explicit_type_annotation_with_isolatedDeclarations.code,
122122
Diagnostics.Expression_type_can_t_be_inferred_with_isolatedDeclarations.code,
123123
Diagnostics.Binding_elements_can_t_be_exported_directly_with_isolatedDeclarations.code,
124+
Diagnostics.Computed_property_names_on_class_or_object_literals_cannot_be_inferred_with_isolatedDeclarations.code,
124125
Diagnostics.Computed_properties_must_be_number_or_string_literals_variables_or_dotted_expressions_with_isolatedDeclarations.code,
125126
Diagnostics.Enum_member_initializers_must_be_computable_without_references_to_external_symbols_with_isolatedDeclarations.code,
126127
Diagnostics.Extends_clause_can_t_contain_an_expression_with_isolatedDeclarations.code,
Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,32 @@
1-
computedPropertiesNarrowed.ts(5,5): error TS9014: Computed properties must be number or string literals, variables or dotted expressions with --isolatedDeclarations.
2-
computedPropertiesNarrowed.ts(18,20): error TS9014: Computed properties must be number or string literals, variables or dotted expressions with --isolatedDeclarations.
3-
computedPropertiesNarrowed.ts(22,5): error TS9014: Computed properties must be number or string literals, variables or dotted expressions with --isolatedDeclarations.
4-
computedPropertiesNarrowed.ts(26,5): error TS9014: Computed properties must be number or string literals, variables or dotted expressions with --isolatedDeclarations.
5-
computedPropertiesNarrowed.ts(37,5): error TS9014: Computed properties must be number or string literals, variables or dotted expressions with --isolatedDeclarations.
6-
computedPropertiesNarrowed.ts(47,5): error TS9014: Computed properties must be number or string literals, variables or dotted expressions with --isolatedDeclarations.
1+
computedPropertiesNarrowed.ts(5,5): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations.
2+
computedPropertiesNarrowed.ts(11,5): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations.
3+
computedPropertiesNarrowed.ts(18,20): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations.
4+
computedPropertiesNarrowed.ts(22,5): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations.
5+
computedPropertiesNarrowed.ts(26,5): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations.
6+
computedPropertiesNarrowed.ts(31,5): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations.
7+
computedPropertiesNarrowed.ts(37,5): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations.
8+
computedPropertiesNarrowed.ts(42,5): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations.
9+
computedPropertiesNarrowed.ts(47,5): error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations.
710

811

9-
==== computedPropertiesNarrowed.ts (6 errors) ====
12+
==== computedPropertiesNarrowed.ts (9 errors) ====
1013
const x: 0 | 1 = Math.random()? 0: 1;
1114
declare function assert(n: number): asserts n is 1;
1215
assert(x);
1316
export let o = {
1417
[x]: 1 // error narrow type !== declared type
1518
~~~
16-
!!! error TS9014: Computed properties must be number or string literals, variables or dotted expressions with --isolatedDeclarations.
19+
!!! error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations.
1720
!!! related TS9027 computedPropertiesNarrowed.ts:4:12: Add a type annotation to the variable o.
1821
}
1922

2023

2124
const y: 0 = 0
2225
export let o2 = {
2326
[y]: 1 // ok literal computed type
27+
~~~
28+
!!! error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations.
29+
!!! related TS9027 computedPropertiesNarrowed.ts:10:12: Add a type annotation to the variable o2.
2430
}
2531

2632
// literals are ok
@@ -29,48 +35,54 @@ computedPropertiesNarrowed.ts(47,5): error TS9014: Computed properties must be n
2935

3036
export let o32 = { [1-1]: 1 } // error number
3137
~~~~~
32-
!!! error TS9014: Computed properties must be number or string literals, variables or dotted expressions with --isolatedDeclarations.
38+
!!! error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations.
3339
!!! related TS9027 computedPropertiesNarrowed.ts:18:12: Add a type annotation to the variable o32.
3440

3541
let u = Symbol();
3642
export let o4 = {
3743
[u]: 1 // Should error, nut a unique symbol
3844
~~~
39-
!!! error TS9014: Computed properties must be number or string literals, variables or dotted expressions with --isolatedDeclarations.
45+
!!! error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations.
4046
!!! related TS9027 computedPropertiesNarrowed.ts:21:12: Add a type annotation to the variable o4.
4147
}
4248

4349
export let o5 ={
4450
[Symbol()]: 1 // Should error
4551
~~~~~~~~~~
46-
!!! error TS9014: Computed properties must be number or string literals, variables or dotted expressions with --isolatedDeclarations.
52+
!!! error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations.
4753
!!! related TS9027 computedPropertiesNarrowed.ts:25:12: Add a type annotation to the variable o5.
4854
}
4955

5056
const uu: unique symbol = Symbol();
5157
export let o6 = {
5258
[uu]: 1 // Should be ok
59+
~~~~
60+
!!! error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations.
61+
!!! related TS9027 computedPropertiesNarrowed.ts:30:12: Add a type annotation to the variable o6.
5362
}
5463

5564

5665
function foo (): 1 { return 1; }
5766
export let o7 = {
5867
[foo()]: 1 // Should error
5968
~~~~~~~
60-
!!! error TS9014: Computed properties must be number or string literals, variables or dotted expressions with --isolatedDeclarations.
69+
!!! error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations.
6170
!!! related TS9027 computedPropertiesNarrowed.ts:36:12: Add a type annotation to the variable o7.
6271
};
6372

6473
let E = { A: 1 } as const
6574
export const o8 = {
6675
[E.A]: 1 // Fresh
76+
~~~~~
77+
!!! error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations.
78+
!!! related TS9027 computedPropertiesNarrowed.ts:41:14: Add a type annotation to the variable o8.
6779
}
6880

6981
function ns() { return { v: 0 } as const }
7082
export const o9 = {
7183
[ns().v]: 1
7284
~~~~~~~~
73-
!!! error TS9014: Computed properties must be number or string literals, variables or dotted expressions with --isolatedDeclarations.
85+
!!! error TS9038: Computed property names on class or object literals cannot be inferred with --isolatedDeclarations.
7486
!!! related TS9027 computedPropertiesNarrowed.ts:46:14: Add a type annotation to the variable o9.
7587
}
7688

0 commit comments

Comments
 (0)