Skip to content

Commit e4ed7f9

Browse files
committed
Address PR comments
1 parent 0113ad5 commit e4ed7f9

7 files changed

Lines changed: 76 additions & 40 deletions

File tree

src/compiler/checker.ts

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5379,11 +5379,8 @@ namespace ts {
53795379

53805380
function isContextSensitiveFunctionLikeDeclaration(node: FunctionLikeDeclaration) {
53815381
const areAllParametersUntyped = !forEach(node.parameters, p => p.type);
5382-
if (node.kind === SyntaxKind.ArrowFunction) {
5383-
return !node.typeParameters && node.parameters.length && areAllParametersUntyped;
5384-
}
5385-
const hasThisType = node.parameters.length && (<Identifier>node.parameters[0].name).text === "this" && node.parameters[0].type;
5386-
return !node.typeParameters && areAllParametersUntyped && !hasThisType;
5382+
const isNullaryArrow = node.kind === SyntaxKind.ArrowFunction && !node.parameters.length;
5383+
return !node.typeParameters && areAllParametersUntyped && !isNullaryArrow;
53875384
}
53885385

53895386
function getTypeWithoutSignatures(type: Type): Type {
@@ -8072,20 +8069,20 @@ namespace ts {
80728069
if (signature.thisType) {
80738070
return signature.thisType;
80748071
}
8072+
if (container.parent && container.parent.kind === SyntaxKind.ObjectLiteralExpression) {
8073+
// Note: this works because object literal methods are deferred,
8074+
// which means that the type of the containing object literal is already known.
8075+
const type = checkExpressionCached(<ObjectLiteralExpression>container.parent);
8076+
if (type) {
8077+
return type;
8078+
}
8079+
}
80758080
}
80768081
if (isClassLike(container.parent)) {
80778082
const symbol = getSymbolOfNode(container.parent);
80788083
const type = container.flags & NodeFlags.Static ? getTypeOfSymbol(symbol) : (<InterfaceType>getDeclaredTypeOfSymbol(symbol)).thisType;
80798084
return getNarrowedTypeOfReference(type, node);
80808085
}
8081-
if (container.parent && container.parent.kind === SyntaxKind.ObjectLiteralExpression) {
8082-
// Note: this works because object literal methods are deferred,
8083-
// which means that the type of the containing object literal is already known.
8084-
const type = checkExpressionCached(<ObjectLiteralExpression>container.parent);
8085-
if (type) {
8086-
return type;
8087-
}
8088-
}
80898086

80908087
if (isInJavaScriptFile(node)) {
80918088
const type = getTypeForThisExpressionFromJSDoc(container);
@@ -12401,9 +12398,12 @@ namespace ts {
1240112398
if (indexOf(func.parameters, node) !== 0) {
1240212399
error(node, Diagnostics.this_parameter_must_be_the_first_parameter);
1240312400
}
12404-
if (func.kind === SyntaxKind.Constructor) {
12401+
if (func.kind === SyntaxKind.Constructor || func.kind === SyntaxKind.ConstructSignature) {
1240512402
error(node, Diagnostics.A_constructor_cannot_have_a_this_parameter);
1240612403
}
12404+
if (func.kind === SyntaxKind.SetAccessor) {
12405+
error(node, Diagnostics.A_setter_cannot_have_a_this_parameter);
12406+
}
1240712407
}
1240812408

1240912409
// Only check rest parameter type if it's not a binding pattern. Since binding patterns are

src/compiler/commandLineParser.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ namespace ts {
125125
{
126126
name: "noImplicitThis",
127127
type: "boolean",
128+
description: Diagnostics.Raise_error_on_this_expressions_with_an_implied_any_type,
128129
},
129130
{
130131
name: "noLib",

src/compiler/diagnosticMessages.json

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1887,10 +1887,14 @@
18871887
"category": "Error",
18881888
"code": 2680
18891889
},
1890-
"'this' implicitly has type 'any' because it does not have a type annotation.": {
1890+
"A setter cannot have a 'this' parameter.": {
18911891
"category": "Error",
18921892
"code": 2681
18931893
},
1894+
"'this' implicitly has type 'any' because it does not have a type annotation.": {
1895+
"category": "Error",
1896+
"code": 2682
1897+
},
18941898
"Import declaration '{0}' is using private name '{1}'.": {
18951899
"category": "Error",
18961900
"code": 4000
@@ -2636,6 +2640,10 @@
26362640
"category": "Message",
26372641
"code": 6113
26382642
},
2643+
"Raise error on 'this' expressions with an implied 'any' type.": {
2644+
"category": "Message",
2645+
"code": 6114
2646+
},
26392647

26402648
"Variable '{0}' implicitly has an '{1}' type.": {
26412649
"category": "Error",

tests/baselines/reference/noImplicitThisFunctions.errors.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
tests/cases/compiler/noImplicitThisFunctions.ts(14,12): error TS2681: 'this' implicitly has type 'any' because it does not have a type annotation.
2-
tests/cases/compiler/noImplicitThisFunctions.ts(18,38): error TS2681: 'this' implicitly has type 'any' because it does not have a type annotation.
1+
tests/cases/compiler/noImplicitThisFunctions.ts(14,12): error TS2682: 'this' implicitly has type 'any' because it does not have a type annotation.
2+
tests/cases/compiler/noImplicitThisFunctions.ts(18,38): error TS2682: 'this' implicitly has type 'any' because it does not have a type annotation.
33

44

55
==== tests/cases/compiler/noImplicitThisFunctions.ts (2 errors) ====
@@ -18,11 +18,11 @@ tests/cases/compiler/noImplicitThisFunctions.ts(18,38): error TS2681: 'this' imp
1818
// error: this is implicitly any
1919
return this.a + z;
2020
~~~~
21-
!!! error TS2681: 'this' implicitly has type 'any' because it does not have a type annotation.
21+
!!! error TS2682: 'this' implicitly has type 'any' because it does not have a type annotation.
2222
}
2323

2424
// error: `this` is `window`, but is still of type `any`
2525
let f4: (b: number) => number = b => this.c + b;
2626
~~~~
27-
!!! error TS2681: 'this' implicitly has type 'any' because it does not have a type annotation.
27+
!!! error TS2682: 'this' implicitly has type 'any' because it does not have a type annotation.
2828

tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -75,29 +75,31 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(146,1): er
7575
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(148,1): error TS2322: Type '(this: Base2) => number' is not assignable to type '(this: Base1) => number'.
7676
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(154,16): error TS2678: A function that is called with the 'new' keyword cannot have a 'this' type that is void.
7777
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(158,17): error TS2680: A constructor cannot have a 'this' parameter.
78-
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(161,30): error TS2679: 'this' parameter must be the first parameter.
79-
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(164,26): error TS1003: Identifier expected.
80-
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(164,30): error TS1005: ',' expected.
81-
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(165,20): error TS2370: A rest parameter must be of an array type.
82-
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(165,23): error TS1003: Identifier expected.
83-
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(165,27): error TS1005: ',' expected.
84-
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(166,23): error TS1005: ',' expected.
85-
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(166,24): error TS1138: Parameter declaration expected.
86-
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(167,28): error TS1003: Identifier expected.
87-
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(167,32): error TS1005: ',' expected.
88-
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(168,30): error TS1005: ',' expected.
89-
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(168,32): error TS1138: Parameter declaration expected.
90-
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(168,39): error TS1005: ';' expected.
91-
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(168,40): error TS1128: Declaration or statement expected.
92-
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(168,42): error TS2304: Cannot find name 'number'.
93-
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(168,49): error TS1005: ';' expected.
94-
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(171,1): error TS7027: Unreachable code detected.
95-
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(171,29): error TS2304: Cannot find name 'm'.
96-
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(171,32): error TS1005: ';' expected.
97-
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(171,35): error TS2304: Cannot find name 'm'.
78+
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(160,11): error TS2681: A setter cannot have a 'this' parameter.
79+
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(164,9): error TS2680: A constructor cannot have a 'this' parameter.
80+
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(166,30): error TS2679: 'this' parameter must be the first parameter.
81+
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(169,26): error TS1003: Identifier expected.
82+
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(169,30): error TS1005: ',' expected.
83+
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(170,20): error TS2370: A rest parameter must be of an array type.
84+
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(170,23): error TS1003: Identifier expected.
85+
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(170,27): error TS1005: ',' expected.
86+
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(171,23): error TS1005: ',' expected.
87+
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(171,24): error TS1138: Parameter declaration expected.
88+
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(172,28): error TS1003: Identifier expected.
89+
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(172,32): error TS1005: ',' expected.
90+
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(173,30): error TS1005: ',' expected.
91+
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(173,32): error TS1138: Parameter declaration expected.
92+
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(173,39): error TS1005: ';' expected.
93+
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(173,40): error TS1128: Declaration or statement expected.
94+
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(173,42): error TS2304: Cannot find name 'number'.
95+
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(173,49): error TS1005: ';' expected.
96+
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(176,1): error TS7027: Unreachable code detected.
97+
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(176,29): error TS2304: Cannot find name 'm'.
98+
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(176,32): error TS1005: ';' expected.
99+
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(176,35): error TS2304: Cannot find name 'm'.
98100

99101

100-
==== tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts (63 errors) ====
102+
==== tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts (65 errors) ====
101103
class C {
102104
n: number;
103105
explicitThis(this: this, m: number): number {
@@ -377,6 +379,15 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(171,35): e
377379
~~~~~~~~~~~~~~~~~~~~~
378380
!!! error TS2680: A constructor cannot have a 'this' parameter.
379381
}
382+
set p(this: void) {
383+
~~~~~~~~~~
384+
!!! error TS2681: A setter cannot have a 'this' parameter.
385+
}
386+
}
387+
interface ThisConstructorInterface {
388+
new(this: ThisConstructor, n: number);
389+
~~~~~~~~~~~~~~~~~~~~~
390+
!!! error TS2680: A constructor cannot have a 'this' parameter.
380391
}
381392
function notFirst(a: number, this: C): number { return this.n; }
382393
~~~~~~~

tests/baselines/reference/thisTypeInFunctionsNegative.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,11 @@ let voidThis = new VoidThis();
158158
class ThisConstructor {
159159
constructor(this: ThisConstructor, private n: number) {
160160
}
161+
set p(this: void) {
162+
}
163+
}
164+
interface ThisConstructorInterface {
165+
new(this: ThisConstructor, n: number);
161166
}
162167
function notFirst(a: number, this: C): number { return this.n; }
163168

@@ -326,6 +331,12 @@ var ThisConstructor = (function () {
326331
function ThisConstructor(n) {
327332
this.n = n;
328333
}
334+
Object.defineProperty(ThisConstructor.prototype, "p", {
335+
set: function () {
336+
},
337+
enumerable: true,
338+
configurable: true
339+
});
329340
return ThisConstructor;
330341
}());
331342
function notFirst(a, this) { return this.n; }

tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,11 @@ let voidThis = new VoidThis();
157157
class ThisConstructor {
158158
constructor(this: ThisConstructor, private n: number) {
159159
}
160+
set p(this: void) {
161+
}
162+
}
163+
interface ThisConstructorInterface {
164+
new(this: ThisConstructor, n: number);
160165
}
161166
function notFirst(a: number, this: C): number { return this.n; }
162167

0 commit comments

Comments
 (0)