Skip to content

Commit 432ad50

Browse files
committed
feat(25259): add better error to report for equals instead of colon in object literals
1 parent 1d1c167 commit 432ad50

12 files changed

+127
-19
lines changed

src/compiler/checker.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -23337,7 +23337,8 @@ namespace ts {
2333723337
memberDecl.kind === SyntaxKind.ShorthandPropertyAssignment ||
2333823338
isObjectLiteralMethod(memberDecl)) {
2333923339
let type = memberDecl.kind === SyntaxKind.PropertyAssignment ? checkPropertyAssignment(memberDecl, checkMode) :
23340-
memberDecl.kind === SyntaxKind.ShorthandPropertyAssignment ? checkExpressionForMutableLocation(memberDecl.name, checkMode) :
23340+
// avoid resolving the left side of the ShorthandPropertyAssignment outside of the destructuring
23341+
memberDecl.kind === SyntaxKind.ShorthandPropertyAssignment ? checkExpressionForMutableLocation(!inDestructuringPattern && memberDecl.objectAssignmentInitializer ? memberDecl.objectAssignmentInitializer : memberDecl.name, checkMode) :
2334123342
checkObjectLiteralMethod(memberDecl, checkMode);
2334223343
if (isInJavascript) {
2334323344
const jsDocType = getTypeForDeclarationFromJSDocComment(memberDecl);
@@ -37559,7 +37560,7 @@ namespace ts {
3755937560
if (prop.kind === SyntaxKind.ShorthandPropertyAssignment && !inDestructuring && prop.objectAssignmentInitializer) {
3756037561
// having objectAssignmentInitializer is only valid in ObjectAssignmentPattern
3756137562
// outside of destructuring it is a syntax error
37562-
return grammarErrorOnNode(prop.equalsToken!, Diagnostics.can_only_be_used_in_an_object_literal_property_inside_a_destructuring_assignment);
37563+
return grammarErrorOnNode(prop.equalsToken!, Diagnostics.can_only_be_used_in_an_object_literal_property_inside_a_destructuring_assignment_Did_you_mean_to_use_a_Colon);
3756337564
}
3756437565

3756537566
if (name.kind === SyntaxKind.PrivateIdentifier) {

src/compiler/diagnosticMessages.json

+5-1
Original file line numberDiff line numberDiff line change
@@ -875,7 +875,7 @@
875875
"category": "Error",
876876
"code": 1308
877877
},
878-
"'=' can only be used in an object literal property inside a destructuring assignment.": {
878+
"'=' can only be used in an object literal property inside a destructuring assignment. Did you mean to use a ':'?": {
879879
"category": "Error",
880880
"code": 1312
881881
},
@@ -5733,6 +5733,10 @@
57335733
"category": "Message",
57345734
"code": 95125
57355735
},
5736+
"Switch each misplaced '{0}' to '{1}'": {
5737+
"category": "Message",
5738+
"code": 95126
5739+
},
57365740

57375741
"No value exists in scope for the shorthand property '{0}'. Either declare one or provide an initializer.": {
57385742
"category": "Error",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/* @internal */
2+
namespace ts.codefix {
3+
const fixId = "fixPropertyAssignment";
4+
const errorCodes = [
5+
Diagnostics.can_only_be_used_in_an_object_literal_property_inside_a_destructuring_assignment_Did_you_mean_to_use_a_Colon.code
6+
];
7+
8+
registerCodeFix({
9+
errorCodes,
10+
fixIds: [fixId],
11+
getCodeActions(context) {
12+
const { sourceFile, span } = context;
13+
const property = getProperty(sourceFile, span.start);
14+
const changes = textChanges.ChangeTracker.with(context, t => doChange(t, context.sourceFile, property));
15+
return [createCodeFixAction(fixId, changes, [Diagnostics.Change_0_to_1, "=", ":"], fixId, [Diagnostics.Switch_each_misplaced_0_to_1, "=", ":"])];
16+
},
17+
getAllCodeActions: context =>
18+
codeFixAll(context, errorCodes, (changes, diag) => doChange(changes, diag.file, getProperty(diag.file, diag.start)))
19+
});
20+
21+
function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, node: ShorthandPropertyAssignment): void {
22+
changes.replaceNode(sourceFile, node, createPropertyAssignment(node.name, node.objectAssignmentInitializer as Expression));
23+
}
24+
25+
function getProperty(sourceFile: SourceFile, pos: number): ShorthandPropertyAssignment {
26+
return cast(getTokenAtPosition(sourceFile, pos).parent, isShorthandPropertyAssignment);
27+
}
28+
}

src/services/tsconfig.json

+1
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676
"codefixes/fixEnableExperimentalDecorators.ts",
7777
"codefixes/fixEnableJsxFlag.ts",
7878
"codefixes/fixModuleAndTargetOptions.ts",
79+
"codefixes/fixPropertyAssignment.ts",
7980
"codefixes/fixExtendsInterfaceBecomesImplements.ts",
8081
"codefixes/fixForgottenThisPropertyAccess.ts",
8182
"codefixes/fixInvalidJsxCharacters.ts",

tests/baselines/reference/shorthandPropertyAssignmentsInDestructuring.errors.txt

+3-6
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,10 @@ tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring.ts(85,19): erro
1111
Types of property 'x' are incompatible.
1212
Type 'number' is not assignable to type 'string'.
1313
tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring.ts(85,26): error TS2322: Type 'number' is not assignable to type 'string'.
14-
tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring.ts(111,12): error TS18004: No value exists in scope for the shorthand property 's'. Either declare one or provide an initializer.
15-
tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring.ts(111,14): error TS1312: '=' can only be used in an object literal property inside a destructuring assignment.
14+
tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring.ts(111,14): error TS1312: '=' can only be used in an object literal property inside a destructuring assignment. Did you mean to use a ':'?
1615

1716

18-
==== tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring.ts (13 errors) ====
17+
==== tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring.ts (12 errors) ====
1918
(function() {
2019
var s0;
2120
for ({ s0 = 5 } of [{ s0: 1 }]) {
@@ -153,10 +152,8 @@ tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring.ts(111,14): err
153152

154153
(function() {
155154
let a = { s = 5 };
156-
~
157-
!!! error TS18004: No value exists in scope for the shorthand property 's'. Either declare one or provide an initializer.
158155
~
159-
!!! error TS1312: '=' can only be used in an object literal property inside a destructuring assignment.
156+
!!! error TS1312: '=' can only be used in an object literal property inside a destructuring assignment. Did you mean to use a ':'?
160157
});
161158

162159
function foo({a = 4, b = { x: 5 }}) {

tests/baselines/reference/shorthandPropertyAssignmentsInDestructuring.types

+2-2
Original file line numberDiff line numberDiff line change
@@ -417,8 +417,8 @@
417417
>function() { let a = { s = 5 };} : () => void
418418

419419
let a = { s = 5 };
420-
>a : { s: any; }
421-
>{ s = 5 } : { s: any; }
420+
>a : { s: number; }
421+
>{ s = 5 } : { s: number; }
422422
>s : any
423423
>5 : 5
424424

tests/baselines/reference/shorthandPropertyAssignmentsInDestructuring_ES6.errors.txt

+3-6
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,10 @@ tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring_ES6.ts(85,19):
1111
Types of property 'x' are incompatible.
1212
Type 'number' is not assignable to type 'string'.
1313
tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring_ES6.ts(85,26): error TS2322: Type 'number' is not assignable to type 'string'.
14-
tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring_ES6.ts(111,12): error TS18004: No value exists in scope for the shorthand property 's'. Either declare one or provide an initializer.
15-
tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring_ES6.ts(111,14): error TS1312: '=' can only be used in an object literal property inside a destructuring assignment.
14+
tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring_ES6.ts(111,14): error TS1312: '=' can only be used in an object literal property inside a destructuring assignment. Did you mean to use a ':'?
1615

1716

18-
==== tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring_ES6.ts (13 errors) ====
17+
==== tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring_ES6.ts (12 errors) ====
1918
(function() {
2019
var s0;
2120
for ({ s0 = 5 } of [{ s0: 1 }]) {
@@ -153,10 +152,8 @@ tests/cases/compiler/shorthandPropertyAssignmentsInDestructuring_ES6.ts(111,14):
153152

154153
(function() {
155154
let a = { s = 5 };
156-
~
157-
!!! error TS18004: No value exists in scope for the shorthand property 's'. Either declare one or provide an initializer.
158155
~
159-
!!! error TS1312: '=' can only be used in an object literal property inside a destructuring assignment.
156+
!!! error TS1312: '=' can only be used in an object literal property inside a destructuring assignment. Did you mean to use a ':'?
160157
});
161158

162159
function foo({a = 4, b = { x: 5 }}) {

tests/baselines/reference/shorthandPropertyAssignmentsInDestructuring_ES6.types

+2-2
Original file line numberDiff line numberDiff line change
@@ -417,8 +417,8 @@
417417
>function() { let a = { s = 5 };} : () => void
418418

419419
let a = { s = 5 };
420-
>a : { s: any; }
421-
>{ s = 5 } : { s: any; }
420+
>a : { s: number; }
421+
>{ s = 5 } : { s: number; }
422422
>s : any
423423
>5 : 5
424424

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/// <reference path='fourslash.ts'/>
2+
3+
////const a = {
4+
//// x/**/= 1
5+
////}
6+
7+
verify.codeFix({
8+
description: [ts.Diagnostics.Change_0_to_1.message, "=", ":"],
9+
index: 0,
10+
newFileContent:
11+
`const a = {
12+
x: 1
13+
}`,
14+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/// <reference path='fourslash.ts'/>
2+
3+
////const a = {
4+
//// x /**/= 1
5+
////}
6+
7+
verify.codeFix({
8+
description: [ts.Diagnostics.Change_0_to_1.message, "=", ":"],
9+
index: 0,
10+
newFileContent:
11+
`const a = {
12+
x: 1
13+
}`,
14+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/// <reference path='fourslash.ts'/>
2+
3+
////const a = {
4+
//// x: 1,
5+
//// y /**/= 1,
6+
//// z: 1
7+
////}
8+
9+
verify.codeFix({
10+
description: [ts.Diagnostics.Change_0_to_1.message, "=", ":"],
11+
index: 0,
12+
newFileContent:
13+
`const a = {
14+
x: 1,
15+
y: 1,
16+
z: 1
17+
}`,
18+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/// <reference path='fourslash.ts'/>
2+
3+
////const a = {
4+
//// x: 1,
5+
//// y = 1,
6+
//// z: 1
7+
////}
8+
////const b = {
9+
//// x = 1,
10+
//// y: 1
11+
////}
12+
////const c = {
13+
//// x: 1,
14+
//// y = 1
15+
////}
16+
17+
verify.codeFixAll({
18+
fixAllDescription: "Switch each misplaced '=' to ':'",
19+
fixId: "fixPropertyAssignment",
20+
newFileContent:
21+
`const a = {
22+
x: 1,
23+
y: 1,
24+
z: 1
25+
}
26+
const b = {
27+
x: 1,
28+
y: 1
29+
}
30+
const c = {
31+
x: 1,
32+
y: 1
33+
}`
34+
});

0 commit comments

Comments
 (0)