First round of review comments addressed.

Only major thing is a bug fix in
`isContextSensitiveFunctionLikeDeclaration`, and turning on context
sensitivity to `this` even with `--strictThis` off.
This commit is contained in:
Nathan Shively-Sanders
2016-02-04 15:43:43 -08:00
parent 0af56c0ee2
commit 8c87da523b
13 changed files with 162 additions and 73 deletions

View File

@@ -131,8 +131,8 @@ namespace ts {
const noConstraintType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
const anySignature = createSignature(undefined, undefined, emptyArray, undefined, anyType, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false);
const unknownSignature = createSignature(undefined, undefined, emptyArray, undefined, unknownType, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false);
const anySignature = createSignature(undefined, undefined, undefined, emptyArray, anyType, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false);
const unknownSignature = createSignature(undefined, undefined, undefined, emptyArray, unknownType, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false);
const enumNumberIndexInfo = createIndexInfo(stringType, /*isReadonly*/ true);
@@ -3540,7 +3540,7 @@ namespace ts {
resolveObjectTypeMembers(type, source, typeParameters, typeArguments);
}
function createSignature(declaration: SignatureDeclaration, typeParameters: TypeParameter[], parameters: Symbol[], thisType: Type,
function createSignature(declaration: SignatureDeclaration, typeParameters: TypeParameter[], thisType: Type, parameters: Symbol[],
resolvedReturnType: Type, minArgumentCount: number, hasRestParameter: boolean, hasStringLiterals: boolean): Signature {
const sig = new Signature(checker);
sig.declaration = declaration;
@@ -3555,7 +3555,7 @@ namespace ts {
}
function cloneSignature(sig: Signature): Signature {
return createSignature(sig.declaration, sig.typeParameters, sig.parameters, sig.thisType, sig.resolvedReturnType,
return createSignature(sig.declaration, sig.typeParameters, sig.thisType, sig.parameters, sig.resolvedReturnType,
sig.minArgumentCount, sig.hasRestParameter, sig.hasStringLiterals);
}
@@ -3567,7 +3567,7 @@ namespace ts {
const baseConstructorType = getBaseConstructorTypeOfClass(classType);
const baseSignatures = getSignaturesOfType(baseConstructorType, SignatureKind.Construct);
if (baseSignatures.length === 0) {
return [createSignature(undefined, classType.localTypeParameters, emptyArray, undefined, classType, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false)];
return [createSignature(undefined, classType.localTypeParameters, undefined, emptyArray, classType, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false)];
}
const baseTypeNode = getBaseTypeNodeOfClass(classType);
const typeArguments = map(baseTypeNode.typeArguments, getTypeFromTypeNode);
@@ -4098,6 +4098,7 @@ namespace ts {
let hasStringLiterals = false;
let minArgumentCount = -1;
let thisType: Type = undefined;
let hasThisParameter: boolean;
const isJSConstructSignature = isJSDocConstructSignature(declaration);
let returnType: Type = undefined;
@@ -4113,11 +4114,9 @@ namespace ts {
const resolvedSymbol = resolveName(param, paramSymbol.name, SymbolFlags.Value, undefined, undefined);
paramSymbol = resolvedSymbol;
}
if (paramSymbol.name === "this") {
thisType = param.type && getTypeOfSymbol(paramSymbol);
if (i !== 0 || declaration.kind === SyntaxKind.Constructor) {
error(param, Diagnostics.this_cannot_be_referenced_in_current_location);
}
if (i == 0 && paramSymbol.name === "this") {
hasThisParameter = true;
thisType = param.type ? getTypeFromTypeNode(param.type) : unknownType;
}
else {
parameters.push(paramSymbol);
@@ -4129,7 +4128,7 @@ namespace ts {
if (param.initializer || param.questionToken || param.dotDotDotToken) {
if (minArgumentCount < 0) {
minArgumentCount = i - (thisType ? 1 : 0);
minArgumentCount = i - (hasThisParameter ? 1 : 0);
}
}
else {
@@ -4139,19 +4138,19 @@ namespace ts {
}
if (minArgumentCount < 0) {
minArgumentCount = declaration.parameters.length - (thisType ? 1 : 0);
minArgumentCount = declaration.parameters.length - (hasThisParameter ? 1 : 0);
}
if (!thisType && compilerOptions.strictThis) {
if (declaration.kind === SyntaxKind.FunctionDeclaration
|| declaration.kind === SyntaxKind.CallSignature
|| declaration.kind == SyntaxKind.FunctionExpression
|| declaration.kind === SyntaxKind.FunctionType) {
if (!hasThisParameter && compilerOptions.strictThis) {
if (declaration.kind === SyntaxKind.FunctionDeclaration ||
declaration.kind === SyntaxKind.CallSignature ||
declaration.kind == SyntaxKind.FunctionExpression ||
declaration.kind === SyntaxKind.FunctionType) {
thisType = voidType;
}
else if ((declaration.kind === SyntaxKind.MethodDeclaration || declaration.kind === SyntaxKind.MethodSignature)
&& (isClassLike(declaration.parent) || declaration.parent.kind === SyntaxKind.InterfaceDeclaration)) {
thisType = declaration.flags & NodeFlags.Static ?
getWidenedType(checkExpression((<ClassLikeDeclaration>declaration.parent).name)) :
getTypeOfSymbol(getSymbolOfNode(declaration.parent)) :
getThisType(declaration.name);
Debug.assert(!!thisType, "couldn't find implicit this type");
}
@@ -4187,7 +4186,7 @@ namespace ts {
}
}
links.resolvedSignature = createSignature(declaration, typeParameters, parameters, thisType, returnType, minArgumentCount, hasRestParameter(declaration), hasStringLiterals);
links.resolvedSignature = createSignature(declaration, typeParameters, thisType, parameters, returnType, minArgumentCount, hasRestParameter(declaration), hasStringLiterals);
}
return links.resolvedSignature;
}
@@ -5105,8 +5104,8 @@ namespace ts {
}
}
const result = createSignature(signature.declaration, freshTypeParameters,
signature.thisType && instantiateType(signature.thisType, mapper),
instantiateList(signature.parameters, mapper, instantiateSymbol),
signature.thisType ? instantiateType(signature.thisType, mapper) : undefined,
instantiateType(signature.resolvedReturnType, mapper),
signature.minArgumentCount, signature.hasRestParameter, signature.hasStringLiterals);
result.target = signature;
@@ -5220,14 +5219,12 @@ namespace ts {
}
function isContextSensitiveFunctionLikeDeclaration(node: FunctionLikeDeclaration) {
if (compilerOptions.strictThis) {
return !node.typeParameters &&
(!forEach(node.parameters, p => p.type)
|| (node.kind !== SyntaxKind.ArrowFunction && (!node.parameters.length || (<Identifier>node.parameters[0].name).text !== "this")));
}
else {
return !node.typeParameters && node.parameters.length && !forEach(node.parameters, p => p.type);
const areAllParametersUntyped = !forEach(node.parameters, p => p.type);
if (node.kind === SyntaxKind.ArrowFunction) {
return !node.typeParameters && node.parameters.length && areAllParametersUntyped;
}
const hasThisType = node.parameters.length && (<Identifier>node.parameters[0].name).text === "this" && node.parameters[0].type;
return !node.typeParameters && areAllParametersUntyped && !hasThisType;
}
function getTypeWithoutSignatures(type: Type): Type {
@@ -5305,13 +5302,13 @@ namespace ts {
let result = Ternary.True;
if (source.thisType || target.thisType) {
const s = source.thisType || anyType;
const t = target.thisType || anyType;
if (s !== voidType) {
if (source.thisType !== voidType) {
const s = source.thisType ? getApparentType(source.thisType) : anyType;
const t = target.thisType ? getApparentType(target.thisType) : anyType;
// void sources are assignable to anything.
let related = compareTypes(getApparentType(t), getApparentType(s), reportErrors);
let related = compareTypes(t, s, reportErrors);
if (!related) {
related = compareTypes(getApparentType(s), getApparentType(t), /*reportErrors*/ false);
related = compareTypes(s, t, /*reportErrors*/ false);
if (!related) {
errorReporter(Diagnostics.Types_of_parameters_0_and_1_are_incompatible, "this", "this");
return Ternary.False;
@@ -11626,6 +11623,11 @@ namespace ts {
if (node.questionToken && isBindingPattern(node.name) && func.body) {
error(node, Diagnostics.A_binding_pattern_parameter_cannot_be_optional_in_an_implementation_signature);
}
if ((<Identifier>node.name).text === "this") {
if(indexOf(func.parameters, node) !== 0 || func.kind === SyntaxKind.Constructor) {
error(node, Diagnostics.this_cannot_be_referenced_in_current_location);
}
}
// Only check rest parameter type if it's not a binding pattern. Since binding patterns are
// not allowed in a rest parameter, we already have an error from checkGrammarParameterList.

View File

@@ -4,7 +4,7 @@ tests/cases/compiler/contextualTyping24.ts(1,55): error TS2322: Type '(a: string
==== tests/cases/compiler/contextualTyping24.ts (1 errors) ====
var foo:(a:{():number; (i:number):number; })=>number; foo = function(a:string){return 5};
var foo:(a:{():number; (i:number):number; })=>number; foo = function(this: void, a:string){return 5};
~~~
!!! error TS2322: Type '(a: string) => number' is not assignable to type '(a: { (): number; (i: number): number; }) => number'.
!!! error TS2322: Types of parameters 'a' and 'a' are incompatible.

View File

@@ -1,5 +1,5 @@
//// [contextualTyping24.ts]
var foo:(a:{():number; (i:number):number; })=>number; foo = function(a:string){return 5};
var foo:(a:{():number; (i:number):number; })=>number; foo = function(this: void, a:string){return 5};
//// [contextualTyping24.js]
var foo;

View File

@@ -1,11 +1,15 @@
tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(20,1): error TS2322: Type '(this: C, m: number) => number' is not assignable to type '(m: number) => number'.
tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(21,1): error TS2322: Type '(this: C, m: number) => number' is not assignable to type '(m: number) => number'.
Types of parameters 'this' and 'this' are incompatible.
Type 'void' is not assignable to type 'C'.
tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(27,9): error TS2345: Argument of type 'void' is not assignable to parameter of type 'I'.
tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(32,5): error TS1005: ',' expected.
tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(33,27): error TS2339: Property 'length' does not exist on type 'number'.
tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(37,9): error TS2345: Argument of type 'void' is not assignable to parameter of type 'I'.
tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(46,19): error TS2339: Property 'length' does not exist on type 'number'.
==== tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts (2 errors) ====
==== tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts (5 errors) ====
interface I {
n: number;
explicitThis(this: this, m: number): number;
}
interface Unused {
@@ -30,10 +34,23 @@ tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(27,9): error
!!! error TS2322: Types of parameters 'this' and 'this' are incompatible.
!!! error TS2322: Type 'void' is not assignable to type 'C'.
let o = {
explicitThis: function (m) { return m },
implicitThis(m: number): number { return m }
n: 101,
explicitThis: function (m: number) {
return m + this.n.length; // ok, this.n: any
},
implicitThis(m: number): number { return m; }
};
let i: I = o;
let o2: I = {
n: 1001
explicitThis: function (m) {
~~~~~~~~~~~~
!!! error TS1005: ',' expected.
return m + this.n.length; // error, this.n: number, no member 'length'
~~~~~~
!!! error TS2339: Property 'length' does not exist on type 'number'.
},
}
let x = i.explicitThis;
let n = x(12); // callee:void doesn't match this:I
~~~~~
@@ -45,4 +62,9 @@ tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(27,9): error
o.implicitThis = c.implicitThis; // ok, implicitThis(this:any)
o.implicitThis = c.explicitThis; // ok, implicitThis(this:any) is assignable to explicitThis(this: this)
o.implicitThis = i.explicitThis;
i.explicitThis = function(m) {
return this.n.length; // error, this.n: number
~~~~~~
!!! error TS2339: Property 'length' does not exist on type 'number'.
}

View File

@@ -1,5 +1,6 @@
//// [looseThisTypeInFunctions.ts]
interface I {
n: number;
explicitThis(this: this, m: number): number;
}
interface Unused {
@@ -20,10 +21,19 @@ class C implements I {
let c = new C();
c.explicitVoid = c.explicitThis; // error, 'void' is missing everything
let o = {
explicitThis: function (m) { return m },
implicitThis(m: number): number { return m }
n: 101,
explicitThis: function (m: number) {
return m + this.n.length; // ok, this.n: any
},
implicitThis(m: number): number { return m; }
};
let i: I = o;
let o2: I = {
n: 1001
explicitThis: function (m) {
return m + this.n.length; // error, this.n: number, no member 'length'
},
}
let x = i.explicitThis;
let n = x(12); // callee:void doesn't match this:I
let u: Unused;
@@ -33,6 +43,9 @@ c.explicitVoid = c.implicitThis // ok, implicitThis(this:any)
o.implicitThis = c.implicitThis; // ok, implicitThis(this:any)
o.implicitThis = c.explicitThis; // ok, implicitThis(this:any) is assignable to explicitThis(this: this)
o.implicitThis = i.explicitThis;
i.explicitThis = function(m) {
return this.n.length; // error, this.n: number
}
//// [looseThisTypeInFunctions.js]
@@ -53,10 +66,19 @@ var C = (function () {
var c = new C();
c.explicitVoid = c.explicitThis; // error, 'void' is missing everything
var o = {
explicitThis: function (m) { return m; },
n: 101,
explicitThis: function (m) {
return m + this.n.length; // ok, this.n: any
},
implicitThis: function (m) { return m; }
};
var i = o;
var o2 = {
n: 1001,
explicitThis: function (m) {
return m + this.n.length; // error, this.n: number, no member 'length'
}
};
var x = i.explicitThis;
var n = x(12); // callee:void doesn't match this:I
var u;
@@ -66,3 +88,6 @@ c.explicitVoid = c.implicitThis; // ok, implicitThis(this:any)
o.implicitThis = c.implicitThis; // ok, implicitThis(this:any)
o.implicitThis = c.explicitThis; // ok, implicitThis(this:any) is assignable to explicitThis(this: this)
o.implicitThis = i.explicitThis;
i.explicitThis = function (m) {
return this.n.length; // error, this.n: number
};

View File

@@ -140,10 +140,10 @@ c.explicitThis = explicitCFunction;
c.explicitThis = function(this: C, m: number) { return this.n + m };
// this:any compatibility
c.explicitC = function(m: number) { return this.n + m };
c.explicitProperty = function(m: number) { return this.n + m };
c.explicitThis = function(m: number) { return this.n + m };
c.implicitThis = function(m: number) { return this.n + m };
c.explicitC = function(m) { return this.n + m };
c.explicitProperty = function(m) { return this.n + m };
c.explicitThis = function(m) { return this.n + m };
c.implicitThis = function(m) { return this.n + m };
c.implicitThis = reconstructed.implicitThis;
c.explicitC = function(this: B, m: number) { return this.n + m };

View File

@@ -585,7 +585,7 @@ c.explicitThis = function(this: C, m: number) { return this.n + m };
>m : Symbol(m, Decl(thisTypeInFunctions.ts, 138, 34))
// this:any compatibility
c.explicitC = function(m: number) { return this.n + m };
c.explicitC = function(m) { return this.n + m };
>c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5))
>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3))
>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5))
@@ -595,7 +595,7 @@ c.explicitC = function(m: number) { return this.n + m };
>n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9))
>m : Symbol(m, Decl(thisTypeInFunctions.ts, 141, 23))
c.explicitProperty = function(m: number) { return this.n + m };
c.explicitProperty = function(m) { return this.n + m };
>c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5))
>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3))
>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5))
@@ -605,7 +605,7 @@ c.explicitProperty = function(m: number) { return this.n + m };
>n : Symbol(n, Decl(thisTypeInFunctions.ts, 12, 28))
>m : Symbol(m, Decl(thisTypeInFunctions.ts, 142, 30))
c.explicitThis = function(m: number) { return this.n + m };
c.explicitThis = function(m) { return this.n + m };
>c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14))
>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3))
>explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14))
@@ -615,7 +615,7 @@ c.explicitThis = function(m: number) { return this.n + m };
>n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9))
>m : Symbol(m, Decl(thisTypeInFunctions.ts, 143, 26))
c.implicitThis = function(m: number) { return this.n + m };
c.implicitThis = function(m) { return this.n + m };
>c.implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 5, 5))
>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3))
>implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 5, 5))

