From a91cdccfc509e0878a8b8993e10aaa3a65246673 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 25 Mar 2016 16:37:28 -0700 Subject: [PATCH] Add --noImplicitThis flag It's basically another --noImplicitAny error, but one that would break large amount of JavaScript-style code. --- src/compiler/checker.ts | 4 ++ src/compiler/commandLineParser.ts | 4 ++ src/compiler/diagnosticMessages.json | 6 ++- src/compiler/types.ts | 1 + .../noImplicitThisFunctions.errors.txt | 25 +++++++++++++ .../reference/noImplicitThisFunctions.js | 37 +++++++++++++++++++ .../cases/compiler/noImplicitThisFunctions.ts | 19 ++++++++++ 7 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/noImplicitThisFunctions.errors.txt create mode 100644 tests/baselines/reference/noImplicitThisFunctions.js create mode 100644 tests/cases/compiler/noImplicitThisFunctions.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 51fad3e7f33..0f9287f9c52 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7707,6 +7707,10 @@ namespace ts { } } + if (compilerOptions.noImplicitThis && isFunctionLike(container)) { + // With noImplicitThis, functions may not reference 'this' if it has type 'any' + error(node, Diagnostics.this_implicitly_has_type_any_because_it_does_not_have_a_type_annotation); + } return anyType; } diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index cf55f030c33..363a3fdfc8f 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -125,6 +125,10 @@ namespace ts { type: "boolean", description: Diagnostics.Raise_error_on_expressions_and_declarations_with_an_implied_any_type, }, + { + name: "noImplicitThis", + type: "boolean", + }, { name: "noLib", type: "boolean", diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 5ea860f00af..53d0bcc07b8 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1863,7 +1863,11 @@ "category": "Error", "code": 2680 }, - "Import declaration '{0}' is using private name '{1}'.": { + "'this' implicitly has type 'any' because it does not have a type annotation.": { + "category": "Error", + "code": 2681 + }, + "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", "code": 4000 }, diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 5965a39a79e..e4c376b7b25 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2395,6 +2395,7 @@ namespace ts { noEmitOnError?: boolean; noErrorTruncation?: boolean; noImplicitAny?: boolean; + noImplicitThis?: boolean; noLib?: boolean; noResolve?: boolean; out?: string; diff --git a/tests/baselines/reference/noImplicitThisFunctions.errors.txt b/tests/baselines/reference/noImplicitThisFunctions.errors.txt new file mode 100644 index 00000000000..b00949d5086 --- /dev/null +++ b/tests/baselines/reference/noImplicitThisFunctions.errors.txt @@ -0,0 +1,25 @@ +tests/cases/compiler/noImplicitThisFunctions.ts(14,12): error TS2681: 'this' implicitly has type 'any' because it does not have a type annotation. + + +==== tests/cases/compiler/noImplicitThisFunctions.ts (1 errors) ==== + + function f1(x) { + // implicit any is still allowed + return x + 1; + } + + function f2(y: number) { + // ok: no reference to this + return y + 1; + } + + function f3(z: number): number { + // error: this is implicitly any + return this.a + z; + ~~~~ +!!! error TS2681: 'this' implicitly has type 'any' because it does not have a type annotation. + } + + // ok, arrow functions don't even bind `this`, so `this` is just `window` + let f4: (b: number) => number = b => this.c + b; + \ No newline at end of file diff --git a/tests/baselines/reference/noImplicitThisFunctions.js b/tests/baselines/reference/noImplicitThisFunctions.js new file mode 100644 index 00000000000..e256df2d77f --- /dev/null +++ b/tests/baselines/reference/noImplicitThisFunctions.js @@ -0,0 +1,37 @@ +//// [noImplicitThisFunctions.ts] + +function f1(x) { + // implicit any is still allowed + return x + 1; +} + +function f2(y: number) { + // ok: no reference to this + return y + 1; +} + +function f3(z: number): number { + // error: this is implicitly any + return this.a + z; +} + +// ok, arrow functions don't even bind `this`, so `this` is just `window` +let f4: (b: number) => number = b => this.c + b; + + +//// [noImplicitThisFunctions.js] +var _this = this; +function f1(x) { + // implicit any is still allowed + return x + 1; +} +function f2(y) { + // ok: no reference to this + return y + 1; +} +function f3(z) { + // error: this is implicitly any + return this.a + z; +} +// ok, arrow functions don't even bind `this`, so `this` is just `window` +var f4 = function (b) { return _this.c + b; }; diff --git a/tests/cases/compiler/noImplicitThisFunctions.ts b/tests/cases/compiler/noImplicitThisFunctions.ts new file mode 100644 index 00000000000..1e0aa0c4da0 --- /dev/null +++ b/tests/cases/compiler/noImplicitThisFunctions.ts @@ -0,0 +1,19 @@ +// @noImplicitThis: true + +function f1(x) { + // implicit any is still allowed + return x + 1; +} + +function f2(y: number) { + // ok: no reference to this + return y + 1; +} + +function f3(z: number): number { + // error: this is implicitly any + return this.a + z; +} + +// ok, arrow functions don't even bind `this`, so `this` is just `window` +let f4: (b: number) => number = b => this.c + b;