mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-12 01:48:33 -05:00
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:
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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'.
|
||||
}
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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 };
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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};
|
||||
@@ -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
|
||||
}
|
||||
|
||||
27
tests/cases/conformance/types/thisType/thisTypeInFuncTemp.ts
Normal file
27
tests/cases/conformance/types/thisType/thisTypeInFuncTemp.ts
Normal 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!!)
|
||||
@@ -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 };
|
||||
|
||||
Reference in New Issue
Block a user