Improve error messages and always return any from newed functions

Previously, functions that specified a type for `this` would return that
type. Now they return `any`. This helps prevent unintentional use of this
feature when --noImplicitAny is turned on.

The type of `this` is still checked in the body of these functions.
This commit is contained in:
Nathan Shively-Sanders
2016-03-31 14:32:56 -07:00
parent 81f0d86634
commit 4197a30f0c
5 changed files with 53 additions and 49 deletions

View File

@@ -5480,7 +5480,7 @@ namespace ts {
|| compareTypes(target.thisType, source.thisType, reportErrors);
if (!related) {
if (reportErrors) {
errorReporter(Diagnostics.Types_of_parameters_0_and_1_are_incompatible, "this", "this");
errorReporter(Diagnostics.this_types_of_each_signature_are_incompatible);
}
return Ternary.False;
}
@@ -10223,7 +10223,7 @@ namespace ts {
const thisArgumentNode = getThisArgumentOfCall(node);
const thisArgumentType = thisArgumentNode ? checkExpression(thisArgumentNode) : voidType;
const errorNode = reportErrors ? (thisArgumentNode || node) : undefined;
const headMessage = Diagnostics.this_context_of_type_0_is_not_assignable_to_method_this_of_type_1;
const headMessage = Diagnostics.this_context_of_type_0_is_not_assignable_to_method_s_this_of_type_1;
if (!checkTypeRelatedTo(thisArgumentType, signature.thisType, relation, errorNode, headMessage)) {
return false;
}
@@ -10929,7 +10929,7 @@ namespace ts {
// If expressionType's apparent type is an object type with no construct signatures but
// one or more call signatures, the expression is processed as a function call. A compile-time
// error occurs if the result of the function call is not Void. The type of the result of the
// operation is the function's this type. It is an error to have a Void this type.
// operation is Any. It is an error to have a Void this type.
const callSignatures = getSignaturesOfType(expressionType, SignatureKind.Call);
if (callSignatures.length) {
const signature = resolveCall(node, callSignatures, candidatesOutArray);
@@ -11117,10 +11117,10 @@ namespace ts {
if (funcSymbol && funcSymbol.members && (funcSymbol.flags & SymbolFlags.Function)) {
return getInferredClassType(funcSymbol);
}
else if (compilerOptions.noImplicitAny && !signature.thisType) {
else if (compilerOptions.noImplicitAny) {
error(node, Diagnostics.new_expression_whose_target_lacks_a_construct_signature_implicitly_has_an_any_type);
}
return signature.thisType || anyType;
return anyType;
}
}

View File

@@ -1879,7 +1879,7 @@
"category": "Error",
"code": 2678
},
"A function that is called with the 'new' keyword cannot have a 'this' type that is void.": {
"A function that is called with the 'new' keyword cannot have a 'this' type that is 'void'.": {
"category": "Error",
"code": 2679
},
@@ -1899,10 +1899,14 @@
"category": "Error",
"code": 2683
},
"'this' context of type '{0}' is not assignable to method 'this' of type '{1}'.": {
"'this' context of type '{0}' is not assignable to method's 'this' of type '{1}'.": {
"category": "Error",
"code": 2684
},
"'this' types of each signature are incompatible.": {
"category": "Error",
"code": 2685
},
"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",
"code": 4000

View File

@@ -1,8 +1,8 @@
tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(21,1): error TS2322: Type '(this: C, m: number) => number' is not assignable to type '(this: void, m: number) => number'.
Types of parameters 'this' and 'this' are incompatible.
'this' types of each signature are incompatible.
Type 'void' is not assignable to type 'C'.
tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(33,28): error TS2339: Property 'length' does not exist on type 'number'.
tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(37,9): error TS2684: 'this' context of type 'void' is not assignable to method 'this' of type 'I'.
tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(37,9): error TS2684: 'this' context of type 'void' is not assignable to method's 'this' of type 'I'.
tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(46,20): error TS2339: Property 'length' does not exist on type 'number'.
@@ -30,7 +30,7 @@ tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(46,20): error
c.explicitVoid = c.explicitThis; // error, 'void' is missing everything
~~~~~~~~~~~~~~
!!! error TS2322: Type '(this: C, m: number) => number' is not assignable to type '(this: void, m: number) => number'.
!!! error TS2322: Types of parameters 'this' and 'this' are incompatible.
!!! error TS2322: 'this' types of each signature are incompatible.
!!! error TS2322: Type 'void' is not assignable to type 'C'.
let o = {
n: 101,
@@ -51,7 +51,7 @@ tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(46,20): error
let x = i.explicitThis;
let n = x(12); // callee:void doesn't match this:I
~~~~~
!!! error TS2684: 'this' context of type 'void' is not assignable to method 'this' of type 'I'.
!!! error TS2684: 'this' context of type 'void' is not assignable to method's 'this' of type 'I'.
let u: Unused;
let y = u.implicitNoThis;
n = y(12); // ok, callee:void matches this:any

View File

@@ -895,13 +895,13 @@ function AnyThis(this: any) {
>"ok" : string
}
let interfaceThis = new InterfaceThis();
>interfaceThis : I
>new InterfaceThis() : I
>interfaceThis : any
>new InterfaceThis() : any
>InterfaceThis : (this: I) => void
let literalTypeThis = new LiteralTypeThis();
>literalTypeThis : { x: string; }
>new LiteralTypeThis() : { x: string; }
>literalTypeThis : any
>new LiteralTypeThis() : any
>LiteralTypeThis : (this: { x: string; }) => void
let anyThis = new AnyThis();

View File

@@ -1,7 +1,7 @@
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(16,15): error TS2339: Property 'n' does not exist on type 'void'.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(39,21): error TS2339: Property 'a' does not exist on type 'void'.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(49,1): error TS2684: 'this' context of type 'void' is not assignable to method 'this' of type '{ a: number; }'.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(51,1): error TS2684: 'this' context of type 'void' is not assignable to method 'this' of type 'I'.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(49,1): error TS2684: 'this' context of type 'void' is not assignable to method's 'this' of type '{ a: number; }'.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(51,1): error TS2684: 'this' context of type 'void' is not assignable to method's 'this' of type 'I'.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(56,21): error TS2339: Property 'notFound' does not exist on type '{ y: number; }'.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(59,21): error TS2339: Property 'notSpecified' does not exist on type 'void'.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(61,79): error TS2322: Type '{ y: number; explicitStructural: (this: { y: number; }, x: number) => number; }' is not assignable to type '{ y: number; f: (this: { y: number; }, x: number) => number; }'.
@@ -13,10 +13,10 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(63,110): e
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(65,1): error TS2346: Supplied parameters do not match any signature of call target.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(66,6): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(67,1): error TS2346: Supplied parameters do not match any signature of call target.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(68,1): error TS2684: 'this' context of type '{ y: string; f: (this: { y: number; }, x: number) => number; }' is not assignable to method 'this' of type '{ y: number; }'.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(68,1): error TS2684: 'this' context of type '{ y: string; f: (this: { y: number; }, x: number) => number; }' is not assignable to method's 'this' of type '{ y: number; }'.
Types of property 'y' are incompatible.
Type 'string' is not assignable to type 'number'.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(69,1): error TS2684: 'this' context of type '{ wrongName: number; f: (this: { y: number; }, x: number) => number; }' is not assignable to method 'this' of type '{ y: number; }'.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(69,1): error TS2684: 'this' context of type '{ wrongName: number; f: (this: { y: number; }, x: number) => number; }' is not assignable to method's 'this' of type '{ y: number; }'.
Property 'y' is missing in type '{ wrongName: number; f: (this: { y: number; }, x: number) => number; }'.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(72,1): error TS2346: Supplied parameters do not match any signature of call target.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(73,13): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.
@@ -31,49 +31,49 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(81,1): err
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(82,20): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(83,1): error TS2346: Supplied parameters do not match any signature of call target.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(86,5): error TS2322: Type '(this: { y: number; }, x: number) => number' is not assignable to type '(this: void, x: number) => number'.
Types of parameters 'this' and 'this' are incompatible.
'this' types of each signature are incompatible.
Type 'void' is not assignable to type '{ y: number; }'.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(107,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'.
Types of parameters 'this' and 'this' are incompatible.
'this' types of each signature are incompatible.
Type 'C' is not assignable to type 'D'.
Property 'x' is missing in type 'C'.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(108,1): error TS2322: Type '(this: { x: number; }, m: number) => number' is not assignable to type '(this: { n: number; }, m: number) => number'.
Types of parameters 'this' and 'this' are incompatible.
'this' types of each signature are incompatible.
Type '{ n: number; }' is not assignable to type '{ x: number; }'.
Property 'x' is missing in type '{ n: number; }'.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(110,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'.
Types of parameters 'this' and 'this' are incompatible.
'this' types of each signature are incompatible.
Type 'C' is not assignable to type 'D'.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(111,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'.
Types of parameters 'this' and 'this' are incompatible.
'this' types of each signature are incompatible.
Type 'C' is not assignable to type 'D'.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(112,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'.
Types of parameters 'this' and 'this' are incompatible.
'this' types of each signature are incompatible.
Type 'C' is not assignable to type 'D'.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(113,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'.
Types of parameters 'this' and 'this' are incompatible.
'this' types of each signature are incompatible.
Type 'C' is not assignable to type 'D'.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(114,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: { n: number; }, m: number) => number'.
Types of parameters 'this' and 'this' are incompatible.
'this' types of each signature are incompatible.
Type '{ n: number; }' is not assignable to type 'D'.
Property 'x' is missing in type '{ n: number; }'.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(115,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(116,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: void, m: number) => number'.
Types of parameters 'this' and 'this' are incompatible.
'this' types of each signature are incompatible.
Type 'void' is not assignable to type 'D'.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(117,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: void, m: number) => number'.
Types of parameters 'this' and 'this' are incompatible.
'this' types of each signature are incompatible.
Type 'void' is not assignable to type 'D'.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(125,69): error TS2339: Property 'x' does not exist on type 'typeof Base1'.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(145,1): error TS2322: Type '(this: Base2) => number' is not assignable to type '(this: Base1) => number'.
Types of parameters 'this' and 'this' are incompatible.
'this' types of each signature are incompatible.
Type 'Base1' is not assignable to type 'Base2'.
Property 'y' is missing in type 'Base1'.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(146,1): error TS2322: Type '(this: Base2) => number' is not assignable to type '(this: Base1) => number'.
Types of parameters 'this' and 'this' are incompatible.
'this' types of each signature are incompatible.
Type 'Base1' is not assignable to type 'Base2'.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(148,1): error TS2322: Type '(this: Base2) => number' is not assignable to type '(this: Base1) => number'.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(154,16): error TS2679: A function that is called with the 'new' keyword cannot have a 'this' type that is void.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(154,16): error TS2679: A function that is called with the 'new' keyword cannot have a 'this' type that is 'void'.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(158,17): error TS2681: A constructor cannot have a 'this' parameter.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(160,11): error TS2682: A setter cannot have a 'this' parameter.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(164,9): error TS2681: A constructor cannot have a 'this' parameter.
@@ -154,11 +154,11 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(176,35): e
let implExplicitStructural = impl.explicitStructural;
implExplicitStructural(); // error, no 'a' in 'void'
~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2684: 'this' context of type 'void' is not assignable to method 'this' of type '{ a: number; }'.
!!! error TS2684: 'this' context of type 'void' is not assignable to method's 'this' of type '{ a: number; }'.
let implExplicitInterface = impl.explicitInterface;
implExplicitInterface(); // error, no 'a' in 'void'
~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2684: 'this' context of type 'void' is not assignable to method 'this' of type 'I'.
!!! error TS2684: 'this' context of type 'void' is not assignable to method's 'this' of type 'I'.
function explicitStructural(this: { y: number }, x: number): number {
return x + this.y;
}
@@ -196,12 +196,12 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(176,35): e
!!! error TS2346: Supplied parameters do not match any signature of call target.
wrongPropertyType.f(13);
~~~~~~~~~~~~~~~~~
!!! error TS2684: 'this' context of type '{ y: string; f: (this: { y: number; }, x: number) => number; }' is not assignable to method 'this' of type '{ y: number; }'.
!!! error TS2684: 'this' context of type '{ y: string; f: (this: { y: number; }, x: number) => number; }' is not assignable to method's 'this' of type '{ y: number; }'.
!!! error TS2684: Types of property 'y' are incompatible.
!!! error TS2684: Type 'string' is not assignable to type 'number'.
wrongPropertyName.f(13);
~~~~~~~~~~~~~~~~~
!!! error TS2684: 'this' context of type '{ wrongName: number; f: (this: { y: number; }, x: number) => number; }' is not assignable to method 'this' of type '{ y: number; }'.
!!! error TS2684: 'this' context of type '{ wrongName: number; f: (this: { y: number; }, x: number) => number; }' is not assignable to method's 'this' of type '{ y: number; }'.
!!! error TS2684: Property 'y' is missing in type '{ wrongName: number; f: (this: { y: number; }, x: number) => number; }'.
let c = new C();
@@ -246,7 +246,7 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(176,35): e
let specifiedToVoid: (this: void, x: number) => number = explicitStructural;
~~~~~~~~~~~~~~~
!!! error TS2322: Type '(this: { y: number; }, x: number) => number' is not assignable to type '(this: void, x: number) => number'.
!!! error TS2322: Types of parameters 'this' and 'this' are incompatible.
!!! error TS2322: 'this' types of each signature are incompatible.
!!! error TS2322: Type 'void' is not assignable to type '{ y: number; }'.
let reconstructed: {
@@ -271,40 +271,40 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(176,35): e
c.explicitC = function(this: D, m: number) { return this.x + m };
~~~~~~~~~~~
!!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'.
!!! error TS2322: Types of parameters 'this' and 'this' are incompatible.
!!! error TS2322: 'this' types of each signature are incompatible.
!!! error TS2322: Type 'C' is not assignable to type 'D'.
!!! error TS2322: Property 'x' is missing in type 'C'.
c.explicitProperty = explicitXProperty;
~~~~~~~~~~~~~~~~~~
!!! error TS2322: Type '(this: { x: number; }, m: number) => number' is not assignable to type '(this: { n: number; }, m: number) => number'.
!!! error TS2322: Types of parameters 'this' and 'this' are incompatible.
!!! error TS2322: 'this' types of each signature are incompatible.
!!! error TS2322: Type '{ n: number; }' is not assignable to type '{ x: number; }'.
!!! error TS2322: Property 'x' is missing in type '{ n: number; }'.
c.explicitC = d.explicitD;
~~~~~~~~~~~
!!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'.
!!! error TS2322: Types of parameters 'this' and 'this' are incompatible.
!!! error TS2322: 'this' types of each signature are incompatible.
!!! error TS2322: Type 'C' is not assignable to type 'D'.
c.explicitC = d.explicitThis;
~~~~~~~~~~~
!!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'.
!!! error TS2322: Types of parameters 'this' and 'this' are incompatible.
!!! error TS2322: 'this' types of each signature are incompatible.
!!! error TS2322: Type 'C' is not assignable to type 'D'.
c.explicitThis = d.explicitD;
~~~~~~~~~~~~~~
!!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'.
!!! error TS2322: Types of parameters 'this' and 'this' are incompatible.
!!! error TS2322: 'this' types of each signature are incompatible.
!!! error TS2322: Type 'C' is not assignable to type 'D'.
c.explicitThis = d.explicitThis;
~~~~~~~~~~~~~~
!!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'.
!!! error TS2322: Types of parameters 'this' and 'this' are incompatible.
!!! error TS2322: 'this' types of each signature are incompatible.
!!! error TS2322: Type 'C' is not assignable to type 'D'.
c.explicitProperty = d.explicitD;
~~~~~~~~~~~~~~~~~~
!!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: { n: number; }, m: number) => number'.
!!! error TS2322: Types of parameters 'this' and 'this' are incompatible.
!!! error TS2322: 'this' types of each signature are incompatible.
!!! error TS2322: Type '{ n: number; }' is not assignable to type 'D'.
!!! error TS2322: Property 'x' is missing in type '{ n: number; }'.
c.explicitThis = d.explicitThis;
@@ -313,12 +313,12 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(176,35): e
c.explicitVoid = d.explicitD;
~~~~~~~~~~~~~~
!!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: void, m: number) => number'.
!!! error TS2322: Types of parameters 'this' and 'this' are incompatible.
!!! error TS2322: 'this' types of each signature are incompatible.
!!! error TS2322: Type 'void' is not assignable to type 'D'.
c.explicitVoid = d.explicitThis;
~~~~~~~~~~~~~~
!!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: void, m: number) => number'.
!!! error TS2322: Types of parameters 'this' and 'this' are incompatible.
!!! error TS2322: 'this' types of each signature are incompatible.
!!! error TS2322: Type 'void' is not assignable to type 'D'.
/// class-based polymorphic assignability (with inheritance!) ///
@@ -352,13 +352,13 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(176,35): e
b1.polymorphic = b2.polymorphic // error, 'this.y' not in Base1: { x }
~~~~~~~~~~~~~~
!!! error TS2322: Type '(this: Base2) => number' is not assignable to type '(this: Base1) => number'.
!!! error TS2322: Types of parameters 'this' and 'this' are incompatible.
!!! error TS2322: 'this' types of each signature are incompatible.
!!! error TS2322: Type 'Base1' is not assignable to type 'Base2'.
!!! error TS2322: Property 'y' is missing in type 'Base1'.
b1.explicit = b2.polymorphic // error, 'y' not in Base1: { x }
~~~~~~~~~~~
!!! error TS2322: Type '(this: Base2) => number' is not assignable to type '(this: Base1) => number'.
!!! error TS2322: Types of parameters 'this' and 'this' are incompatible.
!!! error TS2322: 'this' types of each signature are incompatible.
!!! error TS2322: Type 'Base1' is not assignable to type 'Base2'.
d1.explicit = b2.polymorphic // error, 'y' not in Base1: { x }
@@ -371,7 +371,7 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(176,35): e
}
let voidThis = new VoidThis();
~~~~~~~~~~~~~~
!!! error TS2679: A function that is called with the 'new' keyword cannot have a 'this' type that is void.
!!! error TS2679: A function that is called with the 'new' keyword cannot have a 'this' type that is 'void'.
///// syntax-ish errors /////
class ThisConstructor {