View File

@@ -520,7 +520,7 @@ let anyToSpecified: (this: { y: number }, x: number) => number = function(x: num
>this : { y: number; }
>y : number
>x : number
>function(x: number): number { return x + 12; } : (this: { y: number; }, x: number) => number
>function(x: number): number { return x + 12; } : (x: number) => number
>x : number
>x + 12 : number
>x : number
@@ -718,12 +718,12 @@ c.explicitThis = function(this: C, m: number) { return this.n + m };
>m : number
// this:any compatibility
c.explicitC = function(m: number) { return this.n + m };
>c.explicitC = function(m: number) { return this.n + m } : (this: C, m: number) => number
c.explicitC = function(m) { return this.n + m };
>c.explicitC = function(m) { return this.n + m } : (this: C, m: number) => number
>c.explicitC : (this: C, m: number) => number
>c : C
>explicitC : (this: C, m: number) => number
>function(m: number) { return this.n + m } : (this: C, m: number) => number
>function(m) { return this.n + m } : (this: C, m: number) => number
>m : number
>this.n + m : number
>this.n : number
@@ -731,12 +731,12 @@ c.explicitC = function(m: number) { return this.n + m };
>n : number
>m : number
c.explicitProperty = function(m: number) { return this.n + m };
>c.explicitProperty = function(m: number) { return this.n + m } : (this: { n: number; }, m: number) => number
c.explicitProperty = function(m) { return this.n + m };
>c.explicitProperty = function(m) { return this.n + m } : (this: { n: number; }, m: number) => number
>c.explicitProperty : (this: { n: number; }, m: number) => number
>c : C
>explicitProperty : (this: { n: number; }, m: number) => number
>function(m: number) { return this.n + m } : (this: { n: number; }, m: number) => number
>function(m) { return this.n + m } : (this: { n: number; }, m: number) => number
>m : number
>this.n + m : number
>this.n : number
@@ -744,12 +744,12 @@ c.explicitProperty = function(m: number) { return this.n + m };
>n : number
>m : number
c.explicitThis = function(m: number) { return this.n + m };
>c.explicitThis = function(m: number) { return this.n + m } : (this: C, m: number) => number
c.explicitThis = function(m) { return this.n + m };
>c.explicitThis = function(m) { return this.n + m } : (this: C, m: number) => number
>c.explicitThis : (this: C, m: number) => number
>c : C
>explicitThis : (this: C, m: number) => number
>function(m: number) { return this.n + m } : (this: C, m: number) => number
>function(m) { return this.n + m } : (this: C, m: number) => number
>m : number
>this.n + m : number
>this.n : number
@@ -757,12 +757,12 @@ c.explicitThis = function(m: number) { return this.n + m };
>n : number
>m : number
c.implicitThis = function(m: number) { return this.n + m };
>c.implicitThis = function(m: number) { return this.n + m } : (this: C, m: number) => number
c.implicitThis = function(m) { return this.n + m };
>c.implicitThis = function(m) { return this.n + m } : (this: C, m: number) => number
>c.implicitThis : (this: C, m: number) => number
>c : C
>implicitThis : (this: C, m: number) => number
>function(m: number) { return this.n + m } : (this: C, m: number) => number
>function(m) { return this.n + m } : (this: C, m: number) => number
>m : number
>this.n + m : number
>this.n : number

View File

@@ -94,6 +94,7 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(170,1): er
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(179,16): error TS2672: A function that is called with the 'new' keyword cannot have a 'this' type that is void.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(180,24): error TS2672: A function that is called with the 'new' keyword cannot have a 'this' type that is void.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(184,30): error TS2332: 'this' cannot be referenced in current location.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(184,61): error TS2339: Property 'n' does not exist on type 'void'.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(185,26): error TS1003: Identifier expected.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(185,30): error TS1005: ',' expected.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(185,57): error TS2339: Property 'n' does not exist on type 'void'.
@@ -103,7 +104,6 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(186,27): e
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(186,54): error TS2339: Property 'n' does not exist on type 'void'.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(187,23): error TS1005: ',' expected.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(187,24): error TS1138: Parameter declaration expected.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(187,51): error TS2339: Property 'n' does not exist on type 'void'.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(188,28): error TS1003: Identifier expected.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(188,32): error TS1005: ',' expected.
tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(188,59): error TS2339: Property 'n' does not exist on type 'void'.
@@ -452,6 +452,8 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(192,35): e
function notFirst(a: number, this: C): number { return this.n; }
~~~~~~~
!!! error TS2332: 'this' cannot be referenced in current location.
~
!!! error TS2339: Property 'n' does not exist on type 'void'.
function modifiers(async this: C): number { return this.n; }
~~~~
!!! error TS1003: Identifier expected.
@@ -473,8 +475,6 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(192,35): e
!!! error TS1005: ',' expected.
~
!!! error TS1138: Parameter declaration expected.
~
!!! error TS2339: Property 'n' does not exist on type 'void'.
function decorated(@deco() this: C): number { return this.n; }
~~~~
!!! error TS1003: Identifier expected.

View File

@@ -1 +1 @@
var foo:(a:{():number; (i:number):number; })=>number; foo = function(a:string){return 5};
var foo:(a:{():number; (i:number):number; })=>number; foo = function(this: void, a:string){return 5};

View File

@@ -1,4 +1,5 @@
interface I {
n: number;
explicitThis(this: this, m: number): number;
}
interface Unused {
@@ -19,10 +20,19 @@ class C implements I {
let c = new C();
c.explicitVoid = c.explicitThis; // error, 'void' is missing everything
let o = {
explicitThis: function (m) { return m },
implicitThis(m: number): number { return m }
n: 101,
explicitThis: function (m: number) {
return m + this.n.length; // ok, this.n: any
},
implicitThis(m: number): number { return m; }
};
let i: I = o;
let o2: I = {
n: 1001
explicitThis: function (m) {
return m + this.n.length; // error, this.n: number, no member 'length'
},
}
let x = i.explicitThis;
let n = x(12); // callee:void doesn't match this:I
let u: Unused;
@@ -32,3 +42,6 @@ c.explicitVoid = c.implicitThis // ok, implicitThis(this:any)
o.implicitThis = c.implicitThis; // ok, implicitThis(this:any)
o.implicitThis = c.explicitThis; // ok, implicitThis(this:any) is assignable to explicitThis(this: this)
o.implicitThis = i.explicitThis;
i.explicitThis = function(m) {
return this.n.length; // error, this.n: number
}

View File

@@ -0,0 +1,27 @@
// @strictThis: true
// 1. contextual typing predicate is wrong (currently: method2: function () ...)
// () -> yes (allParametersAreUntyped=t, noThisParameter=t, noTypeParameters=t)
// ok .. fixed?
// 2. contextual typing of this doesn't seem to work
// strictThis was turned off. DUH.
// 3. when it DID work, it was giving bogus types with strictThis OFF (see the last example)
interface T {
(x: number): void;
}
interface I {
n: number
method(this: this): number;
method2(this: this): number;
}
let i: I = {
n: 12,
method: function(this) { // this: I
return this.n.length; // error, 'number' has no property 'length'
},
method2: function() { // this: I
return this.n.length; // error, 'number' has no property 'length'
}
}
i.method = function () { return this.n.length } // this: I
i.method = function (this) { return this.n.length } // this: I
var t: T = function (this, y) { } // yes! (but this: any NOT number!!)

View File

@@ -140,10 +140,10 @@ c.explicitThis = explicitCFunction;
c.explicitThis = function(this: C, m: number) { return this.n + m };
// this:any compatibility
c.explicitC = function(m: number) { return this.n + m };
c.explicitProperty = function(m: number) { return this.n + m };
c.explicitThis = function(m: number) { return this.n + m };
c.implicitThis = function(m: number) { return this.n + m };
c.explicitC = function(m) { return this.n + m };
c.explicitProperty = function(m) { return this.n + m };
c.explicitThis = function(m) { return this.n + m };
c.implicitThis = function(m) { return this.n + m };
c.implicitThis = reconstructed.implicitThis;
c.explicitC = function(this: B, m: number) { return this.n + m };