Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 9244604

Browse filesBrowse files
Merge pull request microsoft#18811 from Microsoft/uncalledDecorator
Give a more helpful error message for certain decorators with too many arguments
2 parents c02865f + 7750a88 commit 9244604
Copy full SHA for 9244604

10 files changed

+876-4Lines changed: 876 additions & 4 deletions
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎src/compiler/checker.ts‎

Copy file name to clipboardExpand all lines: src/compiler/checker.ts
+18Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16548,6 +16548,12 @@ namespace ts {
1654816548
return resolveUntypedCall(node);
1654916549
}
1655016550

16551+
if (isPotentiallyUncalledDecorator(node, callSignatures)) {
16552+
const nodeStr = getTextOfNode(node.expression, /*includeTrivia*/ false);
16553+
error(node, Diagnostics._0_accepts_too_few_arguments_to_be_used_as_a_decorator_here_Did_you_mean_to_call_it_first_and_write_0, nodeStr);
16554+
return resolveErrorCall(node);
16555+
}
16556+
1655116557
const headMessage = getDiagnosticHeadMessageForDecoratorResolution(node);
1655216558
if (!callSignatures.length) {
1655316559
let errorInfo: DiagnosticMessageChain;
@@ -16560,6 +16566,18 @@ namespace ts {
1656016566
return resolveCall(node, callSignatures, candidatesOutArray, headMessage);
1656116567
}
1656216568

16569+
/**
16570+
* Sometimes, we have a decorator that could accept zero arguments,
16571+
* but is receiving too many arguments as part of the decorator invocation.
16572+
* In those cases, a user may have meant to *call* the expression before using it as a decorator.
16573+
*/
16574+
function isPotentiallyUncalledDecorator(decorator: Decorator, signatures: Signature[]) {
16575+
return signatures.length && every(signatures, signature =>
16576+
signature.minArgumentCount === 0 &&
16577+
!signature.hasRestParameter &&
16578+
signature.parameters.length < getEffectiveArgumentCount(decorator, /*args*/ undefined, signature));
16579+
}
16580+
1656316581
/**
1656416582
* This function is similar to getResolvedSignature but is exclusively for trying to resolve JSX stateless-function component.
1656516583
* The main reason we have to use this function instead of getResolvedSignature because, the caller of this function will already check the type of openingLikeElement's tagName
Collapse file

‎src/compiler/diagnosticMessages.json‎

Copy file name to clipboardExpand all lines: src/compiler/diagnosticMessages.json
+4Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -907,6 +907,10 @@
907907
"category": "Error",
908908
"code": 1328
909909
},
910+
"'{0}' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@{0}()'?": {
911+
"category": "Error",
912+
"code": 1329
913+
},
910914

911915
"Duplicate identifier '{0}'.": {
912916
"category": "Error",
Collapse file

‎src/compiler/emitter.ts‎

Copy file name to clipboard
100755100644
Expand all lines: src/compiler/emitter.ts
File mode changed.
Collapse file
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
tests/cases/conformance/decorators/class/method/decoratorOnClassMethod6.ts(4,5): error TS1241: Unable to resolve signature of method decorator when called as an expression.
1+
tests/cases/conformance/decorators/class/method/decoratorOnClassMethod6.ts(4,5): error TS1329: 'dec' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@dec()'?
22

33

44
==== tests/cases/conformance/decorators/class/method/decoratorOnClassMethod6.ts (1 errors) ====
@@ -7,5 +7,5 @@ tests/cases/conformance/decorators/class/method/decoratorOnClassMethod6.ts(4,5):
77
class C {
88
@dec ["method"]() {}
99
~~~~
10-
!!! error TS1241: Unable to resolve signature of method decorator when called as an expression.
10+
!!! error TS1329: 'dec' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@dec()'?
1111
}
Collapse file
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
tests/cases/conformance/decorators/class/property/decoratorOnClassProperty11.ts(4,5): error TS1240: Unable to resolve signature of property decorator when called as an expression.
1+
tests/cases/conformance/decorators/class/property/decoratorOnClassProperty11.ts(4,5): error TS1329: 'dec' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@dec()'?
22

33

44
==== tests/cases/conformance/decorators/class/property/decoratorOnClassProperty11.ts (1 errors) ====
@@ -7,5 +7,5 @@ tests/cases/conformance/decorators/class/property/decoratorOnClassProperty11.ts(
77
class C {
88
@dec prop;
99
~~~~
10-
!!! error TS1240: Unable to resolve signature of property decorator when called as an expression.
10+
!!! error TS1329: 'dec' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@dec()'?
1111
}
Collapse file
+174Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
tests/cases/compiler/potentiallyUncalledDecorators.ts(4,5): error TS1329: 'Input' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@Input()'?
2+
tests/cases/compiler/potentiallyUncalledDecorators.ts(35,1): error TS1329: 'noArgs' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@noArgs()'?
3+
tests/cases/compiler/potentiallyUncalledDecorators.ts(37,5): error TS1329: 'noArgs' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@noArgs()'?
4+
tests/cases/compiler/potentiallyUncalledDecorators.ts(38,5): error TS1329: 'noArgs' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@noArgs()'?
5+
tests/cases/compiler/potentiallyUncalledDecorators.ts(41,1): error TS1238: Unable to resolve signature of class decorator when called as an expression.
6+
Type 'OmniDecorator' is not assignable to type 'typeof B'.
7+
Type 'OmniDecorator' provides no match for the signature 'new (): B'.
8+
tests/cases/compiler/potentiallyUncalledDecorators.ts(43,5): error TS1236: The return type of a property decorator function must be either 'void' or 'any'.
9+
Unable to resolve signature of property decorator when called as an expression.
10+
tests/cases/compiler/potentiallyUncalledDecorators.ts(44,5): error TS1241: Unable to resolve signature of method decorator when called as an expression.
11+
Type 'OmniDecorator' has no properties in common with type 'TypedPropertyDescriptor<() => void>'.
12+
tests/cases/compiler/potentiallyUncalledDecorators.ts(47,1): error TS1238: Unable to resolve signature of class decorator when called as an expression.
13+
Type 'OmniDecorator' is not assignable to type 'typeof C'.
14+
Type 'OmniDecorator' provides no match for the signature 'new (): C'.
15+
tests/cases/compiler/potentiallyUncalledDecorators.ts(49,5): error TS1329: 'oneOptional' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@oneOptional()'?
16+
tests/cases/compiler/potentiallyUncalledDecorators.ts(50,5): error TS1329: 'oneOptional' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@oneOptional()'?
17+
tests/cases/compiler/potentiallyUncalledDecorators.ts(53,1): error TS1238: Unable to resolve signature of class decorator when called as an expression.
18+
Type 'OmniDecorator' is not assignable to type 'typeof D'.
19+
Type 'OmniDecorator' provides no match for the signature 'new (): D'.
20+
tests/cases/compiler/potentiallyUncalledDecorators.ts(55,5): error TS1236: The return type of a property decorator function must be either 'void' or 'any'.
21+
Unable to resolve signature of property decorator when called as an expression.
22+
tests/cases/compiler/potentiallyUncalledDecorators.ts(56,5): error TS1241: Unable to resolve signature of method decorator when called as an expression.
23+
Type 'OmniDecorator' has no properties in common with type 'TypedPropertyDescriptor<() => void>'.
24+
tests/cases/compiler/potentiallyUncalledDecorators.ts(59,1): error TS1238: Unable to resolve signature of class decorator when called as an expression.
25+
Type 'OmniDecorator' is not assignable to type 'typeof E'.
26+
Type 'OmniDecorator' provides no match for the signature 'new (): E'.
27+
tests/cases/compiler/potentiallyUncalledDecorators.ts(61,5): error TS1236: The return type of a property decorator function must be either 'void' or 'any'.
28+
Unable to resolve signature of property decorator when called as an expression.
29+
tests/cases/compiler/potentiallyUncalledDecorators.ts(62,5): error TS1241: Unable to resolve signature of method decorator when called as an expression.
30+
Type 'OmniDecorator' has no properties in common with type 'TypedPropertyDescriptor<() => void>'.
31+
tests/cases/compiler/potentiallyUncalledDecorators.ts(65,1): error TS1238: Unable to resolve signature of class decorator when called as an expression.
32+
Type 'OmniDecorator' is not assignable to type 'typeof F'.
33+
Type 'OmniDecorator' provides no match for the signature 'new (): F'.
34+
tests/cases/compiler/potentiallyUncalledDecorators.ts(67,5): error TS1236: The return type of a property decorator function must be either 'void' or 'any'.
35+
Unable to resolve signature of property decorator when called as an expression.
36+
tests/cases/compiler/potentiallyUncalledDecorators.ts(68,5): error TS1241: Unable to resolve signature of method decorator when called as an expression.
37+
Type 'OmniDecorator' has no properties in common with type 'TypedPropertyDescriptor<() => void>'.
38+
39+
40+
==== tests/cases/compiler/potentiallyUncalledDecorators.ts (19 errors) ====
41+
// Angular-style Input/Output API:
42+
declare function Input(bindingPropertyName?: string): any;
43+
class FooComponent {
44+
@Input foo: string;
45+
~~~~~~
46+
!!! error TS1329: 'Input' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@Input()'?
47+
}
48+
49+
// Glimmer-style tracked API:
50+
declare const tracked: PropertyDecorator & { (...watchedProperties: string[]): any; }
51+
52+
class Person {
53+
@tracked person; any;
54+
}
55+
56+
class MultiplyByTwo {
57+
args: any;
58+
@tracked('args')
59+
get multiplied() {
60+
return this.args.number * 2;
61+
}
62+
}
63+
64+
// Other fun stuff.
65+
66+
interface OmniDecorator extends MethodDecorator, ClassDecorator, PropertyDecorator {
67+
}
68+
69+
declare function noArgs(): OmniDecorator;
70+
declare function allRest(...args: any[]): OmniDecorator;
71+
declare function oneOptional(x?: any): OmniDecorator;
72+
declare function twoOptional(x?: any, y?: any): OmniDecorator;
73+
declare function threeOptional(x?: any, y?: any, z?: any): OmniDecorator;
74+
declare function oneOptionalWithRest(x?: any, ...args: any[]): OmniDecorator;
75+
declare const anyDec: any;
76+
77+
@noArgs
78+
~~~~~~~
79+
!!! error TS1329: 'noArgs' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@noArgs()'?
80+
class A {
81+
@noArgs foo: any;
82+
~~~~~~~
83+
!!! error TS1329: 'noArgs' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@noArgs()'?
84+
@noArgs bar() { }
85+
~~~~~~~
86+
!!! error TS1329: 'noArgs' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@noArgs()'?
87+
}
88+
89+
@allRest
90+
~~~~~~~~
91+
!!! error TS1238: Unable to resolve signature of class decorator when called as an expression.
92+
!!! error TS1238: Type 'OmniDecorator' is not assignable to type 'typeof B'.
93+
!!! error TS1238: Type 'OmniDecorator' provides no match for the signature 'new (): B'.
94+
class B {
95+
@allRest foo: any;
96+
~~~~~~~~
97+
!!! error TS1236: The return type of a property decorator function must be either 'void' or 'any'.
98+
!!! error TS1236: Unable to resolve signature of property decorator when called as an expression.
99+
@allRest bar() { }
100+
~~~~~~~~
101+
!!! error TS1241: Unable to resolve signature of method decorator when called as an expression.
102+
!!! error TS1241: Type 'OmniDecorator' has no properties in common with type 'TypedPropertyDescriptor<() => void>'.
103+
}
104+
105+
@oneOptional
106+
~~~~~~~~~~~~
107+
!!! error TS1238: Unable to resolve signature of class decorator when called as an expression.
108+
!!! error TS1238: Type 'OmniDecorator' is not assignable to type 'typeof C'.
109+
!!! error TS1238: Type 'OmniDecorator' provides no match for the signature 'new (): C'.
110+
class C {
111+
@oneOptional foo: any;
112+
~~~~~~~~~~~~
113+
!!! error TS1329: 'oneOptional' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@oneOptional()'?
114+
@oneOptional bar() { }
115+
~~~~~~~~~~~~
116+
!!! error TS1329: 'oneOptional' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@oneOptional()'?
117+
}
118+
119+
@twoOptional
120+
~~~~~~~~~~~~
121+
!!! error TS1238: Unable to resolve signature of class decorator when called as an expression.
122+
!!! error TS1238: Type 'OmniDecorator' is not assignable to type 'typeof D'.
123+
!!! error TS1238: Type 'OmniDecorator' provides no match for the signature 'new (): D'.
124+
class D {
125+
@twoOptional foo: any;
126+
~~~~~~~~~~~~
127+
!!! error TS1236: The return type of a property decorator function must be either 'void' or 'any'.
128+
!!! error TS1236: Unable to resolve signature of property decorator when called as an expression.
129+
@twoOptional bar() { }
130+
~~~~~~~~~~~~
131+
!!! error TS1241: Unable to resolve signature of method decorator when called as an expression.
132+
!!! error TS1241: Type 'OmniDecorator' has no properties in common with type 'TypedPropertyDescriptor<() => void>'.
133+
}
134+
135+
@threeOptional
136+
~~~~~~~~~~~~~~
137+
!!! error TS1238: Unable to resolve signature of class decorator when called as an expression.
138+
!!! error TS1238: Type 'OmniDecorator' is not assignable to type 'typeof E'.
139+
!!! error TS1238: Type 'OmniDecorator' provides no match for the signature 'new (): E'.
140+
class E {
141+
@threeOptional foo: any;
142+
~~~~~~~~~~~~~~
143+
!!! error TS1236: The return type of a property decorator function must be either 'void' or 'any'.
144+
!!! error TS1236: Unable to resolve signature of property decorator when called as an expression.
145+
@threeOptional bar() { }
146+
~~~~~~~~~~~~~~
147+
!!! error TS1241: Unable to resolve signature of method decorator when called as an expression.
148+
!!! error TS1241: Type 'OmniDecorator' has no properties in common with type 'TypedPropertyDescriptor<() => void>'.
149+
}
150+
151+
@oneOptionalWithRest
152+
~~~~~~~~~~~~~~~~~~~~
153+
!!! error TS1238: Unable to resolve signature of class decorator when called as an expression.
154+
!!! error TS1238: Type 'OmniDecorator' is not assignable to type 'typeof F'.
155+
!!! error TS1238: Type 'OmniDecorator' provides no match for the signature 'new (): F'.
156+
class F {
157+
@oneOptionalWithRest foo: any;
158+
~~~~~~~~~~~~~~~~~~~~
159+
!!! error TS1236: The return type of a property decorator function must be either 'void' or 'any'.
160+
!!! error TS1236: Unable to resolve signature of property decorator when called as an expression.
161+
@oneOptionalWithRest bar() { }
162+
~~~~~~~~~~~~~~~~~~~~
163+
!!! error TS1241: Unable to resolve signature of method decorator when called as an expression.
164+
!!! error TS1241: Type 'OmniDecorator' has no properties in common with type 'TypedPropertyDescriptor<() => void>'.
165+
}
166+
167+
@anyDec
168+
class G {
169+
@anyDec foo: any;
170+
@anyDec bar() { }
171+
}
172+
173+
export { };
174+

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.