From 0a968f0868695953537a656c1a7c36f3bb70f076 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 29 Jan 2016 14:10:43 -0800 Subject: [PATCH 01/41] Parse this type using parameter syntax Syntax is the same as a normal parameter: ```ts function f(this: void, x: number) { } ``` --- src/compiler/parser.ts | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 787a022140fad..725092d12c802 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1722,7 +1722,7 @@ namespace ts { }; // Parses a comma-delimited list of elements - function parseDelimitedList(kind: ParsingContext, parseElement: () => T, considerSemicolonAsDelimeter?: boolean): NodeArray { + function parseDelimitedList(kind: ParsingContext, parseElement: () => T, considerSemicolonAsDelimiter?: boolean): NodeArray { const saveParsingContext = parsingContext; parsingContext |= 1 << kind; const result = >[]; @@ -1751,7 +1751,7 @@ namespace ts { // parse errors. For example, this can happen when people do things like use // a semicolon to delimit object literal members. Note: we'll have already // reported an error when we called parseExpected above. - if (considerSemicolonAsDelimeter && token === SyntaxKind.SemicolonToken && !scanner.hasPrecedingLineBreak()) { + if (considerSemicolonAsDelimiter && token === SyntaxKind.SemicolonToken && !scanner.hasPrecedingLineBreak()) { nextToken(); } continue; @@ -2002,7 +2002,7 @@ namespace ts { } function isStartOfParameter(): boolean { - return token === SyntaxKind.DotDotDotToken || isIdentifierOrPattern() || isModifierKind(token) || token === SyntaxKind.AtToken; + return token === SyntaxKind.DotDotDotToken || isIdentifierOrPattern() || isModifierKind(token) || token === SyntaxKind.AtToken || token === SyntaxKind.ThisKeyword; } function setModifiers(node: Node, modifiers: ModifiersArray) { @@ -2014,15 +2014,19 @@ namespace ts { function parseParameter(): ParameterDeclaration { const node = createNode(SyntaxKind.Parameter); + if (token === SyntaxKind.ThisKeyword) { + node.name = createIdentifier(/*isIdentifier*/true, undefined); + node.type = parseParameterType(); + return finishNode(node); + } + node.decorators = parseDecorators(); setModifiers(node, parseModifiers()); node.dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken); // FormalParameter [Yield,Await]: // BindingElement[?Yield,?Await] - node.name = parseIdentifierOrPattern(); - if (getFullWidth(node.name) === 0 && node.flags === 0 && isModifierKind(token)) { // in cases like // 'use strict' @@ -2060,11 +2064,11 @@ namespace ts { } function fillSignature( - returnToken: SyntaxKind, - yieldContext: boolean, - awaitContext: boolean, - requireCompleteParameterList: boolean, - signature: SignatureDeclaration): void { + returnToken: SyntaxKind, + yieldContext: boolean, + awaitContext: boolean, + requireCompleteParameterList: boolean, + signature: SignatureDeclaration): void { const returnTokenRequired = returnToken === SyntaxKind.EqualsGreaterThanToken; signature.typeParameters = parseTypeParameters(); @@ -2464,7 +2468,7 @@ namespace ts { // ( ... return true; } - if (isIdentifier() || isModifierKind(token)) { + if (isIdentifier() || isModifierKind(token) || token === SyntaxKind.ThisKeyword) { nextToken(); if (token === SyntaxKind.ColonToken || token === SyntaxKind.CommaToken || token === SyntaxKind.QuestionToken || token === SyntaxKind.EqualsToken || @@ -3981,7 +3985,7 @@ namespace ts { node.flags |= NodeFlags.MultiLine; } - node.properties = parseDelimitedList(ParsingContext.ObjectLiteralMembers, parseObjectLiteralElement, /*considerSemicolonAsDelimeter*/ true); + node.properties = parseDelimitedList(ParsingContext.ObjectLiteralMembers, parseObjectLiteralElement, /*considerSemicolonAsDelimiter*/ true); parseExpected(SyntaxKind.CloseBraceToken); return finishNode(node); } From d8a77c00557129f3b24cffb7d35888c8519aaebf Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 29 Jan 2016 14:30:01 -0800 Subject: [PATCH 02/41] Check this type in functions. If `this` is not provided, it defaults to `void` for functions and `this` for methods. The rules for checking are similar to parameter checking, but there's still quite a bit of duplication for this implementation. --- src/compiler/binder.ts | 3 + src/compiler/checker.ts | 161 ++++++++++++++++++++++++++++++++-------- 2 files changed, 134 insertions(+), 30 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index cc81f92fbfcaa..cbeb35ce56ce6 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -1297,6 +1297,9 @@ namespace ts { // as other properties in the object literal. So we use SymbolFlags.PropertyExcludes // so that it will conflict with any other object literal members with the same // name. + if (options.strictThis) { + seenThisKeyword = true; + } return bindPropertyOrMethodOrAccessor(node, SymbolFlags.Method | ((node).questionToken ? SymbolFlags.Optional : SymbolFlags.None), isObjectLiteralMethod(node) ? SymbolFlags.PropertyExcludes : SymbolFlags.MethodExcludes); case SyntaxKind.FunctionDeclaration: diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a0040982356ad..3940be5d69852 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -131,8 +131,8 @@ namespace ts { const noConstraintType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); - const anySignature = createSignature(undefined, undefined, emptyArray, anyType, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false); - const unknownSignature = createSignature(undefined, undefined, emptyArray, unknownType, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false); + 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 enumNumberIndexInfo = createIndexInfo(stringType, /*isReadonly*/ true); @@ -2194,10 +2194,17 @@ namespace ts { } } - function buildDisplayForParametersAndDelimiters(parameters: Symbol[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) { + function buildDisplayForParametersAndDelimiters(thisType: Type, parameters: Symbol[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) { writePunctuation(writer, SyntaxKind.OpenParenToken); + const useThisType = thisType && thisType.symbol; + if (useThisType) { + writeKeyword(writer, SyntaxKind.ThisKeyword); + writePunctuation(writer, SyntaxKind.ColonToken); + writeSpace(writer); + buildTypeDisplay(thisType, writer, enclosingDeclaration, flags, symbolStack); + } for (let i = 0; i < parameters.length; i++) { - if (i > 0) { + if (i > 0 || useThisType) { writePunctuation(writer, SyntaxKind.CommaToken); writeSpace(writer); } @@ -2247,7 +2254,7 @@ namespace ts { buildDisplayForTypeParametersAndDelimiters(signature.typeParameters, writer, enclosingDeclaration, flags, symbolStack); } - buildDisplayForParametersAndDelimiters(signature.parameters, writer, enclosingDeclaration, flags, symbolStack); + buildDisplayForParametersAndDelimiters(signature.thisType, signature.parameters, writer, enclosingDeclaration, flags, symbolStack); buildReturnTypeDisplay(signature, writer, enclosingDeclaration, flags, symbolStack); } @@ -3414,7 +3421,7 @@ namespace ts { // Returns true if the class or interface member given by the symbol is free of "this" references. The // function may return false for symbols that are actually free of "this" references because it is not // feasible to perform a complete analysis in all cases. In particular, property members with types - // inferred from their initializers and function members with inferred return types are convervatively + // inferred from their initializers and function members with inferred return types are conservatively // assumed not to be free of "this" references. function isIndependentMember(symbol: Symbol): boolean { if (symbol.declarations && symbol.declarations.length === 1) { @@ -3426,6 +3433,7 @@ namespace ts { return isIndependentVariableLikeDeclaration(declaration); case SyntaxKind.MethodDeclaration: case SyntaxKind.MethodSignature: + return compilerOptions.strictThis ? false : isIndependentFunctionLikeDeclaration(declaration); case SyntaxKind.Constructor: return isIndependentFunctionLikeDeclaration(declaration); } @@ -3525,12 +3533,13 @@ namespace ts { resolveObjectTypeMembers(type, source, typeParameters, typeArguments); } - function createSignature(declaration: SignatureDeclaration, typeParameters: TypeParameter[], parameters: Symbol[], + function createSignature(declaration: SignatureDeclaration, typeParameters: TypeParameter[], parameters: Symbol[], thisType: Type, resolvedReturnType: Type, minArgumentCount: number, hasRestParameter: boolean, hasStringLiterals: boolean): Signature { const sig = new Signature(checker); sig.declaration = declaration; sig.typeParameters = typeParameters; sig.parameters = parameters; + sig.thisType = thisType; sig.resolvedReturnType = resolvedReturnType; sig.minArgumentCount = minArgumentCount; sig.hasRestParameter = hasRestParameter; @@ -3539,15 +3548,19 @@ namespace ts { } function cloneSignature(sig: Signature): Signature { - return createSignature(sig.declaration, sig.typeParameters, sig.parameters, sig.resolvedReturnType, + return createSignature(sig.declaration, sig.typeParameters, sig.parameters, sig.thisType, sig.resolvedReturnType, sig.minArgumentCount, sig.hasRestParameter, sig.hasStringLiterals); } + function getParameterTypeAtIndex(signature: Signature, i: number, max: number, outOfRangeType?: Type): Type { + return i < max ? getTypeOfSymbol(signature.parameters[i]) : (outOfRangeType || getRestTypeOfSignature(signature)); + } + function getDefaultConstructSignatures(classType: InterfaceType): Signature[] { const baseConstructorType = getBaseConstructorTypeOfClass(classType); const baseSignatures = getSignaturesOfType(baseConstructorType, SignatureKind.Construct); if (baseSignatures.length === 0) { - return [createSignature(undefined, classType.localTypeParameters, emptyArray, classType, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false)]; + return [createSignature(undefined, classType.localTypeParameters, emptyArray, undefined, classType, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false)]; } const baseTypeNode = getBaseTypeNodeOfClass(classType); const typeArguments = map(baseTypeNode.typeArguments, getTypeFromTypeNode); @@ -4077,6 +4090,7 @@ namespace ts { const parameters: Symbol[] = []; let hasStringLiterals = false; let minArgumentCount = -1; + let thisType: Type = undefined; const isJSConstructSignature = isJSDocConstructSignature(declaration); let returnType: Type = undefined; @@ -4092,15 +4106,23 @@ namespace ts { const resolvedSymbol = resolveName(param, paramSymbol.name, SymbolFlags.Value, undefined, undefined); paramSymbol = resolvedSymbol; } - parameters.push(paramSymbol); - + 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); + } + } + else { + parameters.push(paramSymbol); + } + if (param.type && param.type.kind === SyntaxKind.StringLiteralType) { hasStringLiterals = true; } if (param.initializer || param.questionToken || param.dotDotDotToken) { if (minArgumentCount < 0) { - minArgumentCount = i; + minArgumentCount = i - (thisType ? 1 : 0); } } else { @@ -4110,7 +4132,22 @@ namespace ts { } if (minArgumentCount < 0) { - minArgumentCount = declaration.parameters.length; + minArgumentCount = declaration.parameters.length - (thisType ? 1 : 0); + } + if (!thisType && 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((declaration.parent).name)) : + getThisType(declaration.name); + Debug.assert(!!thisType, "couldn't find implicit this type"); + } } if (isJSConstructSignature) { @@ -4143,7 +4180,7 @@ namespace ts { } } - links.resolvedSignature = createSignature(declaration, typeParameters, parameters, returnType, minArgumentCount, hasRestParameter(declaration), hasStringLiterals); + links.resolvedSignature = createSignature(declaration, typeParameters, parameters, thisType, returnType, minArgumentCount, hasRestParameter(declaration), hasStringLiterals); } return links.resolvedSignature; } @@ -4834,7 +4871,7 @@ namespace ts { return links.resolvedType; } - function getThisType(node: TypeNode): Type { + function getThisType(node: Node): Type { const container = getThisContainer(node, /*includeArrowFunctions*/ false); const parent = container && container.parent; if (parent && (isClassLike(parent) || parent.kind === SyntaxKind.InterfaceDeclaration)) { @@ -5062,6 +5099,7 @@ namespace ts { } const result = createSignature(signature.declaration, freshTypeParameters, 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; @@ -5175,7 +5213,14 @@ namespace ts { } function isContextSensitiveFunctionLikeDeclaration(node: FunctionLikeDeclaration) { - return !node.typeParameters && node.parameters.length && !forEach(node.parameters, p => p.type); + if (compilerOptions.strictThis) { + return !node.typeParameters && + (!forEach(node.parameters, p => p.type) + || (node.kind !== SyntaxKind.ArrowFunction && (!node.parameters.length || (node.parameters[0].name).text !== "this"))); + } + else { + return !node.typeParameters && node.parameters.length && !forEach(node.parameters, p => p.type); + } } function getTypeWithoutSignatures(type: Type): Type { @@ -5252,6 +5297,22 @@ namespace ts { target = getErasedSignature(target); let result = Ternary.True; + if (source.thisType || target.thisType) { + const s = source.thisType || anyType; + const t = target.thisType || anyType; + if (s !== voidType) { + // void sources are assignable to anything. + let related = compareTypes(getApparentType(t), getApparentType(s), reportErrors); + if (!related) { + related = compareTypes(getApparentType(s), getApparentType(t), /*reportErrors*/ false); + if (!related) { + errorReporter(Diagnostics.Types_of_parameters_0_and_1_are_incompatible, "this", "this"); + return Ternary.False; + } + } + result &= related; + } + } const sourceMax = getNumNonRestParameters(source); const targetMax = getNumNonRestParameters(target); @@ -6434,9 +6495,7 @@ namespace ts { count = sourceMax < targetMax ? sourceMax : targetMax; } for (let i = 0; i < count; i++) { - const s = i < sourceMax ? getTypeOfSymbol(source.parameters[i]) : getRestTypeOfSignature(source); - const t = i < targetMax ? getTypeOfSymbol(target.parameters[i]) : getRestTypeOfSignature(target); - callback(s, t); + callback(getParameterTypeAtIndex(source, i, sourceMax), getParameterTypeAtIndex(target, i, targetMax)); } } @@ -7313,7 +7372,12 @@ namespace ts { if (needToCaptureLexicalThis) { captureLexicalThis(node, container); } - + if (isFunctionLike(container)) { + const signature = getSignatureFromDeclaration(container); + if (signature.thisType) { + return signature.thisType; + } + } if (isClassLike(container.parent)) { const symbol = getSymbolOfNode(container.parent); return container.flags & NodeFlags.Static ? getTypeOfSymbol(symbol) : (getDeclaredTypeOfSymbol(symbol)).thisType; @@ -7330,7 +7394,7 @@ namespace ts { if (container.kind === SyntaxKind.FunctionExpression) { if (getSpecialPropertyAssignmentKind(container.parent) === SpecialPropertyAssignmentKind.PrototypeProperty) { // Get the 'x' of 'x.prototype.y = f' (here, 'f' is 'container') - const className = (((container.parent as BinaryExpression) // x.protoype.y = f + const className = (((container.parent as BinaryExpression) // x.prototype.y = f .left as PropertyAccessExpression) // x.prototype.y .expression as PropertyAccessExpression) // x.prototype .expression; // x @@ -9306,7 +9370,7 @@ namespace ts { return getSignatureInstantiation(signature, getInferredTypes(context)); } - function inferTypeArguments(node: CallLikeExpression, signature: Signature, args: Expression[], excludeArgument: boolean[], context: InferenceContext): void { + function inferTypeArguments(node: CallLikeExpression, signature: Signature, args: Expression[], excludeCallee: boolean, excludeArgument: boolean[], context: InferenceContext): void { const typeParameters = signature.typeParameters; const inferenceMapper = getInferenceMapper(context); @@ -9332,6 +9396,13 @@ namespace ts { context.failedTypeParameterIndex = undefined; } + const calleeNode = node.kind === SyntaxKind.CallExpression && ((node).expression).expression; + if (signature.thisType) { + const mapper = excludeCallee !== undefined ? identityMapper : inferenceMapper; + const calleeType: Type = calleeNode ? checkExpressionWithContextualType(calleeNode, signature.thisType, mapper) : voidType; + inferTypes(context, calleeType, signature.thisType); + } + // We perform two passes over the arguments. In the first pass we infer from all arguments, but use // wildcards for all context sensitive function expressions. const argCount = getEffectiveArgumentCount(node, args, signature); @@ -9361,8 +9432,13 @@ namespace ts { // Decorators will not have `excludeArgument`, as their arguments cannot be contextually typed. // Tagged template expressions will always have `undefined` for `excludeArgument[0]`. if (excludeArgument) { + if (signature.thisType && calleeNode) { + if (excludeCallee === false) { + inferTypes(context, checkExpressionWithContextualType(calleeNode, signature.thisType, inferenceMapper), signature.thisType); + } + } for (let i = 0; i < argCount; i++) { - // No need to check for omitted args and template expressions, their exlusion value is always undefined + // No need to check for omitted args and template expressions, their exclusion value is always undefined if (excludeArgument[i] === false) { const arg = args[i]; const paramType = getTypeAtPosition(signature, i); @@ -9405,6 +9481,18 @@ namespace ts { } function checkApplicableSignature(node: CallLikeExpression, args: Expression[], signature: Signature, relation: Map, excludeArgument: boolean[], reportErrors: boolean) { + const headMessage = Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1; + if (signature.thisType && signature.thisType !== voidType && node.kind !== SyntaxKind.NewExpression) { + // If the source is not of the form `x.f`, then sourceType = voidType + // If the target is voidType, then the check is skipped -- anything is compatible. + // If the the expression is a new expression, then the check is skipped. + const calleeNode = node.kind === SyntaxKind.CallExpression && ((node).expression).expression; + const calleeType: Type = calleeNode ? checkExpressionWithContextualType(calleeNode, signature.thisType, undefined) : voidType; + const errorNode = reportErrors ? (calleeNode || node) : undefined; + if (!checkTypeRelatedTo(calleeType, getApparentType(signature.thisType), relation, errorNode, headMessage)) { + return false; + } + } const argCount = getEffectiveArgumentCount(node, args, signature); for (let i = 0; i < argCount; i++) { const arg = getEffectiveArgument(node, args, i); @@ -9424,7 +9512,6 @@ namespace ts { // Use argument expression as error location when reporting errors const errorNode = reportErrors ? getEffectiveArgumentErrorNode(node, i, arg) : undefined; - const headMessage = Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1; if (!checkTypeRelatedTo(argType, paramType, relation, errorNode, headMessage)) { return false; } @@ -9778,8 +9865,13 @@ namespace ts { // // For a decorator, no arguments are susceptible to contextual typing due to the fact // decorators are applied to a declaration by the emitter, and not to an expression. + let excludeCallee: boolean; let excludeArgument: boolean[]; if (!isDecorator) { + const calleeNode = node.kind === SyntaxKind.CallExpression && ((node).expression).expression; + if (calleeNode && isContextSensitive(calleeNode)) { + excludeCallee = true; + } // We do not need to call `getEffectiveArgumentCount` here as it only // applies when calculating the number of arguments for a decorator. for (let i = isTaggedTemplate ? 1 : 0; i < args.length; i++) { @@ -9928,7 +10020,7 @@ namespace ts { typeArgumentsAreValid = checkTypeArguments(candidate, typeArguments, typeArgumentTypes, /*reportErrors*/ false); } else { - inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext); + inferTypeArguments(node, candidate, args, excludeCallee, excludeArgument, inferenceContext); typeArgumentsAreValid = inferenceContext.failedTypeParameterIndex === undefined; typeArgumentTypes = inferenceContext.inferredTypes; } @@ -10086,13 +10178,16 @@ 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 Any. + // operation is the function's this type. 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); if (getReturnTypeOfSignature(signature) !== voidType) { error(node, Diagnostics.Only_a_void_function_can_be_called_with_the_new_keyword); } + if (signature.thisType === voidType) { + error(node, Diagnostics.A_function_that_is_called_with_the_new_keyword_cannot_have_a_this_type_that_is_void); + } return signature; } @@ -10244,10 +10339,10 @@ namespace ts { if (funcSymbol && funcSymbol.members && (funcSymbol.flags & SymbolFlags.Function)) { return getInferredClassType(funcSymbol); } - else if (compilerOptions.noImplicitAny) { + else if (compilerOptions.noImplicitAny && !signature.thisType) { error(node, Diagnostics.new_expression_whose_target_lacks_a_construct_signature_implicitly_has_an_any_type); } - return anyType; + return signature.thisType || anyType; } } @@ -10282,11 +10377,17 @@ namespace ts { function getTypeAtPosition(signature: Signature, pos: number): Type { return signature.hasRestParameter ? - pos < signature.parameters.length - 1 ? getTypeOfSymbol(signature.parameters[pos]) : getRestTypeOfSignature(signature) : - pos < signature.parameters.length ? getTypeOfSymbol(signature.parameters[pos]) : anyType; + getParameterTypeAtIndex(signature, pos, signature.parameters.length - 1) : + getParameterTypeAtIndex(signature, pos, signature.parameters.length, anyType); } function assignContextualParameterTypes(signature: Signature, context: Signature, mapper: TypeMapper) { + if (context.thisType) { + if (signature.declaration.kind !== SyntaxKind.ArrowFunction) { + // do not contextually type thisType for ArrowFunction. + signature.thisType = context.thisType; + } + } const len = signature.parameters.length - (signature.hasRestParameter ? 1 : 0); for (let i = 0; i < len; i++) { const parameter = signature.parameters[i]; From a639b71ed0837775593240a1a86cc14594f3213b Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 29 Jan 2016 14:34:44 -0800 Subject: [PATCH 03/41] Skip emit of this types as first parameter. --- src/compiler/emitter.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 4d771bd2538fb..fc8e811fb6539 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -4436,8 +4436,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge write("("); if (node) { const parameters = node.parameters; + const skipCount = node.parameters.length && (node.parameters[0].name).text === "this" ? 1 : 0; const omitCount = languageVersion < ScriptTarget.ES6 && hasRestParameter(node) ? 1 : 0; - emitList(parameters, 0, parameters.length - omitCount, /*multiLine*/ false, /*trailingComma*/ false); + emitList(parameters, skipCount, parameters.length - omitCount - skipCount, /*multiLine*/ false, /*trailingComma*/ false); } write(")"); decreaseIndent(); From 9bd7afb143fff13458a514da29bd7ad8547a4d68 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 29 Jan 2016 14:39:01 -0800 Subject: [PATCH 04/41] Add new error message and strictThis flag --- src/compiler/commandLineParser.ts | 4 ++++ src/compiler/diagnosticMessages.json | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index d5bf95a64058a..3eb42292fb1ba 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -130,6 +130,10 @@ namespace ts { name: "skipDefaultLibCheck", type: "boolean", }, + { + name: "strictThis", + type: "boolean", + }, { name: "out", type: "string", diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index ca5a6d9d41527..2043a89c8fd86 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1819,6 +1819,10 @@ "category": "Error", "code": 2670 }, + "A function that is called with the 'new' keyword cannot have a 'this' type that is void.": { + "category": "Error", + "code": 2671 + }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", "code": 4000 From ca162090325e35fe8479d90698b35b2d89360f7f Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 29 Jan 2016 14:43:50 -0800 Subject: [PATCH 05/41] Make compiler strictThis clean. --- src/compiler/core.ts | 19 ++++++----- src/compiler/program.ts | 3 +- src/compiler/sourcemap.ts | 8 ++--- src/compiler/sys.ts | 2 +- src/compiler/types.ts | 18 +++++----- src/compiler/utilities.ts | 20 +++++------ src/harness/harness.ts | 26 +++++++------- src/harness/loggedIO.ts | 34 ++++++++++--------- src/server/editorServices.ts | 2 +- src/server/node.d.ts | 4 +-- .../formatting/ruleOperationContext.ts | 4 +-- src/services/utilities.ts | 2 +- 12 files changed, 74 insertions(+), 68 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 21536da36ff26..ab8de44ec98f0 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -818,25 +818,26 @@ namespace ts { getSignatureConstructor(): new (checker: TypeChecker) => Signature; } + // TODO: Add a 'this' parameter after I update the previous-version compiler function Symbol(flags: SymbolFlags, name: string) { - this.flags = flags; - this.name = name; - this.declarations = undefined; + (this).flags = flags; + (this).name = name; + (this).declarations = undefined; } function Type(checker: TypeChecker, flags: TypeFlags) { - this.flags = flags; + (this).flags = flags; } function Signature(checker: TypeChecker) { } function Node(kind: SyntaxKind, pos: number, end: number) { - this.kind = kind; - this.pos = pos; - this.end = end; - this.flags = NodeFlags.None; - this.parent = undefined; + (this).kind = kind; + (this).pos = pos; + (this).end = end; + (this).flags = NodeFlags.None; + (this).parent = undefined; } export let objectAllocator: ObjectAllocator = { diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 803ae47b0fd5f..88c77aa57598f 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -933,8 +933,9 @@ namespace ts { return noDiagnosticsTypeChecker || (noDiagnosticsTypeChecker = createTypeChecker(program, /*produceDiagnostics:*/ false)); } + // TODO: needs to have this: Program function emit(sourceFile?: SourceFile, writeFileCallback?: WriteFileCallback, cancellationToken?: CancellationToken): EmitResult { - return runWithCancellationToken(() => emitWorker(this, sourceFile, writeFileCallback, cancellationToken)); + return runWithCancellationToken(() => emitWorker((this), sourceFile, writeFileCallback, cancellationToken)); } function isEmitBlocked(emitFileName: string): boolean { diff --git a/src/compiler/sourcemap.ts b/src/compiler/sourcemap.ts index 8abf1432b0c73..fb61f8b78b825 100644 --- a/src/compiler/sourcemap.ts +++ b/src/compiler/sourcemap.ts @@ -4,10 +4,10 @@ namespace ts { export interface SourceMapWriter { getSourceMapData(): SourceMapData; - setSourceFile(sourceFile: SourceFile): void; - emitPos(pos: number): void; - emitStart(range: TextRange): void; - emitEnd(range: TextRange, stopOverridingSpan?: boolean): void; + setSourceFile: (sourceFile: SourceFile) => void; + emitPos: (pos: number) => void; + emitStart: (range: TextRange) => void; + emitEnd: (range: TextRange, stopOverridingSpan?: boolean) => void; changeEmitSourcePos(): void; getText(): string; getSourceMappingURL(): string; diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index bf25d39aa4395..1a9da39bf9a0e 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -63,7 +63,7 @@ namespace ts { useCaseSensitiveFileNames?: boolean; echo(s: string): void; quit(exitCode?: number): void; - fileExists(path: string): boolean; + fileExists: (path: string) => boolean; directoryExists(path: string): boolean; createDirectory(path: string): void; resolvePath(path: string): string; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 796529d9d4f21..9c2612d96b607 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1593,8 +1593,8 @@ namespace ts { } export interface ScriptReferenceHost { - getCompilerOptions(): CompilerOptions; - getSourceFile(fileName: string): SourceFile; + getCompilerOptions: () => CompilerOptions; + getSourceFile: (fileName: string) => SourceFile; getCurrentDirectory(): string; } @@ -1625,7 +1625,7 @@ namespace ts { /** * Get a list of files in the program */ - getSourceFiles(): SourceFile[]; + getSourceFiles: () => SourceFile[]; /** * Emits the JavaScript and declaration files. If targetSourceFile is not specified, then @@ -1650,7 +1650,7 @@ namespace ts { */ getTypeChecker(): TypeChecker; - /* @internal */ getCommonSourceDirectory(): string; + /* @internal */ getCommonSourceDirectory: () => string; // For testing purposes only. Should not be used by any other consumers (including the // language service). @@ -1781,7 +1781,7 @@ namespace ts { buildParameterDisplay(parameter: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; buildTypeParameterDisplay(tp: TypeParameter, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; buildTypeParameterDisplayFromSymbol(symbol: Symbol, writer: SymbolWriter, enclosingDeclaraiton?: Node, flags?: TypeFormatFlags): void; - buildDisplayForParametersAndDelimiters(parameters: Symbol[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; + buildDisplayForParametersAndDelimiters(thisType: Type, parameters: Symbol[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; buildDisplayForTypeParametersAndDelimiters(typeParameters: TypeParameter[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; buildReturnTypeDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; } @@ -1905,11 +1905,11 @@ namespace ts { getReferencedImportDeclaration(node: Identifier): Declaration; getReferencedDeclarationWithCollidingName(node: Identifier): Declaration; isDeclarationWithCollidingName(node: Declaration): boolean; - isValueAliasDeclaration(node: Node): boolean; - isReferencedAliasDeclaration(node: Node, checkChildren?: boolean): boolean; + isValueAliasDeclaration: (node: Node) => boolean; + isReferencedAliasDeclaration: (node: Node, checkChildren?: boolean) => boolean; isTopLevelValueImportEqualsWithEntityName(node: ImportEqualsDeclaration): boolean; getNodeCheckFlags(node: Node): NodeCheckFlags; - isDeclarationVisible(node: Declaration): boolean; + isDeclarationVisible: (node: Declaration) => boolean; collectLinkedAliases(node: Identifier): Node[]; isImplementationOfOverload(node: FunctionLikeDeclaration): boolean; writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void; @@ -2279,6 +2279,7 @@ namespace ts { declaration: SignatureDeclaration; // Originating declaration typeParameters: TypeParameter[]; // Type parameters (undefined if non-generic) parameters: Symbol[]; // Parameters + thisType?: Type; // type of this-type /* @internal */ resolvedReturnType: Type; // Resolved return type /* @internal */ @@ -2429,6 +2430,7 @@ namespace ts { rootDir?: string; sourceMap?: boolean; sourceRoot?: string; + strictThis?: boolean, suppressExcessPropertyErrors?: boolean; suppressImplicitAnyIndexErrors?: boolean; target?: ScriptTarget; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index bab66eb0688bc..bce821c375676 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -32,11 +32,11 @@ namespace ts { } export interface EmitHost extends ScriptReferenceHost { - getSourceFiles(): SourceFile[]; + getSourceFiles: () => SourceFile[]; - getCommonSourceDirectory(): string; - getCanonicalFileName(fileName: string): string; - getNewLine(): string; + getCommonSourceDirectory: () => string; + getCanonicalFileName: (fileName: string) => string; + getNewLine: () => string; isEmitBlocked(emitFileName: string): boolean; @@ -1869,11 +1869,11 @@ namespace ts { } export interface EmitTextWriter { - write(s: string): void; - writeTextOfNode(text: string, node: Node): void; - writeLine(): void; - increaseIndent(): void; - decreaseIndent(): void; + write: (s: string) => void; + writeTextOfNode: (text: string, node: Node) => void; + writeLine: () => void; + increaseIndent: () => void; + decreaseIndent: () => void; getText(): string; rawWrite(s: string): void; writeLiteral(s: string): void; @@ -2490,7 +2490,7 @@ namespace ts { * as the fallback implementation does not check for circular references by default. */ export const stringify: (value: any) => string = typeof JSON !== "undefined" && JSON.stringify - ? JSON.stringify + ? JSON.stringify : stringifyFallback; /** diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 2b0c95c0a61b0..3b211a0d91ac2 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -417,24 +417,24 @@ namespace Harness.Path { namespace Harness { export interface IO { + args(): string[]; newLine(): string; - getCurrentDirectory(): string; - useCaseSensitiveFileNames(): boolean; - resolvePath(path: string): string; - readFile(path: string): string; + readFile(this: ts.System | IO, path: string): string; writeFile(path: string, contents: string): void; - directoryName(path: string): string; + resolvePath(path: string): string; + fileExists: (fileName: string) => boolean; + directoryExists: (path: string) => boolean; createDirectory(path: string): void; - fileExists(fileName: string): boolean; - directoryExists(path: string): boolean; - deleteFile(fileName: string): void; - listFiles(path: string, filter: RegExp, options?: { recursive?: boolean }): string[]; - log(text: string): void; + getExecutingFilePath(this: ts.System | IO): string; + getCurrentDirectory(): string; + readDirectory(path: string, extension?: string, exclude?: string[]): string[]; getMemoryUsage?(): number; - args(): string[]; - getExecutingFilePath(): string; exit(exitCode?: number): void; - readDirectory(path: string, extension?: string, exclude?: string[]): string[]; + deleteFile(fileName: string): void; + directoryName: (path: string) => string; + listFiles(path: string, filter: RegExp, options?: { recursive?: boolean }): string[]; + log: (text: string) => void; + useCaseSensitiveFileNames(): boolean; } export var IO: IO; diff --git a/src/harness/loggedIO.ts b/src/harness/loggedIO.ts index 3d51682f745b9..dbc05112f3ef0 100644 --- a/src/harness/loggedIO.ts +++ b/src/harness/loggedIO.ts @@ -70,11 +70,11 @@ interface IOLog { interface PlaybackControl { startReplayFromFile(logFileName: string): void; - startReplayFromString(logContents: string): void; - startReplayFromData(log: IOLog): void; + startReplayFromString(this: PlaybackControl, logContents: string): void; + startReplayFromData(this: PlaybackControl, log: IOLog): void; endReplay(): void; startRecord(logFileName: string): void; - endRecord(): void; + endRecord(this: PlaybackControl): void; } namespace Playback { @@ -127,6 +127,8 @@ namespace Playback { function initWrapper(wrapper: PlaybackSystem, underlying: ts.System): void; function initWrapper(wrapper: PlaybackIO, underlying: Harness.IO): void; function initWrapper(wrapper: PlaybackSystem | PlaybackIO, underlying: ts.System | Harness.IO): void { + // TODO: Define a common interface over ts.System | Harness.IO and stop passing a union type. + const underlyingShim: any = underlying; ts.forEach(Object.keys(underlying), prop => { (wrapper)[prop] = (underlying)[prop]; }); @@ -154,20 +156,20 @@ namespace Playback { }; wrapper.startReplayFromFile = logFn => { - wrapper.startReplayFromString(underlying.readFile(logFn)); + wrapper.startReplayFromString(underlyingShim.readFile(logFn)); }; wrapper.endRecord = () => { if (recordLog !== undefined) { let i = 0; const fn = () => recordLogFileNameBase + i + ".json"; - while (underlying.fileExists(fn())) i++; - underlying.writeFile(fn(), JSON.stringify(recordLog)); + while (underlyingShim.fileExists(fn())) i++; + underlyingShim.writeFile(fn(), JSON.stringify(recordLog)); recordLog = undefined; } }; wrapper.fileExists = recordReplay(wrapper.fileExists, underlying)( - path => callAndRecord(underlying.fileExists(path), recordLog.fileExists, { path }), + path => callAndRecord(underlyingShim.fileExists(path), recordLog.fileExists, { path }), memoize(path => { // If we read from the file, it must exist if (findResultByPath(wrapper, replayLog.filesRead, path, null) !== null) { @@ -184,10 +186,10 @@ namespace Playback { return replayLog.executingPath; } else if (recordLog !== undefined) { - return recordLog.executingPath = underlying.getExecutingFilePath(); + return recordLog.executingPath = underlyingShim.getExecutingFilePath(); } else { - return underlying.getExecutingFilePath(); + return underlyingShim.getExecutingFilePath(); } }; @@ -196,20 +198,20 @@ namespace Playback { return replayLog.currentDirectory || ""; } else if (recordLog !== undefined) { - return recordLog.currentDirectory = underlying.getCurrentDirectory(); + return recordLog.currentDirectory = underlyingShim.getCurrentDirectory(); } else { - return underlying.getCurrentDirectory(); + return underlyingShim.getCurrentDirectory(); } }; wrapper.resolvePath = recordReplay(wrapper.resolvePath, underlying)( - path => callAndRecord(underlying.resolvePath(path), recordLog.pathsResolved, { path }), + path => callAndRecord(underlyingShim.resolvePath(path), recordLog.pathsResolved, { path }), memoize(path => findResultByFields(replayLog.pathsResolved, { path }, !ts.isRootedDiskPath(ts.normalizeSlashes(path)) && replayLog.currentDirectory ? replayLog.currentDirectory + "/" + path : ts.normalizeSlashes(path)))); wrapper.readFile = recordReplay(wrapper.readFile, underlying)( path => { - const result = underlying.readFile(path); + const result = underlyingShim.readFile(path); const logEntry = { path, codepage: 0, result: { contents: result, codepage: 0 } }; recordLog.filesRead.push(logEntry); return result; @@ -226,14 +228,14 @@ namespace Playback { (path, extension, exclude) => findResultByPath(wrapper, replayLog.directoriesRead.filter(d => d.extension === extension && ts.arrayIsEqualTo(d.exclude, exclude)), path)); wrapper.writeFile = recordReplay(wrapper.writeFile, underlying)( - (path, contents) => callAndRecord(underlying.writeFile(path, contents), recordLog.filesWritten, { path, contents, bom: false }), - (path, contents) => noOpReplay("writeFile")); + (path: string, contents: string) => callAndRecord(underlyingShim.writeFile(path, contents), recordLog.filesWritten, { path, contents, bom: false }), + (path: string, contents: string) => noOpReplay("writeFile")); wrapper.exit = (exitCode) => { if (recordLog !== undefined) { wrapper.endRecord(); } - underlying.exit(exitCode); + underlyingShim.exit(exitCode); }; } diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index e2ec5cc159f8f..5516b18e0de3d 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -1834,7 +1834,7 @@ namespace ts.server { if (!rangeEnd) { rangeEnd = this.root.charCount(); } - const walkFns = { + const walkFns: ILineIndexWalker = { goSubtree: true, done: false, leaf: function (relativeStart: number, relativeLength: number, ll: LineLeaf) { diff --git a/src/server/node.d.ts b/src/server/node.d.ts index 0bde0bb6602cc..8e4d8c28e9b9d 100644 --- a/src/server/node.d.ts +++ b/src/server/node.d.ts @@ -68,7 +68,7 @@ interface BufferConstructor { new (array: any[]): Buffer; prototype: Buffer; isBuffer(obj: any): boolean; - byteLength(string: string, encoding?: string): number; + byteLength: (string: string, encoding?: string) => number; concat(list: Buffer[], totalLength?: number): Buffer; } declare var Buffer: BufferConstructor; @@ -190,7 +190,7 @@ declare namespace NodeJS { nextTick(callback: Function): void; umask(mask?: number): number; uptime(): number; - hrtime(time?: number[]): number[]; + hrtime: (time?: number[]) => number[]; // Worker send? (message: any, sendHandle?: any): void; diff --git a/src/services/formatting/ruleOperationContext.ts b/src/services/formatting/ruleOperationContext.ts index 47330faa0dda0..3108095e8e6c6 100644 --- a/src/services/formatting/ruleOperationContext.ts +++ b/src/services/formatting/ruleOperationContext.ts @@ -6,8 +6,8 @@ namespace ts.formatting { export class RuleOperationContext { private customContextChecks: { (context: FormattingContext): boolean; }[]; - constructor(...funcs: { (context: FormattingContext): boolean; }[]) { - this.customContextChecks = funcs; + constructor(...funcs: { (this: typeof Rules, context: FormattingContext): boolean; }[]) { + this.customContextChecks = <{ (this: any, context: FormattingContext): boolean }[]>funcs; } static Any: RuleOperationContext = new RuleOperationContext(); diff --git a/src/services/utilities.ts b/src/services/utilities.ts index afdc85fffd805..0363e45a64aee 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -769,7 +769,7 @@ namespace ts { * The default is CRLF. */ export function getNewLineOrDefaultFromHost(host: LanguageServiceHost | LanguageServiceShimHost) { - return host.getNewLine ? host.getNewLine() : carriageReturnLineFeed; + return (host).getNewLine ? (host).getNewLine() : carriageReturnLineFeed; } export function lineBreakPart() { From 22e571f1e9a0250e406734f479d0f1a91fca4347 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 29 Jan 2016 14:44:20 -0800 Subject: [PATCH 06/41] Add services support for this types. --- src/services/services.ts | 27 ++++++++++++++++++++------- src/services/signatureHelp.ts | 2 +- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/services/services.ts b/src/services/services.ts index cb57d415c66a4..1a43f9a744b84 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -19,15 +19,15 @@ namespace ts { getChildCount(sourceFile?: SourceFile): number; getChildAt(index: number, sourceFile?: SourceFile): Node; getChildren(sourceFile?: SourceFile): Node[]; - getStart(sourceFile?: SourceFile): number; + getStart(this: Node, sourceFile?: SourceFile): number; getFullStart(): number; - getEnd(): number; + getEnd(this: Node): number; getWidth(sourceFile?: SourceFile): number; getFullWidth(): number; getLeadingTriviaWidth(sourceFile?: SourceFile): number; getFullText(sourceFile?: SourceFile): string; getText(sourceFile?: SourceFile): string; - getFirstToken(sourceFile?: SourceFile): Node; + getFirstToken(this: Node, sourceFile?: SourceFile): Node; getLastToken(sourceFile?: SourceFile): Node; } @@ -740,6 +740,7 @@ namespace ts { declaration: SignatureDeclaration; typeParameters: TypeParameter[]; parameters: Symbol[]; + thisType: Type; resolvedReturnType: Type; minArgumentCount: number; hasRestParameter: boolean; @@ -4021,6 +4022,9 @@ namespace ts { if (typeChecker.isArgumentsSymbol(symbol)) { return ScriptElementKind.localVariableElement; } + if (location.kind === SyntaxKind.ThisKeyword && isExpression(location)) { + return ScriptElementKind.parameterElement; + } if (flags & SymbolFlags.Variable) { if (isFirstDeclarationOfSymbolParameter(symbol)) { return ScriptElementKind.parameterElement; @@ -4083,6 +4087,7 @@ namespace ts { const symbolFlags = symbol.flags; let symbolKind = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, symbolFlags, location); let hasAddedSymbolInfo: boolean; + const isThisExpression: boolean = location.kind === SyntaxKind.ThisKeyword && isExpression(location); let type: Type; // Class at constructor site need to be shown as constructor apart from property,method, vars @@ -4093,7 +4098,7 @@ namespace ts { } let signature: Signature; - type = typeChecker.getTypeOfSymbolAtLocation(symbol, location); + type = isThisExpression ? typeChecker.getTypeAtLocation(location) : typeChecker.getTypeOfSymbolAtLocation(symbol, location); if (type) { if (location.parent && location.parent.kind === SyntaxKind.PropertyAccessExpression) { const right = (location.parent).name; @@ -4204,7 +4209,7 @@ namespace ts { } } } - if (symbolFlags & SymbolFlags.Class && !hasAddedSymbolInfo) { + if (symbolFlags & SymbolFlags.Class && !hasAddedSymbolInfo && !isThisExpression) { if (getDeclarationOfKind(symbol, SyntaxKind.ClassExpression)) { // Special case for class expressions because we would like to indicate that // the class name is local to the class body (similar to function expression) @@ -4346,11 +4351,19 @@ namespace ts { if (!hasAddedSymbolInfo) { if (symbolKind !== ScriptElementKind.unknown) { if (type) { - addPrefixForAnyFunctionOrVar(symbol, symbolKind); + if (isThisExpression) { + addNewLineIfDisplayPartsExist(); + displayParts.push(keywordPart(SyntaxKind.ThisKeyword)); + } + else { + addPrefixForAnyFunctionOrVar(symbol, symbolKind); + } + // For properties, variables and local vars: show the type if (symbolKind === ScriptElementKind.memberVariableElement || symbolFlags & SymbolFlags.Variable || - symbolKind === ScriptElementKind.localVariableElement) { + symbolKind === ScriptElementKind.localVariableElement || + isThisExpression) { displayParts.push(punctuationPart(SyntaxKind.ColonToken)); displayParts.push(spacePart()); // If the type is type parameter, format it specially diff --git a/src/services/signatureHelp.ts b/src/services/signatureHelp.ts index 02e36e185a56a..cdf0b997bcc4c 100644 --- a/src/services/signatureHelp.ts +++ b/src/services/signatureHelp.ts @@ -559,7 +559,7 @@ namespace ts.SignatureHelp { signatureHelpParameters = typeParameters && typeParameters.length > 0 ? map(typeParameters, createSignatureHelpParameterForTypeParameter) : emptyArray; suffixDisplayParts.push(punctuationPart(SyntaxKind.GreaterThanToken)); let parameterParts = mapToDisplayParts(writer => - typeChecker.getSymbolDisplayBuilder().buildDisplayForParametersAndDelimiters(candidateSignature.parameters, writer, invocation)); + typeChecker.getSymbolDisplayBuilder().buildDisplayForParametersAndDelimiters(candidateSignature.thisType, candidateSignature.parameters, writer, invocation)); addRange(suffixDisplayParts, parameterParts); } else { From 5fe84781592a08b5294e01a2fbf42d1def07111d Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 29 Jan 2016 14:46:01 -0800 Subject: [PATCH 07/41] Add overloads for Function.apply/call/bind The new overloads use this types to specify the return type of these functions as well as the type of `thisArg`. --- src/lib/core.d.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/lib/core.d.ts b/src/lib/core.d.ts index 31cf0ca31369d..fe2fd6b79f627 100644 --- a/src/lib/core.d.ts +++ b/src/lib/core.d.ts @@ -215,14 +215,16 @@ interface Function { * @param thisArg The object to be used as the this object. * @param argArray A set of arguments to be passed to the function. */ - apply(thisArg: any, argArray?: any): any; + apply(this: (this: T, ...argArray: any[]) => U, thisArg: T, argArray?: any): U; + apply(this: Function, thisArg: any, argArray?: any): any; /** * Calls a method of an object, substituting another object for the current object. * @param thisArg The object to be used as the current object. * @param argArray A list of arguments to be passed to the method. */ - call(thisArg: any, ...argArray: any[]): any; + call(this: (this: T, ...argArray: any[]) => U, thisArg: T, ...argArray: any[]): U; + call(this: Function, thisArg: any, ...argArray: any[]): any; /** * For a given function, creates a bound function that has the same body as the original function. @@ -230,7 +232,8 @@ interface Function { * @param thisArg An object to which the this keyword can refer inside the new function. * @param argArray A list of arguments to be passed to the new function. */ - bind(thisArg: any, ...argArray: any[]): any; + bind(this: (this: T, ...argArray: any[]) => U, thisArg: T, ...argArray: any[]): (...argArray: any[]) => U; + bind(this: Function, thisArg: any, ...argArray: any[]): any; prototype: any; readonly length: number; From 04e7d811054f712276264f87a7574ba2796cd4bd Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 29 Jan 2016 14:49:52 -0800 Subject: [PATCH 08/41] Add tests and baselines for this-function types. --- .../looseThisTypeInFunctions.errors.txt | 48 + .../reference/looseThisTypeInFunctions.js | 68 ++ .../reference/thisTypeInFunctions.js | 407 +++++++ .../reference/thisTypeInFunctions.symbols | 862 ++++++++++++++ .../reference/thisTypeInFunctions.types | 1037 +++++++++++++++++ .../thisTypeInFunctionsNegative.errors.txt | 509 ++++++++ .../reference/thisTypeInFunctionsNegative.js | 386 ++++++ .../thisType/looseThisTypeInFunctions.ts | 34 + .../types/thisType/thisTypeInFunctions.ts | 209 ++++ .../thisType/thisTypeInFunctionsNegative.ts | 193 +++ .../fourslash/memberListOnExplicitThis.ts | 30 + 11 files changed, 3783 insertions(+) create mode 100644 tests/baselines/reference/looseThisTypeInFunctions.errors.txt create mode 100644 tests/baselines/reference/looseThisTypeInFunctions.js create mode 100644 tests/baselines/reference/thisTypeInFunctions.js create mode 100644 tests/baselines/reference/thisTypeInFunctions.symbols create mode 100644 tests/baselines/reference/thisTypeInFunctions.types create mode 100644 tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt create mode 100644 tests/baselines/reference/thisTypeInFunctionsNegative.js create mode 100644 tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts create mode 100644 tests/cases/conformance/types/thisType/thisTypeInFunctions.ts create mode 100644 tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts create mode 100644 tests/cases/fourslash/memberListOnExplicitThis.ts diff --git a/tests/baselines/reference/looseThisTypeInFunctions.errors.txt b/tests/baselines/reference/looseThisTypeInFunctions.errors.txt new file mode 100644 index 0000000000000..058a1555ed678 --- /dev/null +++ b/tests/baselines/reference/looseThisTypeInFunctions.errors.txt @@ -0,0 +1,48 @@ +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'. + 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 (2 errors) ==== + interface I { + explicitThis(this: this, m: number): number; + } + interface Unused { + implicitNoThis(m: number): number; + } + class C implements I { + n: number; + explicitThis(this: this, m: number): number { + return this.n + m; + } + implicitThis(m: number): number { + return this.n + m; + } + explicitVoid(this: void, m: number): number { + return m + 1; + } + } + let c = new C(); + c.explicitVoid = c.explicitThis; // error, 'void' is missing everything + ~~~~~~~~~~~~~~ +!!! error TS2322: Type '(this: C, m: number) => number' is not assignable to type '(m: number) => number'. +!!! 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 } + }; + let i: I = o; + let x = i.explicitThis; + let n = x(12); // callee:void doesn't match this:I + ~~~~~ +!!! error TS2345: Argument of type 'void' is not assignable to parameter of type 'I'. + let u: Unused; + let y = u.implicitNoThis; + n = y(12); // ok, callee:void matches this:any + 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; + \ No newline at end of file diff --git a/tests/baselines/reference/looseThisTypeInFunctions.js b/tests/baselines/reference/looseThisTypeInFunctions.js new file mode 100644 index 0000000000000..66677293c5b70 --- /dev/null +++ b/tests/baselines/reference/looseThisTypeInFunctions.js @@ -0,0 +1,68 @@ +//// [looseThisTypeInFunctions.ts] +interface I { + explicitThis(this: this, m: number): number; +} +interface Unused { + implicitNoThis(m: number): number; +} +class C implements I { + n: number; + explicitThis(this: this, m: number): number { + return this.n + m; + } + implicitThis(m: number): number { + return this.n + m; + } + explicitVoid(this: void, m: number): number { + return m + 1; + } +} +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 } +}; +let i: I = o; +let x = i.explicitThis; +let n = x(12); // callee:void doesn't match this:I +let u: Unused; +let y = u.implicitNoThis; +n = y(12); // ok, callee:void matches this:any +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; + + +//// [looseThisTypeInFunctions.js] +var C = (function () { + function C() { + } + C.prototype.explicitThis = function (m) { + return this.n + m; + }; + C.prototype.implicitThis = function (m) { + return this.n + m; + }; + C.prototype.explicitVoid = function (m) { + return m + 1; + }; + return C; +}()); +var c = new C(); +c.explicitVoid = c.explicitThis; // error, 'void' is missing everything +var o = { + explicitThis: function (m) { return m; }, + implicitThis: function (m) { return m; } +}; +var i = o; +var x = i.explicitThis; +var n = x(12); // callee:void doesn't match this:I +var u; +var y = u.implicitNoThis; +n = y(12); // ok, callee:void matches this:any +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; diff --git a/tests/baselines/reference/thisTypeInFunctions.js b/tests/baselines/reference/thisTypeInFunctions.js new file mode 100644 index 0000000000000..0798843fc44f5 --- /dev/null +++ b/tests/baselines/reference/thisTypeInFunctions.js @@ -0,0 +1,407 @@ +//// [thisTypeInFunctions.ts] +// body checking +class C { + n: number; + explicitThis(this: this, m: number): number { + return this.n + m; + } + implicitThis(m: number): number { + return this.n + m; + } + explicitC(this: C, m: number): number { + return this.n + m; + } + explicitProperty(this: {n: number}, m: number): number { + return this.n + m; + } + explicitVoid(this: void, m: number): number { + return m + 1; + } +} +class D extends C { } +class B { + n: number; +} +interface I { + a: number; + explicitVoid1(this: void): number; + explicitVoid2(this: void): number; + explicitStructural(this: {a: number}): number; + explicitInterface(this: I): number; + explicitThis(this: this): number; + implicitMethod(): number; + implicitFunction: () => number; +} +function explicitStructural(this: { y: number }, x: number): number { + return x + this.y; +} +function justThis(this: { y: number }): number { + return this.y; +} +function implicitThis(n: number): number { + return 12; +} +let impl: I = { + a: 12, + explicitVoid2: () => this.a, // ok, this: any because it refers to some outer object (window?) + explicitVoid1() { return 12; }, + explicitStructural() { + return this.a; + }, + explicitInterface() { + return this.a; + }, + explicitThis() { + return this.a; + }, + implicitMethod() { + return this.a; + }, + implicitFunction: () => this.a, // ok, this: any because it refers to some outer object (window?) +} +impl.explicitVoid1 = function () { return 12; }; +impl.explicitVoid2 = () => 12; +impl.explicitStructural = function() { return this.a; }; +impl.explicitInterface = function() { return this.a; }; +impl.explicitStructural = () => 12; +impl.explicitInterface = () => 12; +impl.explicitThis = function () { return this.a; }; +impl.implicitMethod = function () { return this.a; }; +impl.implicitMethod = () => 12; +impl.implicitFunction = () => this.a; // ok, this: any because it refers to some outer object (window?) +// parameter checking +let ok: {y: number, f: (this: { y: number }, x: number) => number} = { y: 12, f: explicitStructural }; +let implicitAnyOk: {notSpecified: number, f: (x: number) => number} = { notSpecified: 12, f: implicitThis }; +ok.f(13); +implicitThis(12); +implicitAnyOk.f(12); + +let c = new C(); +let d = new D(); +let ripped = c.explicitC; +c.explicitC(12); +c.explicitProperty(12); +c.explicitThis(12); +c.implicitThis(12); +d.explicitC(12); +d.explicitProperty(12); +d.explicitThis(12); +d.implicitThis(12); +let reconstructed: { + n: number, + explicitThis(this: C, m: number): number, // note: this: this is not allowed in an object literal type. + implicitThis(m: number): number, + explicitC(this: C, m: number): number, + explicitProperty: (this: {n : number}, m: number) => number, + explicitVoid(this: void, m: number): number, +} = { + n: 12, + explicitThis: c.explicitThis, + implicitThis: c.implicitThis, + explicitC: c.explicitC, + explicitProperty: c.explicitProperty, + explicitVoid: c.explicitVoid +}; +reconstructed.explicitProperty(11); +reconstructed.implicitThis(11); + +// assignment checking +let unboundToSpecified: (this: { y: number }, x: number) => number = x => x + this.y; // ok, this:any +let specifiedToSpecified: (this: {y: number}, x: number) => number = explicitStructural; +let anyToSpecified: (this: { y: number }, x: number) => number = function(x: number): number { return x + 12; }; + +let unspecifiedLambda: (x: number) => number = x => x + 12; +let specifiedLambda: (this: void, x: number) => number = x => x + 12; +let unspecifiedLambdaToSpecified: (this: {y: number}, x: number) => number = unspecifiedLambda; +let specifiedLambdaToSpecified: (this: {y: number}, x: number) => number = specifiedLambda; + + +let explicitCFunction: (this: C, m: number) => number; +let explicitPropertyFunction: (this: {n: number}, m: number) => number; +c.explicitC = explicitCFunction; +c.explicitC = function(this: C, m: number) { return this.n + m }; +c.explicitProperty = explicitPropertyFunction; +c.explicitProperty = function(this: {n: number}, m: number) { return this.n + m }; +c.explicitProperty = reconstructed.explicitProperty; + +// lambdas are assignable to anything +c.explicitC = m => m; +c.explicitThis = m => m; +c.explicitProperty = m => m; + +// this inside lambdas refer to outer scope +// the outer-scoped lambda at top-level is still just `any` +c.explicitC = m => m + this.n; +c.explicitThis = m => m + this.n; +c.explicitProperty = m => m + this.n; + +//NOTE: this=C here, I guess? +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.implicitThis = reconstructed.implicitThis; + +c.explicitC = function(this: B, m: number) { return this.n + m }; + +// this:void compatibility +c.explicitVoid = n => n; + +// class-based assignability +class Base1 { + x: number; + public implicit(): number { return this.x; } + explicit(this: Base1): number { return this.x; } + static implicitStatic(): number { return this.y; } + static explicitStatic(this: typeof Base1): number { return this.y; } + static y: number; + +} +class Derived1 extends Base1 { + y: number +} +class Base2 { + y: number + implicit(): number { return this.y; } + explicit(this: Base1): number { return this.x; } +} +class Derived2 extends Base2 { + x: number +} +let b1 = new Base1(); +let b2 = new Base2(); +let d1 = new Derived1(); +let d2 = new Derived2(); +d2.implicit = d1.implicit // ok, 'x' and 'y' in { x, y } (d assignable to f and vice versa) +d1.implicit = d2.implicit // ok, 'x' and 'y' in { x, y } (f assignable to d and vice versa) + +// bivariance-allowed cases +d1.implicit = b2.implicit // ok, 'y' in D: { x, y } (d assignable e) +d2.implicit = d1.explicit // ok, 'y' in { x, y } (c assignable to f) +b1.implicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) +b1.explicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) + +////// use this-type for construction with new //// +function InterfaceThis(this: I) { + this.a = 12; +} +function LiteralTypeThis(this: {x: string}) { + this.x = "ok"; +} +function AnyThis(this: any) { + this.x = "ok"; +} +let interfaceThis = new InterfaceThis(); +let literalTypeThis = new LiteralTypeThis(); +let anyThis = new AnyThis(); + +//// type parameter inference //// +declare var f: { + (this: void, x: number): number, + call(this: (...argArray: any[]) => U, ...argArray: any[]): U; +}; +let n: number = f.call(12); + +function missingTypeIsImplicitAny(this, a: number) { return a; } + +//// [thisTypeInFunctions.js] +var __extends = (this && this.__extends) || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +}; +var _this = this; +// body checking +var C = (function () { + function C() { + } + C.prototype.explicitThis = function (m) { + return this.n + m; + }; + C.prototype.implicitThis = function (m) { + return this.n + m; + }; + C.prototype.explicitC = function (m) { + return this.n + m; + }; + C.prototype.explicitProperty = function (m) { + return this.n + m; + }; + C.prototype.explicitVoid = function (m) { + return m + 1; + }; + return C; +}()); +var D = (function (_super) { + __extends(D, _super); + function D() { + _super.apply(this, arguments); + } + return D; +}(C)); +var B = (function () { + function B() { + } + return B; +}()); +function explicitStructural(x) { + return x + this.y; +} +function justThis() { + return this.y; +} +function implicitThis(n) { + return 12; +} +var impl = { + a: 12, + explicitVoid2: function () { return _this.a; }, + explicitVoid1: function () { return 12; }, + explicitStructural: function () { + return this.a; + }, + explicitInterface: function () { + return this.a; + }, + explicitThis: function () { + return this.a; + }, + implicitMethod: function () { + return this.a; + }, + implicitFunction: function () { return _this.a; } +}; +impl.explicitVoid1 = function () { return 12; }; +impl.explicitVoid2 = function () { return 12; }; +impl.explicitStructural = function () { return this.a; }; +impl.explicitInterface = function () { return this.a; }; +impl.explicitStructural = function () { return 12; }; +impl.explicitInterface = function () { return 12; }; +impl.explicitThis = function () { return this.a; }; +impl.implicitMethod = function () { return this.a; }; +impl.implicitMethod = function () { return 12; }; +impl.implicitFunction = function () { return _this.a; }; // ok, this: any because it refers to some outer object (window?) +// parameter checking +var ok = { y: 12, f: explicitStructural }; +var implicitAnyOk = { notSpecified: 12, f: implicitThis }; +ok.f(13); +implicitThis(12); +implicitAnyOk.f(12); +var c = new C(); +var d = new D(); +var ripped = c.explicitC; +c.explicitC(12); +c.explicitProperty(12); +c.explicitThis(12); +c.implicitThis(12); +d.explicitC(12); +d.explicitProperty(12); +d.explicitThis(12); +d.implicitThis(12); +var reconstructed = { + n: 12, + explicitThis: c.explicitThis, + implicitThis: c.implicitThis, + explicitC: c.explicitC, + explicitProperty: c.explicitProperty, + explicitVoid: c.explicitVoid +}; +reconstructed.explicitProperty(11); +reconstructed.implicitThis(11); +// assignment checking +var unboundToSpecified = function (x) { return x + _this.y; }; // ok, this:any +var specifiedToSpecified = explicitStructural; +var anyToSpecified = function (x) { return x + 12; }; +var unspecifiedLambda = function (x) { return x + 12; }; +var specifiedLambda = function (x) { return x + 12; }; +var unspecifiedLambdaToSpecified = unspecifiedLambda; +var specifiedLambdaToSpecified = specifiedLambda; +var explicitCFunction; +var explicitPropertyFunction; +c.explicitC = explicitCFunction; +c.explicitC = function (m) { return this.n + m; }; +c.explicitProperty = explicitPropertyFunction; +c.explicitProperty = function (m) { return this.n + m; }; +c.explicitProperty = reconstructed.explicitProperty; +// lambdas are assignable to anything +c.explicitC = function (m) { return m; }; +c.explicitThis = function (m) { return m; }; +c.explicitProperty = function (m) { return m; }; +// this inside lambdas refer to outer scope +// the outer-scoped lambda at top-level is still just `any` +c.explicitC = function (m) { return m + _this.n; }; +c.explicitThis = function (m) { return m + _this.n; }; +c.explicitProperty = function (m) { return m + _this.n; }; +//NOTE: this=C here, I guess? +c.explicitThis = explicitCFunction; +c.explicitThis = function (m) { return this.n + m; }; +// this:any compatibility +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 (m) { return this.n + m; }; +// this:void compatibility +c.explicitVoid = function (n) { return n; }; +// class-based assignability +var Base1 = (function () { + function Base1() { + } + Base1.prototype.implicit = function () { return this.x; }; + Base1.prototype.explicit = function () { return this.x; }; + Base1.implicitStatic = function () { return this.y; }; + Base1.explicitStatic = function () { return this.y; }; + return Base1; +}()); +var Derived1 = (function (_super) { + __extends(Derived1, _super); + function Derived1() { + _super.apply(this, arguments); + } + return Derived1; +}(Base1)); +var Base2 = (function () { + function Base2() { + } + Base2.prototype.implicit = function () { return this.y; }; + Base2.prototype.explicit = function () { return this.x; }; + return Base2; +}()); +var Derived2 = (function (_super) { + __extends(Derived2, _super); + function Derived2() { + _super.apply(this, arguments); + } + return Derived2; +}(Base2)); +var b1 = new Base1(); +var b2 = new Base2(); +var d1 = new Derived1(); +var d2 = new Derived2(); +d2.implicit = d1.implicit; // ok, 'x' and 'y' in { x, y } (d assignable to f and vice versa) +d1.implicit = d2.implicit; // ok, 'x' and 'y' in { x, y } (f assignable to d and vice versa) +// bivariance-allowed cases +d1.implicit = b2.implicit; // ok, 'y' in D: { x, y } (d assignable e) +d2.implicit = d1.explicit; // ok, 'y' in { x, y } (c assignable to f) +b1.implicit = d2.implicit; // ok, 'x' and 'y' not in C: { x } (c assignable to f) +b1.explicit = d2.implicit; // ok, 'x' and 'y' not in C: { x } (c assignable to f) +////// use this-type for construction with new //// +function InterfaceThis() { + this.a = 12; +} +function LiteralTypeThis() { + this.x = "ok"; +} +function AnyThis() { + this.x = "ok"; +} +var interfaceThis = new InterfaceThis(); +var literalTypeThis = new LiteralTypeThis(); +var anyThis = new AnyThis(); +var n = f.call(12); +function missingTypeIsImplicitAny(a) { return a; } diff --git a/tests/baselines/reference/thisTypeInFunctions.symbols b/tests/baselines/reference/thisTypeInFunctions.symbols new file mode 100644 index 0000000000000..1d9ebbd0cf4c2 --- /dev/null +++ b/tests/baselines/reference/thisTypeInFunctions.symbols @@ -0,0 +1,862 @@ +=== tests/cases/conformance/types/thisType/thisTypeInFunctions.ts === +// body checking +class C { +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) + + n: number; +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 1, 9)) + + explicitThis(this: this, m: number): number { +>explicitThis : Symbol(explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 3, 17)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 3, 28)) + + return this.n + m; +>this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 1, 9)) +>this : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 1, 9)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 3, 28)) + } + implicitThis(m: number): number { +>implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 6, 17)) + + return this.n + m; +>this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 1, 9)) +>this : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 1, 9)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 6, 17)) + } + explicitC(this: C, m: number): number { +>explicitC : Symbol(explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 9, 14)) +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 9, 22)) + + return this.n + m; +>this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 1, 9)) +>this : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 1, 9)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 9, 22)) + } + explicitProperty(this: {n: number}, m: number): number { +>explicitProperty : Symbol(explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 12, 21)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 12, 28)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 12, 39)) + + return this.n + m; +>this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 12, 28)) +>this : Symbol(, Decl(thisTypeInFunctions.ts, 12, 26)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 12, 28)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 12, 39)) + } + explicitVoid(this: void, m: number): number { +>explicitVoid : Symbol(explicitVoid, Decl(thisTypeInFunctions.ts, 14, 5)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 15, 17)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 15, 28)) + + return m + 1; +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 15, 28)) + } +} +class D extends C { } +>D : Symbol(D, Decl(thisTypeInFunctions.ts, 18, 1)) +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) + +class B { +>B : Symbol(B, Decl(thisTypeInFunctions.ts, 19, 21)) + + n: number; +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 20, 9)) +} +interface I { +>I : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) + + a: number; +>a : Symbol(a, Decl(thisTypeInFunctions.ts, 23, 13)) + + explicitVoid1(this: void): number; +>explicitVoid1 : Symbol(explicitVoid1, Decl(thisTypeInFunctions.ts, 24, 14)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 25, 18)) + + explicitVoid2(this: void): number; +>explicitVoid2 : Symbol(explicitVoid2, Decl(thisTypeInFunctions.ts, 25, 38)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 26, 18)) + + explicitStructural(this: {a: number}): number; +>explicitStructural : Symbol(explicitStructural, Decl(thisTypeInFunctions.ts, 26, 38)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 27, 23)) +>a : Symbol(a, Decl(thisTypeInFunctions.ts, 27, 30)) + + explicitInterface(this: I): number; +>explicitInterface : Symbol(explicitInterface, Decl(thisTypeInFunctions.ts, 27, 50)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 28, 22)) +>I : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) + + explicitThis(this: this): number; +>explicitThis : Symbol(explicitThis, Decl(thisTypeInFunctions.ts, 28, 39)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 29, 17)) + + implicitMethod(): number; +>implicitMethod : Symbol(implicitMethod, Decl(thisTypeInFunctions.ts, 29, 37)) + + implicitFunction: () => number; +>implicitFunction : Symbol(implicitFunction, Decl(thisTypeInFunctions.ts, 30, 29)) +} +function explicitStructural(this: { y: number }, x: number): number { +>explicitStructural : Symbol(explicitStructural, Decl(thisTypeInFunctions.ts, 32, 1)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 33, 28)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 33, 35)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 33, 48)) + + return x + this.y; +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 33, 48)) +>this.y : Symbol(y, Decl(thisTypeInFunctions.ts, 33, 35)) +>this : Symbol(, Decl(thisTypeInFunctions.ts, 33, 33)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 33, 35)) +} +function justThis(this: { y: number }): number { +>justThis : Symbol(justThis, Decl(thisTypeInFunctions.ts, 35, 1)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 36, 18)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 36, 25)) + + return this.y; +>this.y : Symbol(y, Decl(thisTypeInFunctions.ts, 36, 25)) +>this : Symbol(, Decl(thisTypeInFunctions.ts, 36, 23)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 36, 25)) +} +function implicitThis(n: number): number { +>implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 38, 1)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 39, 22)) + + return 12; +} +let impl: I = { +>impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) +>I : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) + + a: 12, +>a : Symbol(a, Decl(thisTypeInFunctions.ts, 42, 15)) + + explicitVoid2: () => this.a, // ok, this: any because it refers to some outer object (window?) +>explicitVoid2 : Symbol(explicitVoid2, Decl(thisTypeInFunctions.ts, 43, 10)) + + explicitVoid1() { return 12; }, +>explicitVoid1 : Symbol(explicitVoid1, Decl(thisTypeInFunctions.ts, 44, 32)) + + explicitStructural() { +>explicitStructural : Symbol(explicitStructural, Decl(thisTypeInFunctions.ts, 45, 35)) + + return this.a; +>this.a : Symbol(a, Decl(thisTypeInFunctions.ts, 27, 30)) +>this : Symbol(, Decl(thisTypeInFunctions.ts, 27, 28)) +>a : Symbol(a, Decl(thisTypeInFunctions.ts, 27, 30)) + + }, + explicitInterface() { +>explicitInterface : Symbol(explicitInterface, Decl(thisTypeInFunctions.ts, 48, 6)) + + return this.a; +>this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) +>this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) +>a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) + + }, + explicitThis() { +>explicitThis : Symbol(explicitThis, Decl(thisTypeInFunctions.ts, 51, 6)) + + return this.a; +>this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) +>this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) +>a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) + + }, + implicitMethod() { +>implicitMethod : Symbol(implicitMethod, Decl(thisTypeInFunctions.ts, 54, 6)) + + return this.a; +>this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) +>this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) +>a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) + + }, + implicitFunction: () => this.a, // ok, this: any because it refers to some outer object (window?) +>implicitFunction : Symbol(implicitFunction, Decl(thisTypeInFunctions.ts, 57, 6)) +} +impl.explicitVoid1 = function () { return 12; }; +>impl.explicitVoid1 : Symbol(I.explicitVoid1, Decl(thisTypeInFunctions.ts, 24, 14)) +>impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) +>explicitVoid1 : Symbol(I.explicitVoid1, Decl(thisTypeInFunctions.ts, 24, 14)) + +impl.explicitVoid2 = () => 12; +>impl.explicitVoid2 : Symbol(I.explicitVoid2, Decl(thisTypeInFunctions.ts, 25, 38)) +>impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) +>explicitVoid2 : Symbol(I.explicitVoid2, Decl(thisTypeInFunctions.ts, 25, 38)) + +impl.explicitStructural = function() { return this.a; }; +>impl.explicitStructural : Symbol(I.explicitStructural, Decl(thisTypeInFunctions.ts, 26, 38)) +>impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) +>explicitStructural : Symbol(I.explicitStructural, Decl(thisTypeInFunctions.ts, 26, 38)) +>this.a : Symbol(a, Decl(thisTypeInFunctions.ts, 27, 30)) +>this : Symbol(, Decl(thisTypeInFunctions.ts, 27, 28)) +>a : Symbol(a, Decl(thisTypeInFunctions.ts, 27, 30)) + +impl.explicitInterface = function() { return this.a; }; +>impl.explicitInterface : Symbol(I.explicitInterface, Decl(thisTypeInFunctions.ts, 27, 50)) +>impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) +>explicitInterface : Symbol(I.explicitInterface, Decl(thisTypeInFunctions.ts, 27, 50)) +>this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) +>this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) +>a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) + +impl.explicitStructural = () => 12; +>impl.explicitStructural : Symbol(I.explicitStructural, Decl(thisTypeInFunctions.ts, 26, 38)) +>impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) +>explicitStructural : Symbol(I.explicitStructural, Decl(thisTypeInFunctions.ts, 26, 38)) + +impl.explicitInterface = () => 12; +>impl.explicitInterface : Symbol(I.explicitInterface, Decl(thisTypeInFunctions.ts, 27, 50)) +>impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) +>explicitInterface : Symbol(I.explicitInterface, Decl(thisTypeInFunctions.ts, 27, 50)) + +impl.explicitThis = function () { return this.a; }; +>impl.explicitThis : Symbol(I.explicitThis, Decl(thisTypeInFunctions.ts, 28, 39)) +>impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) +>explicitThis : Symbol(I.explicitThis, Decl(thisTypeInFunctions.ts, 28, 39)) +>this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) +>this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) +>a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) + +impl.implicitMethod = function () { return this.a; }; +>impl.implicitMethod : Symbol(I.implicitMethod, Decl(thisTypeInFunctions.ts, 29, 37)) +>impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) +>implicitMethod : Symbol(I.implicitMethod, Decl(thisTypeInFunctions.ts, 29, 37)) +>this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) +>this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) +>a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) + +impl.implicitMethod = () => 12; +>impl.implicitMethod : Symbol(I.implicitMethod, Decl(thisTypeInFunctions.ts, 29, 37)) +>impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) +>implicitMethod : Symbol(I.implicitMethod, Decl(thisTypeInFunctions.ts, 29, 37)) + +impl.implicitFunction = () => this.a; // ok, this: any because it refers to some outer object (window?) +>impl.implicitFunction : Symbol(I.implicitFunction, Decl(thisTypeInFunctions.ts, 30, 29)) +>impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) +>implicitFunction : Symbol(I.implicitFunction, Decl(thisTypeInFunctions.ts, 30, 29)) + +// parameter checking +let ok: {y: number, f: (this: { y: number }, x: number) => number} = { y: 12, f: explicitStructural }; +>ok : Symbol(ok, Decl(thisTypeInFunctions.ts, 71, 3)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 71, 9)) +>f : Symbol(f, Decl(thisTypeInFunctions.ts, 71, 19)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 71, 24)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 71, 31)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 71, 44)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 71, 70)) +>f : Symbol(f, Decl(thisTypeInFunctions.ts, 71, 77)) +>explicitStructural : Symbol(explicitStructural, Decl(thisTypeInFunctions.ts, 32, 1)) + +let implicitAnyOk: {notSpecified: number, f: (x: number) => number} = { notSpecified: 12, f: implicitThis }; +>implicitAnyOk : Symbol(implicitAnyOk, Decl(thisTypeInFunctions.ts, 72, 3)) +>notSpecified : Symbol(notSpecified, Decl(thisTypeInFunctions.ts, 72, 20)) +>f : Symbol(f, Decl(thisTypeInFunctions.ts, 72, 41)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 72, 46)) +>notSpecified : Symbol(notSpecified, Decl(thisTypeInFunctions.ts, 72, 71)) +>f : Symbol(f, Decl(thisTypeInFunctions.ts, 72, 89)) +>implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 38, 1)) + +ok.f(13); +>ok.f : Symbol(f, Decl(thisTypeInFunctions.ts, 71, 19)) +>ok : Symbol(ok, Decl(thisTypeInFunctions.ts, 71, 3)) +>f : Symbol(f, Decl(thisTypeInFunctions.ts, 71, 19)) + +implicitThis(12); +>implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 38, 1)) + +implicitAnyOk.f(12); +>implicitAnyOk.f : Symbol(f, Decl(thisTypeInFunctions.ts, 72, 41)) +>implicitAnyOk : Symbol(implicitAnyOk, Decl(thisTypeInFunctions.ts, 72, 3)) +>f : Symbol(f, Decl(thisTypeInFunctions.ts, 72, 41)) + +let c = new C(); +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) + +let d = new D(); +>d : Symbol(d, Decl(thisTypeInFunctions.ts, 78, 3)) +>D : Symbol(D, Decl(thisTypeInFunctions.ts, 18, 1)) + +let ripped = c.explicitC; +>ripped : Symbol(ripped, Decl(thisTypeInFunctions.ts, 79, 3)) +>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)) + +c.explicitC(12); +>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)) + +c.explicitProperty(12); +>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)) + +c.explicitThis(12); +>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)) + +c.implicitThis(12); +>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)) + +d.explicitC(12); +>d.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>d : Symbol(d, Decl(thisTypeInFunctions.ts, 78, 3)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) + +d.explicitProperty(12); +>d.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>d : Symbol(d, Decl(thisTypeInFunctions.ts, 78, 3)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) + +d.explicitThis(12); +>d.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>d : Symbol(d, Decl(thisTypeInFunctions.ts, 78, 3)) +>explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) + +d.implicitThis(12); +>d.implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) +>d : Symbol(d, Decl(thisTypeInFunctions.ts, 78, 3)) +>implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) + +let reconstructed: { +>reconstructed : Symbol(reconstructed, Decl(thisTypeInFunctions.ts, 88, 3)) + + n: number, +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 88, 20)) + + explicitThis(this: C, m: number): number, // note: this: this is not allowed in an object literal type. +>explicitThis : Symbol(explicitThis, Decl(thisTypeInFunctions.ts, 89, 14)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 90, 17)) +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 90, 25)) + + implicitThis(m: number): number, +>implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 90, 45)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 91, 17)) + + explicitC(this: C, m: number): number, +>explicitC : Symbol(explicitC, Decl(thisTypeInFunctions.ts, 91, 36)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 92, 14)) +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 92, 22)) + + explicitProperty: (this: {n : number}, m: number) => number, +>explicitProperty : Symbol(explicitProperty, Decl(thisTypeInFunctions.ts, 92, 42)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 93, 23)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 93, 30)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 93, 42)) + + explicitVoid(this: void, m: number): number, +>explicitVoid : Symbol(explicitVoid, Decl(thisTypeInFunctions.ts, 93, 64)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 94, 17)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 94, 28)) + +} = { + n: 12, +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 95, 5)) + + explicitThis: c.explicitThis, +>explicitThis : Symbol(explicitThis, Decl(thisTypeInFunctions.ts, 96, 10)) +>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)) + + implicitThis: c.implicitThis, +>implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 97, 33)) +>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)) + + explicitC: c.explicitC, +>explicitC : Symbol(explicitC, Decl(thisTypeInFunctions.ts, 98, 33)) +>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)) + + explicitProperty: c.explicitProperty, +>explicitProperty : Symbol(explicitProperty, Decl(thisTypeInFunctions.ts, 99, 27)) +>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)) + + explicitVoid: c.explicitVoid +>explicitVoid : Symbol(explicitVoid, Decl(thisTypeInFunctions.ts, 100, 41)) +>c.explicitVoid : Symbol(C.explicitVoid, Decl(thisTypeInFunctions.ts, 14, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitVoid : Symbol(C.explicitVoid, Decl(thisTypeInFunctions.ts, 14, 5)) + +}; +reconstructed.explicitProperty(11); +>reconstructed.explicitProperty : Symbol(explicitProperty, Decl(thisTypeInFunctions.ts, 92, 42)) +>reconstructed : Symbol(reconstructed, Decl(thisTypeInFunctions.ts, 88, 3)) +>explicitProperty : Symbol(explicitProperty, Decl(thisTypeInFunctions.ts, 92, 42)) + +reconstructed.implicitThis(11); +>reconstructed.implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 90, 45)) +>reconstructed : Symbol(reconstructed, Decl(thisTypeInFunctions.ts, 88, 3)) +>implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 90, 45)) + +// assignment checking +let unboundToSpecified: (this: { y: number }, x: number) => number = x => x + this.y; // ok, this:any +>unboundToSpecified : Symbol(unboundToSpecified, Decl(thisTypeInFunctions.ts, 107, 3)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 107, 25)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 107, 32)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 107, 45)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 107, 68)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 107, 68)) + +let specifiedToSpecified: (this: {y: number}, x: number) => number = explicitStructural; +>specifiedToSpecified : Symbol(specifiedToSpecified, Decl(thisTypeInFunctions.ts, 108, 3)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 108, 27)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 108, 34)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 108, 45)) +>explicitStructural : Symbol(explicitStructural, Decl(thisTypeInFunctions.ts, 32, 1)) + +let anyToSpecified: (this: { y: number }, x: number) => number = function(x: number): number { return x + 12; }; +>anyToSpecified : Symbol(anyToSpecified, Decl(thisTypeInFunctions.ts, 109, 3)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 109, 21)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 109, 28)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 109, 41)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 109, 74)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 109, 74)) + +let unspecifiedLambda: (x: number) => number = x => x + 12; +>unspecifiedLambda : Symbol(unspecifiedLambda, Decl(thisTypeInFunctions.ts, 111, 3)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 111, 24)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 111, 46)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 111, 46)) + +let specifiedLambda: (this: void, x: number) => number = x => x + 12; +>specifiedLambda : Symbol(specifiedLambda, Decl(thisTypeInFunctions.ts, 112, 3)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 112, 22)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 112, 33)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 112, 56)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 112, 56)) + +let unspecifiedLambdaToSpecified: (this: {y: number}, x: number) => number = unspecifiedLambda; +>unspecifiedLambdaToSpecified : Symbol(unspecifiedLambdaToSpecified, Decl(thisTypeInFunctions.ts, 113, 3)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 113, 35)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 113, 42)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 113, 53)) +>unspecifiedLambda : Symbol(unspecifiedLambda, Decl(thisTypeInFunctions.ts, 111, 3)) + +let specifiedLambdaToSpecified: (this: {y: number}, x: number) => number = specifiedLambda; +>specifiedLambdaToSpecified : Symbol(specifiedLambdaToSpecified, Decl(thisTypeInFunctions.ts, 114, 3)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 114, 33)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 114, 40)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 114, 51)) +>specifiedLambda : Symbol(specifiedLambda, Decl(thisTypeInFunctions.ts, 112, 3)) + + +let explicitCFunction: (this: C, m: number) => number; +>explicitCFunction : Symbol(explicitCFunction, Decl(thisTypeInFunctions.ts, 117, 3)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 117, 24)) +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 117, 32)) + +let explicitPropertyFunction: (this: {n: number}, m: number) => number; +>explicitPropertyFunction : Symbol(explicitPropertyFunction, Decl(thisTypeInFunctions.ts, 118, 3)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 118, 31)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 118, 38)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 118, 49)) + +c.explicitC = explicitCFunction; +>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)) +>explicitCFunction : Symbol(explicitCFunction, Decl(thisTypeInFunctions.ts, 117, 3)) + +c.explicitC = function(this: C, m: number) { 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)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 120, 23)) +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 120, 31)) +>this.n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) +>this : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 120, 31)) + +c.explicitProperty = explicitPropertyFunction; +>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)) +>explicitPropertyFunction : Symbol(explicitPropertyFunction, Decl(thisTypeInFunctions.ts, 118, 3)) + +c.explicitProperty = function(this: {n: number}, m: number) { 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)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 122, 30)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 122, 37)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 122, 48)) +>this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 122, 37)) +>this : Symbol(, Decl(thisTypeInFunctions.ts, 122, 35)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 122, 37)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 122, 48)) + +c.explicitProperty = reconstructed.explicitProperty; +>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)) +>reconstructed.explicitProperty : Symbol(explicitProperty, Decl(thisTypeInFunctions.ts, 92, 42)) +>reconstructed : Symbol(reconstructed, Decl(thisTypeInFunctions.ts, 88, 3)) +>explicitProperty : Symbol(explicitProperty, Decl(thisTypeInFunctions.ts, 92, 42)) + +// lambdas are assignable to anything +c.explicitC = m => 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)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 126, 13)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 126, 13)) + +c.explicitThis = m => 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)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 127, 16)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 127, 16)) + +c.explicitProperty = m => 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)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 128, 20)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 128, 20)) + +// this inside lambdas refer to outer scope +// the outer-scoped lambda at top-level is still just `any` +c.explicitC = m => m + this.n; +>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)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 132, 13)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 132, 13)) + +c.explicitThis = m => m + this.n; +>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)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 133, 16)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 133, 16)) + +c.explicitProperty = m => m + this.n; +>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)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 134, 20)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 134, 20)) + +//NOTE: this=C here, I guess? +c.explicitThis = explicitCFunction; +>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)) +>explicitCFunction : Symbol(explicitCFunction, Decl(thisTypeInFunctions.ts, 117, 3)) + +c.explicitThis = function(this: C, m: number) { 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)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 138, 26)) +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 138, 34)) +>this.n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) +>this : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 138, 34)) + +// this:any compatibility +c.explicitC = function(m: number) { 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)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 141, 23)) +>this.n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) +>this : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>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 : 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)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 142, 30)) +>this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 12, 28)) +>this : Symbol(, Decl(thisTypeInFunctions.ts, 12, 26)) +>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 : 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)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 143, 26)) +>this.n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) +>this : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>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 : 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)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 144, 26)) +>this.n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) +>this : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 144, 26)) + +c.implicitThis = reconstructed.implicitThis; +>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)) +>reconstructed.implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 90, 45)) +>reconstructed : Symbol(reconstructed, Decl(thisTypeInFunctions.ts, 88, 3)) +>implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 90, 45)) + +c.explicitC = function(this: B, m: number) { 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)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 147, 23)) +>B : Symbol(B, Decl(thisTypeInFunctions.ts, 19, 21)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 147, 31)) +>this.n : Symbol(B.n, Decl(thisTypeInFunctions.ts, 20, 9)) +>this : Symbol(B, Decl(thisTypeInFunctions.ts, 19, 21)) +>n : Symbol(B.n, Decl(thisTypeInFunctions.ts, 20, 9)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 147, 31)) + +// this:void compatibility +c.explicitVoid = n => n; +>c.explicitVoid : Symbol(C.explicitVoid, Decl(thisTypeInFunctions.ts, 14, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitVoid : Symbol(C.explicitVoid, Decl(thisTypeInFunctions.ts, 14, 5)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 150, 16)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 150, 16)) + +// class-based assignability +class Base1 { +>Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) + + x: number; +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 153, 13)) + + public implicit(): number { return this.x; } +>implicit : Symbol(implicit, Decl(thisTypeInFunctions.ts, 154, 14)) +>this.x : Symbol(x, Decl(thisTypeInFunctions.ts, 153, 13)) +>this : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 153, 13)) + + explicit(this: Base1): number { return this.x; } +>explicit : Symbol(explicit, Decl(thisTypeInFunctions.ts, 155, 48)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 156, 13)) +>Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) +>this.x : Symbol(x, Decl(thisTypeInFunctions.ts, 153, 13)) +>this : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 153, 13)) + + static implicitStatic(): number { return this.y; } +>implicitStatic : Symbol(Base1.implicitStatic, Decl(thisTypeInFunctions.ts, 156, 52)) +>this.y : Symbol(Base1.y, Decl(thisTypeInFunctions.ts, 158, 72)) +>this : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) +>y : Symbol(Base1.y, Decl(thisTypeInFunctions.ts, 158, 72)) + + static explicitStatic(this: typeof Base1): number { return this.y; } +>explicitStatic : Symbol(Base1.explicitStatic, Decl(thisTypeInFunctions.ts, 157, 54)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 158, 26)) +>Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) +>this.y : Symbol(Base1.y, Decl(thisTypeInFunctions.ts, 158, 72)) +>this : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) +>y : Symbol(Base1.y, Decl(thisTypeInFunctions.ts, 158, 72)) + + static y: number; +>y : Symbol(Base1.y, Decl(thisTypeInFunctions.ts, 158, 72)) + +} +class Derived1 extends Base1 { +>Derived1 : Symbol(Derived1, Decl(thisTypeInFunctions.ts, 161, 1)) +>Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) + + y: number +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 162, 30)) +} +class Base2 { +>Base2 : Symbol(Base2, Decl(thisTypeInFunctions.ts, 164, 1)) + + y: number +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 165, 13)) + + implicit(): number { return this.y; } +>implicit : Symbol(implicit, Decl(thisTypeInFunctions.ts, 166, 13)) +>this.y : Symbol(y, Decl(thisTypeInFunctions.ts, 165, 13)) +>this : Symbol(Base2, Decl(thisTypeInFunctions.ts, 164, 1)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 165, 13)) + + explicit(this: Base1): number { return this.x; } +>explicit : Symbol(explicit, Decl(thisTypeInFunctions.ts, 167, 41)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 168, 13)) +>Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) +>this.x : Symbol(Base1.x, Decl(thisTypeInFunctions.ts, 153, 13)) +>this : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) +>x : Symbol(Base1.x, Decl(thisTypeInFunctions.ts, 153, 13)) +} +class Derived2 extends Base2 { +>Derived2 : Symbol(Derived2, Decl(thisTypeInFunctions.ts, 169, 1)) +>Base2 : Symbol(Base2, Decl(thisTypeInFunctions.ts, 164, 1)) + + x: number +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 170, 30)) +} +let b1 = new Base1(); +>b1 : Symbol(b1, Decl(thisTypeInFunctions.ts, 173, 3)) +>Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) + +let b2 = new Base2(); +>b2 : Symbol(b2, Decl(thisTypeInFunctions.ts, 174, 3)) +>Base2 : Symbol(Base2, Decl(thisTypeInFunctions.ts, 164, 1)) + +let d1 = new Derived1(); +>d1 : Symbol(d1, Decl(thisTypeInFunctions.ts, 175, 3)) +>Derived1 : Symbol(Derived1, Decl(thisTypeInFunctions.ts, 161, 1)) + +let d2 = new Derived2(); +>d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 176, 3)) +>Derived2 : Symbol(Derived2, Decl(thisTypeInFunctions.ts, 169, 1)) + +d2.implicit = d1.implicit // ok, 'x' and 'y' in { x, y } (d assignable to f and vice versa) +>d2.implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) +>d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 176, 3)) +>implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) +>d1.implicit : Symbol(Base1.implicit, Decl(thisTypeInFunctions.ts, 154, 14)) +>d1 : Symbol(d1, Decl(thisTypeInFunctions.ts, 175, 3)) +>implicit : Symbol(Base1.implicit, Decl(thisTypeInFunctions.ts, 154, 14)) + +d1.implicit = d2.implicit // ok, 'x' and 'y' in { x, y } (f assignable to d and vice versa) +>d1.implicit : Symbol(Base1.implicit, Decl(thisTypeInFunctions.ts, 154, 14)) +>d1 : Symbol(d1, Decl(thisTypeInFunctions.ts, 175, 3)) +>implicit : Symbol(Base1.implicit, Decl(thisTypeInFunctions.ts, 154, 14)) +>d2.implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) +>d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 176, 3)) +>implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) + +// bivariance-allowed cases +d1.implicit = b2.implicit // ok, 'y' in D: { x, y } (d assignable e) +>d1.implicit : Symbol(Base1.implicit, Decl(thisTypeInFunctions.ts, 154, 14)) +>d1 : Symbol(d1, Decl(thisTypeInFunctions.ts, 175, 3)) +>implicit : Symbol(Base1.implicit, Decl(thisTypeInFunctions.ts, 154, 14)) +>b2.implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) +>b2 : Symbol(b2, Decl(thisTypeInFunctions.ts, 174, 3)) +>implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) + +d2.implicit = d1.explicit // ok, 'y' in { x, y } (c assignable to f) +>d2.implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) +>d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 176, 3)) +>implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) +>d1.explicit : Symbol(Base1.explicit, Decl(thisTypeInFunctions.ts, 155, 48)) +>d1 : Symbol(d1, Decl(thisTypeInFunctions.ts, 175, 3)) +>explicit : Symbol(Base1.explicit, Decl(thisTypeInFunctions.ts, 155, 48)) + +b1.implicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) +>b1.implicit : Symbol(Base1.implicit, Decl(thisTypeInFunctions.ts, 154, 14)) +>b1 : Symbol(b1, Decl(thisTypeInFunctions.ts, 173, 3)) +>implicit : Symbol(Base1.implicit, Decl(thisTypeInFunctions.ts, 154, 14)) +>d2.implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) +>d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 176, 3)) +>implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) + +b1.explicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) +>b1.explicit : Symbol(Base1.explicit, Decl(thisTypeInFunctions.ts, 155, 48)) +>b1 : Symbol(b1, Decl(thisTypeInFunctions.ts, 173, 3)) +>explicit : Symbol(Base1.explicit, Decl(thisTypeInFunctions.ts, 155, 48)) +>d2.implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) +>d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 176, 3)) +>implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) + +////// use this-type for construction with new //// +function InterfaceThis(this: I) { +>InterfaceThis : Symbol(InterfaceThis, Decl(thisTypeInFunctions.ts, 184, 25)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 187, 23)) +>I : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) + + this.a = 12; +>this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) +>this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) +>a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) +} +function LiteralTypeThis(this: {x: string}) { +>LiteralTypeThis : Symbol(LiteralTypeThis, Decl(thisTypeInFunctions.ts, 189, 1)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 190, 25)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 190, 32)) + + this.x = "ok"; +>this.x : Symbol(x, Decl(thisTypeInFunctions.ts, 190, 32)) +>this : Symbol(, Decl(thisTypeInFunctions.ts, 190, 30)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 190, 32)) +} +function AnyThis(this: any) { +>AnyThis : Symbol(AnyThis, Decl(thisTypeInFunctions.ts, 192, 1)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 193, 17)) + + this.x = "ok"; +} +let interfaceThis = new InterfaceThis(); +>interfaceThis : Symbol(interfaceThis, Decl(thisTypeInFunctions.ts, 196, 3)) +>InterfaceThis : Symbol(InterfaceThis, Decl(thisTypeInFunctions.ts, 184, 25)) + +let literalTypeThis = new LiteralTypeThis(); +>literalTypeThis : Symbol(literalTypeThis, Decl(thisTypeInFunctions.ts, 197, 3)) +>LiteralTypeThis : Symbol(LiteralTypeThis, Decl(thisTypeInFunctions.ts, 189, 1)) + +let anyThis = new AnyThis(); +>anyThis : Symbol(anyThis, Decl(thisTypeInFunctions.ts, 198, 3)) +>AnyThis : Symbol(AnyThis, Decl(thisTypeInFunctions.ts, 192, 1)) + +//// type parameter inference //// +declare var f: { +>f : Symbol(f, Decl(thisTypeInFunctions.ts, 201, 11)) + + (this: void, x: number): number, +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 202, 5)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 202, 16)) + + call(this: (...argArray: any[]) => U, ...argArray: any[]): U; +>call : Symbol(call, Decl(thisTypeInFunctions.ts, 202, 36)) +>U : Symbol(U, Decl(thisTypeInFunctions.ts, 203, 9)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 203, 12)) +>argArray : Symbol(argArray, Decl(thisTypeInFunctions.ts, 203, 19)) +>U : Symbol(U, Decl(thisTypeInFunctions.ts, 203, 9)) +>argArray : Symbol(argArray, Decl(thisTypeInFunctions.ts, 203, 44)) +>U : Symbol(U, Decl(thisTypeInFunctions.ts, 203, 9)) + +}; +let n: number = f.call(12); +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 205, 3)) +>f.call : Symbol(call, Decl(thisTypeInFunctions.ts, 202, 36)) +>f : Symbol(f, Decl(thisTypeInFunctions.ts, 201, 11)) +>call : Symbol(call, Decl(thisTypeInFunctions.ts, 202, 36)) + +function missingTypeIsImplicitAny(this, a: number) { return a; } +>missingTypeIsImplicitAny : Symbol(missingTypeIsImplicitAny, Decl(thisTypeInFunctions.ts, 205, 27)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 207, 34)) +>a : Symbol(a, Decl(thisTypeInFunctions.ts, 207, 39)) +>a : Symbol(a, Decl(thisTypeInFunctions.ts, 207, 39)) + diff --git a/tests/baselines/reference/thisTypeInFunctions.types b/tests/baselines/reference/thisTypeInFunctions.types new file mode 100644 index 0000000000000..36b458b91e0d7 --- /dev/null +++ b/tests/baselines/reference/thisTypeInFunctions.types @@ -0,0 +1,1037 @@ +=== tests/cases/conformance/types/thisType/thisTypeInFunctions.ts === +// body checking +class C { +>C : C + + n: number; +>n : number + + explicitThis(this: this, m: number): number { +>explicitThis : (this: this, m: number) => number +>this : this +>m : number + + return this.n + m; +>this.n + m : number +>this.n : number +>this : this +>n : number +>m : number + } + implicitThis(m: number): number { +>implicitThis : (this: this, m: number) => number +>m : number + + return this.n + m; +>this.n + m : number +>this.n : number +>this : this +>n : number +>m : number + } + explicitC(this: C, m: number): number { +>explicitC : (this: C, m: number) => number +>this : C +>C : C +>m : number + + return this.n + m; +>this.n + m : number +>this.n : number +>this : C +>n : number +>m : number + } + explicitProperty(this: {n: number}, m: number): number { +>explicitProperty : (this: { n: number; }, m: number) => number +>this : { n: number; } +>n : number +>m : number + + return this.n + m; +>this.n + m : number +>this.n : number +>this : { n: number; } +>n : number +>m : number + } + explicitVoid(this: void, m: number): number { +>explicitVoid : (m: number) => number +>this : void +>m : number + + return m + 1; +>m + 1 : number +>m : number +>1 : number + } +} +class D extends C { } +>D : D +>C : C + +class B { +>B : B + + n: number; +>n : number +} +interface I { +>I : I + + a: number; +>a : number + + explicitVoid1(this: void): number; +>explicitVoid1 : () => number +>this : void + + explicitVoid2(this: void): number; +>explicitVoid2 : () => number +>this : void + + explicitStructural(this: {a: number}): number; +>explicitStructural : (this: { a: number; }) => number +>this : { a: number; } +>a : number + + explicitInterface(this: I): number; +>explicitInterface : (this: I) => number +>this : I +>I : I + + explicitThis(this: this): number; +>explicitThis : (this: this) => number +>this : this + + implicitMethod(): number; +>implicitMethod : (this: this) => number + + implicitFunction: () => number; +>implicitFunction : () => number +} +function explicitStructural(this: { y: number }, x: number): number { +>explicitStructural : (this: { y: number; }, x: number) => number +>this : { y: number; } +>y : number +>x : number + + return x + this.y; +>x + this.y : number +>x : number +>this.y : number +>this : { y: number; } +>y : number +} +function justThis(this: { y: number }): number { +>justThis : (this: { y: number; }) => number +>this : { y: number; } +>y : number + + return this.y; +>this.y : number +>this : { y: number; } +>y : number +} +function implicitThis(n: number): number { +>implicitThis : (n: number) => number +>n : number + + return 12; +>12 : number +} +let impl: I = { +>impl : I +>I : I +>{ a: 12, explicitVoid2: () => this.a, // ok, this: any because it refers to some outer object (window?) explicitVoid1() { return 12; }, explicitStructural() { return this.a; }, explicitInterface() { return this.a; }, explicitThis() { return this.a; }, implicitMethod() { return this.a; }, implicitFunction: () => this.a, // ok, this: any because it refers to some outer object (window?)} : { a: number; explicitVoid2: () => any; explicitVoid1(): number; explicitStructural(this: { a: number; }): number; explicitInterface(this: I): number; explicitThis(this: I): number; implicitMethod(this: I): number; implicitFunction: () => any; } + + a: 12, +>a : number +>12 : number + + explicitVoid2: () => this.a, // ok, this: any because it refers to some outer object (window?) +>explicitVoid2 : () => any +>() => this.a : () => any +>this.a : any +>this : any +>a : any + + explicitVoid1() { return 12; }, +>explicitVoid1 : () => number +>12 : number + + explicitStructural() { +>explicitStructural : (this: { a: number; }) => number + + return this.a; +>this.a : number +>this : { a: number; } +>a : number + + }, + explicitInterface() { +>explicitInterface : (this: I) => number + + return this.a; +>this.a : number +>this : I +>a : number + + }, + explicitThis() { +>explicitThis : (this: I) => number + + return this.a; +>this.a : number +>this : I +>a : number + + }, + implicitMethod() { +>implicitMethod : (this: I) => number + + return this.a; +>this.a : number +>this : I +>a : number + + }, + implicitFunction: () => this.a, // ok, this: any because it refers to some outer object (window?) +>implicitFunction : () => any +>() => this.a : () => any +>this.a : any +>this : any +>a : any +} +impl.explicitVoid1 = function () { return 12; }; +>impl.explicitVoid1 = function () { return 12; } : () => number +>impl.explicitVoid1 : () => number +>impl : I +>explicitVoid1 : () => number +>function () { return 12; } : () => number +>12 : number + +impl.explicitVoid2 = () => 12; +>impl.explicitVoid2 = () => 12 : () => number +>impl.explicitVoid2 : () => number +>impl : I +>explicitVoid2 : () => number +>() => 12 : () => number +>12 : number + +impl.explicitStructural = function() { return this.a; }; +>impl.explicitStructural = function() { return this.a; } : (this: { a: number; }) => number +>impl.explicitStructural : (this: { a: number; }) => number +>impl : I +>explicitStructural : (this: { a: number; }) => number +>function() { return this.a; } : (this: { a: number; }) => number +>this.a : number +>this : { a: number; } +>a : number + +impl.explicitInterface = function() { return this.a; }; +>impl.explicitInterface = function() { return this.a; } : (this: I) => number +>impl.explicitInterface : (this: I) => number +>impl : I +>explicitInterface : (this: I) => number +>function() { return this.a; } : (this: I) => number +>this.a : number +>this : I +>a : number + +impl.explicitStructural = () => 12; +>impl.explicitStructural = () => 12 : () => number +>impl.explicitStructural : (this: { a: number; }) => number +>impl : I +>explicitStructural : (this: { a: number; }) => number +>() => 12 : () => number +>12 : number + +impl.explicitInterface = () => 12; +>impl.explicitInterface = () => 12 : () => number +>impl.explicitInterface : (this: I) => number +>impl : I +>explicitInterface : (this: I) => number +>() => 12 : () => number +>12 : number + +impl.explicitThis = function () { return this.a; }; +>impl.explicitThis = function () { return this.a; } : (this: I) => number +>impl.explicitThis : (this: I) => number +>impl : I +>explicitThis : (this: I) => number +>function () { return this.a; } : (this: I) => number +>this.a : number +>this : I +>a : number + +impl.implicitMethod = function () { return this.a; }; +>impl.implicitMethod = function () { return this.a; } : (this: I) => number +>impl.implicitMethod : (this: I) => number +>impl : I +>implicitMethod : (this: I) => number +>function () { return this.a; } : (this: I) => number +>this.a : number +>this : I +>a : number + +impl.implicitMethod = () => 12; +>impl.implicitMethod = () => 12 : () => number +>impl.implicitMethod : (this: I) => number +>impl : I +>implicitMethod : (this: I) => number +>() => 12 : () => number +>12 : number + +impl.implicitFunction = () => this.a; // ok, this: any because it refers to some outer object (window?) +>impl.implicitFunction = () => this.a : () => any +>impl.implicitFunction : () => number +>impl : I +>implicitFunction : () => number +>() => this.a : () => any +>this.a : any +>this : any +>a : any + +// parameter checking +let ok: {y: number, f: (this: { y: number }, x: number) => number} = { y: 12, f: explicitStructural }; +>ok : { y: number; f: (this: { y: number; }, x: number) => number; } +>y : number +>f : (this: { y: number; }, x: number) => number +>this : { y: number; } +>y : number +>x : number +>{ y: 12, f: explicitStructural } : { y: number; f: (this: { y: number; }, x: number) => number; } +>y : number +>12 : number +>f : (this: { y: number; }, x: number) => number +>explicitStructural : (this: { y: number; }, x: number) => number + +let implicitAnyOk: {notSpecified: number, f: (x: number) => number} = { notSpecified: 12, f: implicitThis }; +>implicitAnyOk : { notSpecified: number; f: (x: number) => number; } +>notSpecified : number +>f : (x: number) => number +>x : number +>{ notSpecified: 12, f: implicitThis } : { notSpecified: number; f: (n: number) => number; } +>notSpecified : number +>12 : number +>f : (n: number) => number +>implicitThis : (n: number) => number + +ok.f(13); +>ok.f(13) : number +>ok.f : (this: { y: number; }, x: number) => number +>ok : { y: number; f: (this: { y: number; }, x: number) => number; } +>f : (this: { y: number; }, x: number) => number +>13 : number + +implicitThis(12); +>implicitThis(12) : number +>implicitThis : (n: number) => number +>12 : number + +implicitAnyOk.f(12); +>implicitAnyOk.f(12) : number +>implicitAnyOk.f : (x: number) => number +>implicitAnyOk : { notSpecified: number; f: (x: number) => number; } +>f : (x: number) => number +>12 : number + +let c = new C(); +>c : C +>new C() : C +>C : typeof C + +let d = new D(); +>d : D +>new D() : D +>D : typeof D + +let ripped = c.explicitC; +>ripped : (this: C, m: number) => number +>c.explicitC : (this: C, m: number) => number +>c : C +>explicitC : (this: C, m: number) => number + +c.explicitC(12); +>c.explicitC(12) : number +>c.explicitC : (this: C, m: number) => number +>c : C +>explicitC : (this: C, m: number) => number +>12 : number + +c.explicitProperty(12); +>c.explicitProperty(12) : number +>c.explicitProperty : (this: { n: number; }, m: number) => number +>c : C +>explicitProperty : (this: { n: number; }, m: number) => number +>12 : number + +c.explicitThis(12); +>c.explicitThis(12) : number +>c.explicitThis : (this: C, m: number) => number +>c : C +>explicitThis : (this: C, m: number) => number +>12 : number + +c.implicitThis(12); +>c.implicitThis(12) : number +>c.implicitThis : (this: C, m: number) => number +>c : C +>implicitThis : (this: C, m: number) => number +>12 : number + +d.explicitC(12); +>d.explicitC(12) : number +>d.explicitC : (this: C, m: number) => number +>d : D +>explicitC : (this: C, m: number) => number +>12 : number + +d.explicitProperty(12); +>d.explicitProperty(12) : number +>d.explicitProperty : (this: { n: number; }, m: number) => number +>d : D +>explicitProperty : (this: { n: number; }, m: number) => number +>12 : number + +d.explicitThis(12); +>d.explicitThis(12) : number +>d.explicitThis : (this: D, m: number) => number +>d : D +>explicitThis : (this: D, m: number) => number +>12 : number + +d.implicitThis(12); +>d.implicitThis(12) : number +>d.implicitThis : (this: D, m: number) => number +>d : D +>implicitThis : (this: D, m: number) => number +>12 : number + +let reconstructed: { +>reconstructed : { n: number; explicitThis(this: C, m: number): number; implicitThis(m: number): number; explicitC(this: C, m: number): number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid(m: number): number; } + + n: number, +>n : number + + explicitThis(this: C, m: number): number, // note: this: this is not allowed in an object literal type. +>explicitThis : (this: C, m: number) => number +>this : C +>C : C +>m : number + + implicitThis(m: number): number, +>implicitThis : (m: number) => number +>m : number + + explicitC(this: C, m: number): number, +>explicitC : (this: C, m: number) => number +>this : C +>C : C +>m : number + + explicitProperty: (this: {n : number}, m: number) => number, +>explicitProperty : (this: { n: number; }, m: number) => number +>this : { n: number; } +>n : number +>m : number + + explicitVoid(this: void, m: number): number, +>explicitVoid : (m: number) => number +>this : void +>m : number + +} = { +>{ n: 12, explicitThis: c.explicitThis, implicitThis: c.implicitThis, explicitC: c.explicitC, explicitProperty: c.explicitProperty, explicitVoid: c.explicitVoid} : { n: number; explicitThis: (this: C, m: number) => number; implicitThis: (this: C, m: number) => number; explicitC: (this: C, m: number) => number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid: (m: number) => number; } + + n: 12, +>n : number +>12 : number + + explicitThis: c.explicitThis, +>explicitThis : (this: C, m: number) => number +>c.explicitThis : (this: C, m: number) => number +>c : C +>explicitThis : (this: C, m: number) => number + + implicitThis: c.implicitThis, +>implicitThis : (this: C, m: number) => number +>c.implicitThis : (this: C, m: number) => number +>c : C +>implicitThis : (this: C, m: number) => number + + explicitC: c.explicitC, +>explicitC : (this: C, m: number) => number +>c.explicitC : (this: C, m: number) => number +>c : C +>explicitC : (this: C, m: number) => number + + explicitProperty: c.explicitProperty, +>explicitProperty : (this: { n: number; }, m: number) => number +>c.explicitProperty : (this: { n: number; }, m: number) => number +>c : C +>explicitProperty : (this: { n: number; }, m: number) => number + + explicitVoid: c.explicitVoid +>explicitVoid : (m: number) => number +>c.explicitVoid : (m: number) => number +>c : C +>explicitVoid : (m: number) => number + +}; +reconstructed.explicitProperty(11); +>reconstructed.explicitProperty(11) : number +>reconstructed.explicitProperty : (this: { n: number; }, m: number) => number +>reconstructed : { n: number; explicitThis(this: C, m: number): number; implicitThis(m: number): number; explicitC(this: C, m: number): number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid(m: number): number; } +>explicitProperty : (this: { n: number; }, m: number) => number +>11 : number + +reconstructed.implicitThis(11); +>reconstructed.implicitThis(11) : number +>reconstructed.implicitThis : (m: number) => number +>reconstructed : { n: number; explicitThis(this: C, m: number): number; implicitThis(m: number): number; explicitC(this: C, m: number): number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid(m: number): number; } +>implicitThis : (m: number) => number +>11 : number + +// assignment checking +let unboundToSpecified: (this: { y: number }, x: number) => number = x => x + this.y; // ok, this:any +>unboundToSpecified : (this: { y: number; }, x: number) => number +>this : { y: number; } +>y : number +>x : number +>x => x + this.y : (x: number) => any +>x : number +>x + this.y : any +>x : number +>this.y : any +>this : any +>y : any + +let specifiedToSpecified: (this: {y: number}, x: number) => number = explicitStructural; +>specifiedToSpecified : (this: { y: number; }, x: number) => number +>this : { y: number; } +>y : number +>x : number +>explicitStructural : (this: { y: number; }, x: number) => number + +let anyToSpecified: (this: { y: number }, x: number) => number = function(x: number): number { return x + 12; }; +>anyToSpecified : (this: { y: number; }, x: number) => number +>this : { y: number; } +>y : number +>x : number +>function(x: number): number { return x + 12; } : (this: { y: number; }, x: number) => number +>x : number +>x + 12 : number +>x : number +>12 : number + +let unspecifiedLambda: (x: number) => number = x => x + 12; +>unspecifiedLambda : (x: number) => number +>x : number +>x => x + 12 : (x: number) => number +>x : number +>x + 12 : number +>x : number +>12 : number + +let specifiedLambda: (this: void, x: number) => number = x => x + 12; +>specifiedLambda : (x: number) => number +>this : void +>x : number +>x => x + 12 : (x: number) => number +>x : number +>x + 12 : number +>x : number +>12 : number + +let unspecifiedLambdaToSpecified: (this: {y: number}, x: number) => number = unspecifiedLambda; +>unspecifiedLambdaToSpecified : (this: { y: number; }, x: number) => number +>this : { y: number; } +>y : number +>x : number +>unspecifiedLambda : (x: number) => number + +let specifiedLambdaToSpecified: (this: {y: number}, x: number) => number = specifiedLambda; +>specifiedLambdaToSpecified : (this: { y: number; }, x: number) => number +>this : { y: number; } +>y : number +>x : number +>specifiedLambda : (x: number) => number + + +let explicitCFunction: (this: C, m: number) => number; +>explicitCFunction : (this: C, m: number) => number +>this : C +>C : C +>m : number + +let explicitPropertyFunction: (this: {n: number}, m: number) => number; +>explicitPropertyFunction : (this: { n: number; }, m: number) => number +>this : { n: number; } +>n : number +>m : number + +c.explicitC = explicitCFunction; +>c.explicitC = explicitCFunction : (this: C, m: number) => number +>c.explicitC : (this: C, m: number) => number +>c : C +>explicitC : (this: C, m: number) => number +>explicitCFunction : (this: C, m: number) => number + +c.explicitC = function(this: C, m: number) { return this.n + m }; +>c.explicitC = function(this: C, m: number) { 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(this: C, m: number) { return this.n + m } : (this: C, m: number) => number +>this : C +>C : C +>m : number +>this.n + m : number +>this.n : number +>this : C +>n : number +>m : number + +c.explicitProperty = explicitPropertyFunction; +>c.explicitProperty = explicitPropertyFunction : (this: { n: number; }, m: number) => number +>c.explicitProperty : (this: { n: number; }, m: number) => number +>c : C +>explicitProperty : (this: { n: number; }, m: number) => number +>explicitPropertyFunction : (this: { n: number; }, m: number) => number + +c.explicitProperty = function(this: {n: number}, m: number) { return this.n + m }; +>c.explicitProperty = function(this: {n: number}, m: number) { 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(this: {n: number}, m: number) { return this.n + m } : (this: { n: number; }, m: number) => number +>this : { n: number; } +>n : number +>m : number +>this.n + m : number +>this.n : number +>this : { n: number; } +>n : number +>m : number + +c.explicitProperty = reconstructed.explicitProperty; +>c.explicitProperty = reconstructed.explicitProperty : (this: { n: number; }, m: number) => number +>c.explicitProperty : (this: { n: number; }, m: number) => number +>c : C +>explicitProperty : (this: { n: number; }, m: number) => number +>reconstructed.explicitProperty : (this: { n: number; }, m: number) => number +>reconstructed : { n: number; explicitThis(this: C, m: number): number; implicitThis(m: number): number; explicitC(this: C, m: number): number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid(m: number): number; } +>explicitProperty : (this: { n: number; }, m: number) => number + +// lambdas are assignable to anything +c.explicitC = m => m; +>c.explicitC = m => m : (m: number) => number +>c.explicitC : (this: C, m: number) => number +>c : C +>explicitC : (this: C, m: number) => number +>m => m : (m: number) => number +>m : number +>m : number + +c.explicitThis = m => m; +>c.explicitThis = m => m : (m: number) => number +>c.explicitThis : (this: C, m: number) => number +>c : C +>explicitThis : (this: C, m: number) => number +>m => m : (m: number) => number +>m : number +>m : number + +c.explicitProperty = m => m; +>c.explicitProperty = m => m : (m: number) => number +>c.explicitProperty : (this: { n: number; }, m: number) => number +>c : C +>explicitProperty : (this: { n: number; }, m: number) => number +>m => m : (m: number) => number +>m : number +>m : number + +// this inside lambdas refer to outer scope +// the outer-scoped lambda at top-level is still just `any` +c.explicitC = m => m + this.n; +>c.explicitC = m => m + this.n : (m: number) => any +>c.explicitC : (this: C, m: number) => number +>c : C +>explicitC : (this: C, m: number) => number +>m => m + this.n : (m: number) => any +>m : number +>m + this.n : any +>m : number +>this.n : any +>this : any +>n : any + +c.explicitThis = m => m + this.n; +>c.explicitThis = m => m + this.n : (m: number) => any +>c.explicitThis : (this: C, m: number) => number +>c : C +>explicitThis : (this: C, m: number) => number +>m => m + this.n : (m: number) => any +>m : number +>m + this.n : any +>m : number +>this.n : any +>this : any +>n : any + +c.explicitProperty = m => m + this.n; +>c.explicitProperty = m => m + this.n : (m: number) => any +>c.explicitProperty : (this: { n: number; }, m: number) => number +>c : C +>explicitProperty : (this: { n: number; }, m: number) => number +>m => m + this.n : (m: number) => any +>m : number +>m + this.n : any +>m : number +>this.n : any +>this : any +>n : any + +//NOTE: this=C here, I guess? +c.explicitThis = explicitCFunction; +>c.explicitThis = explicitCFunction : (this: C, m: number) => number +>c.explicitThis : (this: C, m: number) => number +>c : C +>explicitThis : (this: C, m: number) => number +>explicitCFunction : (this: C, m: number) => number + +c.explicitThis = function(this: C, m: number) { return this.n + m }; +>c.explicitThis = function(this: C, m: number) { 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(this: C, m: number) { return this.n + m } : (this: C, m: number) => number +>this : C +>C : C +>m : number +>this.n + m : number +>this.n : number +>this : C +>n : number +>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 : (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 +>m : number +>this.n + m : number +>this.n : number +>this : C +>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 : (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 +>m : number +>this.n + m : number +>this.n : number +>this : { n: number; } +>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 : (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 +>m : number +>this.n + m : number +>this.n : number +>this : C +>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 : (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 +>m : number +>this.n + m : number +>this.n : number +>this : C +>n : number +>m : number + +c.implicitThis = reconstructed.implicitThis; +>c.implicitThis = reconstructed.implicitThis : (m: number) => number +>c.implicitThis : (this: C, m: number) => number +>c : C +>implicitThis : (this: C, m: number) => number +>reconstructed.implicitThis : (m: number) => number +>reconstructed : { n: number; explicitThis(this: C, m: number): number; implicitThis(m: number): number; explicitC(this: C, m: number): number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid(m: number): number; } +>implicitThis : (m: number) => number + +c.explicitC = function(this: B, m: number) { return this.n + m }; +>c.explicitC = function(this: B, m: number) { return this.n + m } : (this: B, m: number) => number +>c.explicitC : (this: C, m: number) => number +>c : C +>explicitC : (this: C, m: number) => number +>function(this: B, m: number) { return this.n + m } : (this: B, m: number) => number +>this : B +>B : B +>m : number +>this.n + m : number +>this.n : number +>this : B +>n : number +>m : number + +// this:void compatibility +c.explicitVoid = n => n; +>c.explicitVoid = n => n : (n: number) => number +>c.explicitVoid : (m: number) => number +>c : C +>explicitVoid : (m: number) => number +>n => n : (n: number) => number +>n : number +>n : number + +// class-based assignability +class Base1 { +>Base1 : Base1 + + x: number; +>x : number + + public implicit(): number { return this.x; } +>implicit : (this: this) => number +>this.x : number +>this : this +>x : number + + explicit(this: Base1): number { return this.x; } +>explicit : (this: Base1) => number +>this : Base1 +>Base1 : Base1 +>this.x : number +>this : Base1 +>x : number + + static implicitStatic(): number { return this.y; } +>implicitStatic : (this: typeof Base1) => number +>this.y : number +>this : typeof Base1 +>y : number + + static explicitStatic(this: typeof Base1): number { return this.y; } +>explicitStatic : (this: typeof Base1) => number +>this : typeof Base1 +>Base1 : typeof Base1 +>this.y : number +>this : typeof Base1 +>y : number + + static y: number; +>y : number + +} +class Derived1 extends Base1 { +>Derived1 : Derived1 +>Base1 : Base1 + + y: number +>y : number +} +class Base2 { +>Base2 : Base2 + + y: number +>y : number + + implicit(): number { return this.y; } +>implicit : (this: this) => number +>this.y : number +>this : this +>y : number + + explicit(this: Base1): number { return this.x; } +>explicit : (this: Base1) => number +>this : Base1 +>Base1 : Base1 +>this.x : number +>this : Base1 +>x : number +} +class Derived2 extends Base2 { +>Derived2 : Derived2 +>Base2 : Base2 + + x: number +>x : number +} +let b1 = new Base1(); +>b1 : Base1 +>new Base1() : Base1 +>Base1 : typeof Base1 + +let b2 = new Base2(); +>b2 : Base2 +>new Base2() : Base2 +>Base2 : typeof Base2 + +let d1 = new Derived1(); +>d1 : Derived1 +>new Derived1() : Derived1 +>Derived1 : typeof Derived1 + +let d2 = new Derived2(); +>d2 : Derived2 +>new Derived2() : Derived2 +>Derived2 : typeof Derived2 + +d2.implicit = d1.implicit // ok, 'x' and 'y' in { x, y } (d assignable to f and vice versa) +>d2.implicit = d1.implicit : (this: Derived1) => number +>d2.implicit : (this: Derived2) => number +>d2 : Derived2 +>implicit : (this: Derived2) => number +>d1.implicit : (this: Derived1) => number +>d1 : Derived1 +>implicit : (this: Derived1) => number + +d1.implicit = d2.implicit // ok, 'x' and 'y' in { x, y } (f assignable to d and vice versa) +>d1.implicit = d2.implicit : (this: Derived2) => number +>d1.implicit : (this: Derived1) => number +>d1 : Derived1 +>implicit : (this: Derived1) => number +>d2.implicit : (this: Derived2) => number +>d2 : Derived2 +>implicit : (this: Derived2) => number + +// bivariance-allowed cases +d1.implicit = b2.implicit // ok, 'y' in D: { x, y } (d assignable e) +>d1.implicit = b2.implicit : (this: Base2) => number +>d1.implicit : (this: Derived1) => number +>d1 : Derived1 +>implicit : (this: Derived1) => number +>b2.implicit : (this: Base2) => number +>b2 : Base2 +>implicit : (this: Base2) => number + +d2.implicit = d1.explicit // ok, 'y' in { x, y } (c assignable to f) +>d2.implicit = d1.explicit : (this: Base1) => number +>d2.implicit : (this: Derived2) => number +>d2 : Derived2 +>implicit : (this: Derived2) => number +>d1.explicit : (this: Base1) => number +>d1 : Derived1 +>explicit : (this: Base1) => number + +b1.implicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) +>b1.implicit = d2.implicit : (this: Derived2) => number +>b1.implicit : (this: Base1) => number +>b1 : Base1 +>implicit : (this: Base1) => number +>d2.implicit : (this: Derived2) => number +>d2 : Derived2 +>implicit : (this: Derived2) => number + +b1.explicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) +>b1.explicit = d2.implicit : (this: Derived2) => number +>b1.explicit : (this: Base1) => number +>b1 : Base1 +>explicit : (this: Base1) => number +>d2.implicit : (this: Derived2) => number +>d2 : Derived2 +>implicit : (this: Derived2) => number + +////// use this-type for construction with new //// +function InterfaceThis(this: I) { +>InterfaceThis : (this: I) => void +>this : I +>I : I + + this.a = 12; +>this.a = 12 : number +>this.a : number +>this : I +>a : number +>12 : number +} +function LiteralTypeThis(this: {x: string}) { +>LiteralTypeThis : (this: { x: string; }) => void +>this : { x: string; } +>x : string + + this.x = "ok"; +>this.x = "ok" : string +>this.x : string +>this : { x: string; } +>x : string +>"ok" : string +} +function AnyThis(this: any) { +>AnyThis : () => void +>this : any + + this.x = "ok"; +>this.x = "ok" : string +>this.x : any +>this : any +>x : any +>"ok" : string +} +let interfaceThis = new InterfaceThis(); +>interfaceThis : I +>new InterfaceThis() : I +>InterfaceThis : (this: I) => void + +let literalTypeThis = new LiteralTypeThis(); +>literalTypeThis : { x: string; } +>new LiteralTypeThis() : { x: string; } +>LiteralTypeThis : (this: { x: string; }) => void + +let anyThis = new AnyThis(); +>anyThis : any +>new AnyThis() : any +>AnyThis : () => void + +//// type parameter inference //// +declare var f: { +>f : { (x: number): number; call(this: (...argArray: any[]) => U, ...argArray: any[]): U; } + + (this: void, x: number): number, +>this : void +>x : number + + call(this: (...argArray: any[]) => U, ...argArray: any[]): U; +>call : (this: (...argArray: any[]) => U, ...argArray: any[]) => U +>U : U +>this : (...argArray: any[]) => U +>argArray : any[] +>U : U +>argArray : any[] +>U : U + +}; +let n: number = f.call(12); +>n : number +>f.call(12) : number +>f.call : (this: (...argArray: any[]) => U, ...argArray: any[]) => U +>f : { (x: number): number; call(this: (...argArray: any[]) => U, ...argArray: any[]): U; } +>call : (this: (...argArray: any[]) => U, ...argArray: any[]) => U +>12 : number + +function missingTypeIsImplicitAny(this, a: number) { return a; } +>missingTypeIsImplicitAny : (a: number) => number +>this : any +>a : number +>a : number + diff --git a/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt b/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt new file mode 100644 index 0000000000000..49a4380977a87 --- /dev/null +++ b/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt @@ -0,0 +1,509 @@ +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(44,21): error TS2339: Property 'a' does not exist on type 'void'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(55,49): error TS2339: Property 'a' does not exist on type 'void'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(58,1): error TS2345: Argument of type 'void' is not assignable to parameter of type '{ a: number; }'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(60,1): error TS2345: Argument of type 'void' is not assignable to parameter of type 'I'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(62,1): error TS2345: Argument of type 'void' is not assignable to parameter of type 'I'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(67,21): error TS2339: Property 'notFound' does not exist on type '{ y: number; }'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(70,21): error TS2339: Property 'notSpecified' does not exist on type 'void'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(74,21): error TS2339: Property 'notSpecified' does not exist on type 'void'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(76,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; }'. + Object literal may only specify known properties, and 'explicitStructural' does not exist in type '{ y: number; f: (this: { y: number; }, x: number) => number; }'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(77,97): error TS2322: Type '{ y: string; explicitStructural: (this: { y: number; }, x: number) => number; }' is not assignable to type '{ y: string; f: (this: { y: number; }, x: number) => number; }'. + Object literal may only specify known properties, and 'explicitStructural' does not exist in type '{ y: string; f: (this: { y: number; }, x: number) => number; }'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(78,110): error TS2322: Type '{ wrongName: number; explicitStructural: (this: { y: number; }, x: number) => number; }' is not assignable to type '{ wrongName: number; f: (this: { y: number; }, x: number) => number; }'. + Object literal may only specify known properties, and 'explicitStructural' does not exist in type '{ wrongName: number; f: (this: { y: number; }, x: number) => number; }'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(80,1): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(81,6): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(82,1): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(83,1): error TS2345: Argument of type '{ y: string; f: (this: { y: number; }, x: number) => number; }' is not assignable to parameter 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(84,1): error TS2345: Argument of type '{ wrongName: number; f: (this: { y: number; }, x: number) => number; }' is not assignable to parameter 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(87,1): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(88,13): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(89,1): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(90,1): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(91,16): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(92,1): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(93,1): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(94,16): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(95,1): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(96,1): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(97,20): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(98,1): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(101,5): error TS2322: Type '(this: { y: number; }, x: number) => number' is not assignable to type '(x: number) => number'. + Types of parameters 'this' and 'this' are incompatible. + Type 'void' is not assignable to type '{ y: number; }'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(124,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. + Type 'C' is not assignable to type 'D'. + Property 'x' is missing in type 'C'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(125,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. + 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(127,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. + Type 'C' is not assignable to type 'D'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(128,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. + Type 'C' is not assignable to type 'D'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(129,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. + Type 'C' is not assignable to type 'D'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(130,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. + Type 'C' is not assignable to type 'D'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(131,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. + Type 'C' is not assignable to type 'D'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(132,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. + Type 'C' is not assignable to type 'D'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(133,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. + Type '{ n: number; }' is not assignable to type 'D'. + Property 'x' is missing in type '{ n: number; }'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(134,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. + Type '{ n: number; }' is not assignable to type 'D'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(135,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(136,1): error TS2322: Type '(this: D, 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 'D'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(137,1): error TS2322: Type '(this: D, 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 'D'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(138,1): error TS2322: Type '(this: D, 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 'D'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(146,51): error TS2339: Property 'x' does not exist on type 'typeof Base1'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(147,69): error TS2339: Property 'x' does not exist on type 'typeof Base1'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(167,1): error TS2322: Type '(this: Base2) => number' is not assignable to type '(this: Base1) => number'. + Types of parameters 'this' and 'this' are incompatible. + Type 'Base1' is not assignable to type 'Base2'. + Property 'y' is missing in type 'Base1'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(168,1): error TS2322: Type '(this: Base2) => number' is not assignable to type '(this: Base1) => number'. + Types of parameters 'this' and 'this' are incompatible. + Type 'Base1' is not assignable to type 'Base2'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(170,1): error TS2322: Type '(this: Base2) => number' is not assignable to type '(this: Base1) => number'. + Types of parameters 'this' and 'this' are incompatible. + Type 'Base1' is not assignable to type 'Base2'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(179,16): error TS2671: 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 TS2671: 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(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'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(186,20): error TS2370: A rest parameter must be of an array type. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(186,23): error TS1003: Identifier expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(186,27): error TS1005: ',' expected. +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'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(189,30): error TS1005: ',' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(189,32): error TS1138: Parameter declaration expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(189,39): error TS1005: ';' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(189,40): error TS1128: Declaration or statement expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(189,42): error TS2304: Cannot find name 'number'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(189,49): error TS1005: ';' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(192,1): error TS7027: Unreachable code detected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(192,29): error TS2304: Cannot find name 'm'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(192,32): error TS1005: ';' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(192,35): error TS2304: Cannot find name 'm'. + + +==== tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts (75 errors) ==== + class C { + n: number; + explicitThis(this: this, m: number): number { + return this.n + m; + } + implicitThis(m: number): number { + return this.n + m; + } + explicitC(this: C, m: number): number { + return this.n + m; + } + explicitProperty(this: {n: number}, m: number): number { + return this.n + m; + } + explicitVoid(this: void, m: number): number { + return this.n + m; // 'n' doesn't exist on type 'void'. + ~ +!!! error TS2339: Property 'n' does not exist on type 'void'. + } + } + class D { + x: number; + explicitThis(this: this, m: number): number { + return this.x + m; + } + explicitD(this: D, m: number): number { + return this.x + m; + } + implicitD(m: number): number { + return this.x + m; + } + } + interface I { + a: number; + explicitVoid1(this: void): number; + explicitVoid2(this: void): number; + explicitStructural(this: {a: number}): number; + explicitInterface(this: I): number; + explicitThis(this: this): number; // TODO: Allow `this` types for interfaces + implicitMethod(): number; + implicitFunction: () => number; + } + let impl: I = { + a: 12, + explicitVoid1() { + return this.a; // error, no 'a' in 'void' + ~ +!!! error TS2339: Property 'a' does not exist on type 'void'. + }, + explicitVoid2: () => this.a, // ok, `this:any` because it refers to an outer object + explicitStructural: () => 12, + explicitInterface: () => 12, + explicitThis() { + return this.a; + }, + implicitMethod() { + return this.a; // ok, I.a: number + }, + implicitFunction: function () { return this.a; } // TODO: error 'a' not found in 'void' + ~ +!!! error TS2339: Property 'a' does not exist on type 'void'. + } + let implExplicitStructural = impl.explicitStructural; + implExplicitStructural(); // error, no 'a' in 'void' + ~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type 'void' is not assignable to parameter of type '{ a: number; }'. + let implExplicitInterface = impl.explicitInterface; + implExplicitInterface(); // error, no 'a' in 'void' + ~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type 'void' is not assignable to parameter of type 'I'. + let implImplicitMethod = impl.implicitMethod; + implImplicitMethod(); // error, no 'a' in 'void' + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type 'void' is not assignable to parameter of type 'I'. + function explicitStructural(this: { y: number }, x: number): number { + return x + this.y; + } + function propertyName(this: { y: number }, x: number): number { + return x + this.notFound; + ~~~~~~~~ +!!! error TS2339: Property 'notFound' does not exist on type '{ y: number; }'. + } + function voidThisSpecified(this: void, x: number): number { + return x + this.notSpecified; + ~~~~~~~~~~~~ +!!! error TS2339: Property 'notSpecified' does not exist on type 'void'. + } + function noThisSpecified(x: number): number { + // this:void unless loose-this is on + return x + this.notSpecified; + ~~~~~~~~~~~~ +!!! error TS2339: Property 'notSpecified' does not exist on type 'void'. + } + let ok: {y: number, f: (this: { y: number }, x: number) => number} = { y: 12, explicitStructural }; + ~~~~~~~~~~~~~~~~~~ +!!! 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; }'. +!!! error TS2322: Object literal may only specify known properties, and 'explicitStructural' does not exist in type '{ y: number; f: (this: { y: number; }, x: number) => number; }'. + let wrongPropertyType: {y: string, f: (this: { y: number }, x: number) => number} = { y: 'foo', explicitStructural }; + ~~~~~~~~~~~~~~~~~~ +!!! error TS2322: Type '{ y: string; explicitStructural: (this: { y: number; }, x: number) => number; }' is not assignable to type '{ y: string; f: (this: { y: number; }, x: number) => number; }'. +!!! error TS2322: Object literal may only specify known properties, and 'explicitStructural' does not exist in type '{ y: string; f: (this: { y: number; }, x: number) => number; }'. + let wrongPropertyName: {wrongName: number, f: (this: { y: number }, x: number) => number} = { wrongName: 12, explicitStructural }; + ~~~~~~~~~~~~~~~~~~ +!!! error TS2322: Type '{ wrongName: number; explicitStructural: (this: { y: number; }, x: number) => number; }' is not assignable to type '{ wrongName: number; f: (this: { y: number; }, x: number) => number; }'. +!!! error TS2322: Object literal may only specify known properties, and 'explicitStructural' does not exist in type '{ wrongName: number; f: (this: { y: number; }, x: number) => number; }'. + + ok.f(); // not enough arguments + ~~~~~~ +!!! error TS2346: Supplied parameters do not match any signature of call target. + ok.f('wrong type'); + ~~~~~~~~~~~~ +!!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. + ok.f(13, 'too many arguments'); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2346: Supplied parameters do not match any signature of call target. + wrongPropertyType.f(13); + ~~~~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type '{ y: string; f: (this: { y: number; }, x: number) => number; }' is not assignable to parameter of type '{ y: number; }'. +!!! error TS2345: Types of property 'y' are incompatible. +!!! error TS2345: Type 'string' is not assignable to type 'number'. + wrongPropertyName.f(13); + ~~~~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type '{ wrongName: number; f: (this: { y: number; }, x: number) => number; }' is not assignable to parameter of type '{ y: number; }'. +!!! error TS2345: Property 'y' is missing in type '{ wrongName: number; f: (this: { y: number; }, x: number) => number; }'. + + let c = new C(); + c.explicitC(); // not enough arguments + ~~~~~~~~~~~~~ +!!! error TS2346: Supplied parameters do not match any signature of call target. + c.explicitC('wrong type'); + ~~~~~~~~~~~~ +!!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. + c.explicitC(13, 'too many arguments'); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2346: Supplied parameters do not match any signature of call target. + c.explicitThis(); // not enough arguments + ~~~~~~~~~~~~~~~~ +!!! error TS2346: Supplied parameters do not match any signature of call target. + c.explicitThis('wrong type 2'); + ~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. + c.explicitThis(14, 'too many arguments 2'); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2346: Supplied parameters do not match any signature of call target. + c.implicitThis(); // not enough arguments + ~~~~~~~~~~~~~~~~ +!!! error TS2346: Supplied parameters do not match any signature of call target. + c.implicitThis('wrong type 2'); + ~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. + c.implicitThis(14, 'too many arguments 2'); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2346: Supplied parameters do not match any signature of call target. + c.explicitProperty(); // not enough arguments + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS2346: Supplied parameters do not match any signature of call target. + c.explicitProperty('wrong type 3'); + ~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. + c.explicitProperty(15, 'too many arguments 3'); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2346: Supplied parameters do not match any signature of call target. + + // oops, this triggers contextual typing, which needs to be updated to understand that =>'s `this` is void. + let specifiedToImplicitVoid: (x: number) => number = explicitStructural; + ~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2322: Type '(this: { y: number; }, x: number) => number' is not assignable to type '(x: number) => number'. +!!! error TS2322: Types of parameters 'this' and 'this' are incompatible. +!!! error TS2322: Type 'void' is not assignable to type '{ y: number; }'. + + let reconstructed: { + n: number, + explicitThis(this: C, m: number): number, // note: this: this is not allowed in an object literal type. + implicitThis(m: number): number, + explicitC(this: C, m: number): number, + explicitProperty: (this: {n : number}, m: number) => number, + explicitVoid(this: void, m: number): number, + } = { + n: 12, + explicitThis: c.explicitThis, + implicitThis: c.implicitThis, // error not assignable -- c.this:c not assignable to this:void. + explicitC: c.explicitC, + explicitProperty: c.explicitProperty, + explicitVoid: c.explicitVoid + };; + + // lambdas have this: void for assignability purposes (and this unbound (free) for body checking) + let d = new D(); + let explicitXProperty: (this: { x: number }, m: number) => number; + + // from differing object types + 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: 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: Type '{ n: number; }' is not assignable to type '{ x: number; }'. +!!! error TS2322: Property 'x' is missing in type '{ n: number; }'. + + c.explicitC = d.implicitD; + ~~~~~~~~~~~ +!!! 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: Type 'C' is not assignable to type 'D'. + 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: 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: Type 'C' is not assignable to type 'D'. + c.explicitThis = d.implicitD; + ~~~~~~~~~~~~~~ +!!! 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: 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: 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: 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: Type '{ n: number; }' is not assignable to type 'D'. +!!! error TS2322: Property 'x' is missing in type '{ n: number; }'. + c.explicitProperty = d.implicitD; + ~~~~~~~~~~~~~~~~~~ +!!! 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: Type '{ n: number; }' 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'. + c.explicitVoid = d.implicitD; + ~~~~~~~~~~~~~~ +!!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(m: number) => number'. +!!! error TS2322: Types of parameters 'this' and 'this' are incompatible. +!!! error TS2322: Type 'void' is not assignable to type 'D'. + c.explicitVoid = d.explicitD; + ~~~~~~~~~~~~~~ +!!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(m: number) => number'. +!!! error TS2322: Types of parameters 'this' and 'this' 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 '(m: number) => number'. +!!! error TS2322: Types of parameters 'this' and 'this' are incompatible. +!!! error TS2322: Type 'void' is not assignable to type 'D'. + + /// class-based implicit assignability (with inheritance!) /// + + class Base1 { + x: number + public implicit(): number { return this.x; } + explicit(this: Base1): number { return this.x; } + static implicitStatic(): number { return this.x; } + ~ +!!! error TS2339: Property 'x' does not exist on type 'typeof Base1'. + static explicitStatic(this: typeof Base1): number { return this.x; } + ~ +!!! error TS2339: Property 'x' does not exist on type 'typeof Base1'. + } + class Derived1 extends Base1 { + y: number + } + class Base2 { + y: number + implicit(): number { return this.y; } + explicit(this: Base1): number { return this.x; } + } + class Derived2 extends Base2 { + x: number + } + + + let b1 = new Base1(); + let d1 = new Derived1(); + let b2 = new Base2(); + let d2 = new Derived2(); + + b1.implicit = b2.implicit // error, 'this.y' not in C: { x } (c assignable to e) + ~~~~~~~~~~~ +!!! 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: Type 'Base1' is not assignable to type 'Base2'. +!!! error TS2322: Property 'y' is missing in type 'Base1'. + b1.explicit = b2.implicit // error, 'y' not in C: { x } (c assignable to e) + ~~~~~~~~~~~ +!!! 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: Type 'Base1' is not assignable to type 'Base2'. + + d1.explicit = b2.implicit // error, 'y' not in C: { x } (c assignable to e) + ~~~~~~~~~~~ +!!! 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: Type 'Base1' is not assignable to type 'Base2'. + + ////// use this-type for construction with new //// + function VoidThis(this: void) { + + } + function ImplicitVoidThis() { + + } + let voidThis = new VoidThis(); + ~~~~~~~~~~~~~~ +!!! error TS2671: A function that is called with the 'new' keyword cannot have a 'this' type that is void. + let implicitVoidThis = new ImplicitVoidThis(); + ~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2671: A function that is called with the 'new' keyword cannot have a 'this' type that is void. + + + ///// parse errors ///// + function notFirst(a: number, this: C): number { return this.n; } + ~~~~~~~ +!!! error TS2332: 'this' cannot be referenced in current location. + function modifiers(async this: C): number { return this.n; } + ~~~~ +!!! error TS1003: Identifier expected. + ~ +!!! error TS1005: ',' expected. + ~ +!!! error TS2339: Property 'n' does not exist on type 'void'. + function restParam(...this: C): number { return this.n; } + ~~~~~~~ +!!! error TS2370: A rest parameter must be of an array type. + ~~~~ +!!! error TS1003: Identifier expected. + ~ +!!! error TS1005: ',' expected. + ~ +!!! error TS2339: Property 'n' does not exist on type 'void'. + function optional(this?: C): number { return this.n; } + ~ +!!! 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. + ~ +!!! error TS1005: ',' expected. + ~ +!!! error TS2339: Property 'n' does not exist on type 'void'. + function initializer(this: C = new C()): number { return this.n; } + ~ +!!! error TS1005: ',' expected. + ~~~ +!!! error TS1138: Parameter declaration expected. + ~ +!!! error TS1005: ';' expected. + ~ +!!! error TS1128: Declaration or statement expected. + ~~~~~~ +!!! error TS2304: Cannot find name 'number'. + ~ +!!! error TS1005: ';' expected. + + // can't name parameters 'this' in a lambda. + c.explicitProperty = (this, m) => m + this.n; + ~ +!!! error TS7027: Unreachable code detected. + ~ +!!! error TS2304: Cannot find name 'm'. + ~~ +!!! error TS1005: ';' expected. + ~ +!!! error TS2304: Cannot find name 'm'. + \ No newline at end of file diff --git a/tests/baselines/reference/thisTypeInFunctionsNegative.js b/tests/baselines/reference/thisTypeInFunctionsNegative.js new file mode 100644 index 0000000000000..43d83daef0d9f --- /dev/null +++ b/tests/baselines/reference/thisTypeInFunctionsNegative.js @@ -0,0 +1,386 @@ +//// [thisTypeInFunctionsNegative.ts] +class C { + n: number; + explicitThis(this: this, m: number): number { + return this.n + m; + } + implicitThis(m: number): number { + return this.n + m; + } + explicitC(this: C, m: number): number { + return this.n + m; + } + explicitProperty(this: {n: number}, m: number): number { + return this.n + m; + } + explicitVoid(this: void, m: number): number { + return this.n + m; // 'n' doesn't exist on type 'void'. + } +} +class D { + x: number; + explicitThis(this: this, m: number): number { + return this.x + m; + } + explicitD(this: D, m: number): number { + return this.x + m; + } + implicitD(m: number): number { + return this.x + m; + } +} +interface I { + a: number; + explicitVoid1(this: void): number; + explicitVoid2(this: void): number; + explicitStructural(this: {a: number}): number; + explicitInterface(this: I): number; + explicitThis(this: this): number; // TODO: Allow `this` types for interfaces + implicitMethod(): number; + implicitFunction: () => number; +} +let impl: I = { + a: 12, + explicitVoid1() { + return this.a; // error, no 'a' in 'void' + }, + explicitVoid2: () => this.a, // ok, `this:any` because it refers to an outer object + explicitStructural: () => 12, + explicitInterface: () => 12, + explicitThis() { + return this.a; + }, + implicitMethod() { + return this.a; // ok, I.a: number + }, + implicitFunction: function () { return this.a; } // TODO: error 'a' not found in 'void' +} +let implExplicitStructural = impl.explicitStructural; +implExplicitStructural(); // error, no 'a' in 'void' +let implExplicitInterface = impl.explicitInterface; +implExplicitInterface(); // error, no 'a' in 'void' +let implImplicitMethod = impl.implicitMethod; +implImplicitMethod(); // error, no 'a' in 'void' +function explicitStructural(this: { y: number }, x: number): number { + return x + this.y; +} +function propertyName(this: { y: number }, x: number): number { + return x + this.notFound; +} +function voidThisSpecified(this: void, x: number): number { + return x + this.notSpecified; +} +function noThisSpecified(x: number): number { + // this:void unless loose-this is on + return x + this.notSpecified; +} +let ok: {y: number, f: (this: { y: number }, x: number) => number} = { y: 12, explicitStructural }; +let wrongPropertyType: {y: string, f: (this: { y: number }, x: number) => number} = { y: 'foo', explicitStructural }; +let wrongPropertyName: {wrongName: number, f: (this: { y: number }, x: number) => number} = { wrongName: 12, explicitStructural }; + +ok.f(); // not enough arguments +ok.f('wrong type'); +ok.f(13, 'too many arguments'); +wrongPropertyType.f(13); +wrongPropertyName.f(13); + +let c = new C(); +c.explicitC(); // not enough arguments +c.explicitC('wrong type'); +c.explicitC(13, 'too many arguments'); +c.explicitThis(); // not enough arguments +c.explicitThis('wrong type 2'); +c.explicitThis(14, 'too many arguments 2'); +c.implicitThis(); // not enough arguments +c.implicitThis('wrong type 2'); +c.implicitThis(14, 'too many arguments 2'); +c.explicitProperty(); // not enough arguments +c.explicitProperty('wrong type 3'); +c.explicitProperty(15, 'too many arguments 3'); + +// oops, this triggers contextual typing, which needs to be updated to understand that =>'s `this` is void. +let specifiedToImplicitVoid: (x: number) => number = explicitStructural; + +let reconstructed: { + n: number, + explicitThis(this: C, m: number): number, // note: this: this is not allowed in an object literal type. + implicitThis(m: number): number, + explicitC(this: C, m: number): number, + explicitProperty: (this: {n : number}, m: number) => number, + explicitVoid(this: void, m: number): number, +} = { + n: 12, + explicitThis: c.explicitThis, + implicitThis: c.implicitThis, // error not assignable -- c.this:c not assignable to this:void. + explicitC: c.explicitC, + explicitProperty: c.explicitProperty, + explicitVoid: c.explicitVoid +};; + +// lambdas have this: void for assignability purposes (and this unbound (free) for body checking) +let d = new D(); +let explicitXProperty: (this: { x: number }, m: number) => number; + +// from differing object types +c.explicitC = function(this: D, m: number) { return this.x + m }; +c.explicitProperty = explicitXProperty; + +c.explicitC = d.implicitD; +c.explicitC = d.explicitD; +c.explicitC = d.explicitThis; +c.explicitThis = d.implicitD; +c.explicitThis = d.explicitD; +c.explicitThis = d.explicitThis; +c.explicitProperty = d.explicitD; +c.explicitProperty = d.implicitD; +c.explicitThis = d.explicitThis; +c.explicitVoid = d.implicitD; +c.explicitVoid = d.explicitD; +c.explicitVoid = d.explicitThis; + +/// class-based implicit assignability (with inheritance!) /// + +class Base1 { + x: number + public implicit(): number { return this.x; } + explicit(this: Base1): number { return this.x; } + static implicitStatic(): number { return this.x; } + static explicitStatic(this: typeof Base1): number { return this.x; } +} +class Derived1 extends Base1 { + y: number +} +class Base2 { + y: number + implicit(): number { return this.y; } + explicit(this: Base1): number { return this.x; } +} +class Derived2 extends Base2 { + x: number +} + + +let b1 = new Base1(); +let d1 = new Derived1(); +let b2 = new Base2(); +let d2 = new Derived2(); + +b1.implicit = b2.implicit // error, 'this.y' not in C: { x } (c assignable to e) +b1.explicit = b2.implicit // error, 'y' not in C: { x } (c assignable to e) + +d1.explicit = b2.implicit // error, 'y' not in C: { x } (c assignable to e) + +////// use this-type for construction with new //// +function VoidThis(this: void) { + +} +function ImplicitVoidThis() { + +} +let voidThis = new VoidThis(); +let implicitVoidThis = new ImplicitVoidThis(); + + +///// parse errors ///// +function notFirst(a: number, this: C): number { return this.n; } +function modifiers(async this: C): number { return this.n; } +function restParam(...this: C): number { return this.n; } +function optional(this?: C): number { return this.n; } +function decorated(@deco() this: C): number { return this.n; } +function initializer(this: C = new C()): number { return this.n; } + +// can't name parameters 'this' in a lambda. +c.explicitProperty = (this, m) => m + this.n; + + +//// [thisTypeInFunctionsNegative.js] +var __extends = (this && this.__extends) || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +}; +var _this = this; +var C = (function () { + function C() { + } + C.prototype.explicitThis = function (m) { + return this.n + m; + }; + C.prototype.implicitThis = function (m) { + return this.n + m; + }; + C.prototype.explicitC = function (m) { + return this.n + m; + }; + C.prototype.explicitProperty = function (m) { + return this.n + m; + }; + C.prototype.explicitVoid = function (m) { + return this.n + m; // 'n' doesn't exist on type 'void'. + }; + return C; +}()); +var D = (function () { + function D() { + } + D.prototype.explicitThis = function (m) { + return this.x + m; + }; + D.prototype.explicitD = function (m) { + return this.x + m; + }; + D.prototype.implicitD = function (m) { + return this.x + m; + }; + return D; +}()); +var impl = { + a: 12, + explicitVoid1: function () { + return this.a; // error, no 'a' in 'void' + }, + explicitVoid2: function () { return _this.a; }, + explicitStructural: function () { return 12; }, + explicitInterface: function () { return 12; }, + explicitThis: function () { + return this.a; + }, + implicitMethod: function () { + return this.a; // ok, I.a: number + }, + implicitFunction: function () { return this.a; } // TODO: error 'a' not found in 'void' +}; +var implExplicitStructural = impl.explicitStructural; +implExplicitStructural(); // error, no 'a' in 'void' +var implExplicitInterface = impl.explicitInterface; +implExplicitInterface(); // error, no 'a' in 'void' +var implImplicitMethod = impl.implicitMethod; +implImplicitMethod(); // error, no 'a' in 'void' +function explicitStructural(x) { + return x + this.y; +} +function propertyName(x) { + return x + this.notFound; +} +function voidThisSpecified(x) { + return x + this.notSpecified; +} +function noThisSpecified(x) { + // this:void unless loose-this is on + return x + this.notSpecified; +} +var ok = { y: 12, explicitStructural: explicitStructural }; +var wrongPropertyType = { y: 'foo', explicitStructural: explicitStructural }; +var wrongPropertyName = { wrongName: 12, explicitStructural: explicitStructural }; +ok.f(); // not enough arguments +ok.f('wrong type'); +ok.f(13, 'too many arguments'); +wrongPropertyType.f(13); +wrongPropertyName.f(13); +var c = new C(); +c.explicitC(); // not enough arguments +c.explicitC('wrong type'); +c.explicitC(13, 'too many arguments'); +c.explicitThis(); // not enough arguments +c.explicitThis('wrong type 2'); +c.explicitThis(14, 'too many arguments 2'); +c.implicitThis(); // not enough arguments +c.implicitThis('wrong type 2'); +c.implicitThis(14, 'too many arguments 2'); +c.explicitProperty(); // not enough arguments +c.explicitProperty('wrong type 3'); +c.explicitProperty(15, 'too many arguments 3'); +// oops, this triggers contextual typing, which needs to be updated to understand that =>'s `this` is void. +var specifiedToImplicitVoid = explicitStructural; +var reconstructed = { + n: 12, + explicitThis: c.explicitThis, + implicitThis: c.implicitThis, + explicitC: c.explicitC, + explicitProperty: c.explicitProperty, + explicitVoid: c.explicitVoid +}; +; +// lambdas have this: void for assignability purposes (and this unbound (free) for body checking) +var d = new D(); +var explicitXProperty; +// from differing object types +c.explicitC = function (m) { return this.x + m; }; +c.explicitProperty = explicitXProperty; +c.explicitC = d.implicitD; +c.explicitC = d.explicitD; +c.explicitC = d.explicitThis; +c.explicitThis = d.implicitD; +c.explicitThis = d.explicitD; +c.explicitThis = d.explicitThis; +c.explicitProperty = d.explicitD; +c.explicitProperty = d.implicitD; +c.explicitThis = d.explicitThis; +c.explicitVoid = d.implicitD; +c.explicitVoid = d.explicitD; +c.explicitVoid = d.explicitThis; +/// class-based implicit assignability (with inheritance!) /// +var Base1 = (function () { + function Base1() { + } + Base1.prototype.implicit = function () { return this.x; }; + Base1.prototype.explicit = function () { return this.x; }; + Base1.implicitStatic = function () { return this.x; }; + Base1.explicitStatic = function () { return this.x; }; + return Base1; +}()); +var Derived1 = (function (_super) { + __extends(Derived1, _super); + function Derived1() { + _super.apply(this, arguments); + } + return Derived1; +}(Base1)); +var Base2 = (function () { + function Base2() { + } + Base2.prototype.implicit = function () { return this.y; }; + Base2.prototype.explicit = function () { return this.x; }; + return Base2; +}()); +var Derived2 = (function (_super) { + __extends(Derived2, _super); + function Derived2() { + _super.apply(this, arguments); + } + return Derived2; +}(Base2)); +var b1 = new Base1(); +var d1 = new Derived1(); +var b2 = new Base2(); +var d2 = new Derived2(); +b1.implicit = b2.implicit; // error, 'this.y' not in C: { x } (c assignable to e) +b1.explicit = b2.implicit; // error, 'y' not in C: { x } (c assignable to e) +d1.explicit = b2.implicit; // error, 'y' not in C: { x } (c assignable to e) +////// use this-type for construction with new //// +function VoidThis() { +} +function ImplicitVoidThis() { +} +var voidThis = new VoidThis(); +var implicitVoidThis = new ImplicitVoidThis(); +///// parse errors ///// +function notFirst(a, this) { return this.n; } +function modifiers(, C) { + if ( === void 0) { = this; } + return this.n; +} +function restParam(, C) { return this.n; } +function optional(C) { return this.n; } +function decorated(, C) { + if ( === void 0) { = this; } + return this.n; +} +new C(); +number; +{ + return this.n; +} +// can't name parameters 'this' in a lambda. +c.explicitProperty = (this, m); +m + this.n; diff --git a/tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts b/tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts new file mode 100644 index 0000000000000..34d1ebd4a8ee6 --- /dev/null +++ b/tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts @@ -0,0 +1,34 @@ +interface I { + explicitThis(this: this, m: number): number; +} +interface Unused { + implicitNoThis(m: number): number; +} +class C implements I { + n: number; + explicitThis(this: this, m: number): number { + return this.n + m; + } + implicitThis(m: number): number { + return this.n + m; + } + explicitVoid(this: void, m: number): number { + return m + 1; + } +} +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 } +}; +let i: I = o; +let x = i.explicitThis; +let n = x(12); // callee:void doesn't match this:I +let u: Unused; +let y = u.implicitNoThis; +n = y(12); // ok, callee:void matches this:any +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; diff --git a/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts b/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts new file mode 100644 index 0000000000000..623c880d33944 --- /dev/null +++ b/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts @@ -0,0 +1,209 @@ +// @strictThis: true +// body checking +class C { + n: number; + explicitThis(this: this, m: number): number { + return this.n + m; + } + implicitThis(m: number): number { + return this.n + m; + } + explicitC(this: C, m: number): number { + return this.n + m; + } + explicitProperty(this: {n: number}, m: number): number { + return this.n + m; + } + explicitVoid(this: void, m: number): number { + return m + 1; + } +} +class D extends C { } +class B { + n: number; +} +interface I { + a: number; + explicitVoid1(this: void): number; + explicitVoid2(this: void): number; + explicitStructural(this: {a: number}): number; + explicitInterface(this: I): number; + explicitThis(this: this): number; + implicitMethod(): number; + implicitFunction: () => number; +} +function explicitStructural(this: { y: number }, x: number): number { + return x + this.y; +} +function justThis(this: { y: number }): number { + return this.y; +} +function implicitThis(n: number): number { + return 12; +} +let impl: I = { + a: 12, + explicitVoid2: () => this.a, // ok, this: any because it refers to some outer object (window?) + explicitVoid1() { return 12; }, + explicitStructural() { + return this.a; + }, + explicitInterface() { + return this.a; + }, + explicitThis() { + return this.a; + }, + implicitMethod() { + return this.a; + }, + implicitFunction: () => this.a, // ok, this: any because it refers to some outer object (window?) +} +impl.explicitVoid1 = function () { return 12; }; +impl.explicitVoid2 = () => 12; +impl.explicitStructural = function() { return this.a; }; +impl.explicitInterface = function() { return this.a; }; +impl.explicitStructural = () => 12; +impl.explicitInterface = () => 12; +impl.explicitThis = function () { return this.a; }; +impl.implicitMethod = function () { return this.a; }; +impl.implicitMethod = () => 12; +impl.implicitFunction = () => this.a; // ok, this: any because it refers to some outer object (window?) +// parameter checking +let ok: {y: number, f: (this: { y: number }, x: number) => number} = { y: 12, f: explicitStructural }; +let implicitAnyOk: {notSpecified: number, f: (x: number) => number} = { notSpecified: 12, f: implicitThis }; +ok.f(13); +implicitThis(12); +implicitAnyOk.f(12); + +let c = new C(); +let d = new D(); +let ripped = c.explicitC; +c.explicitC(12); +c.explicitProperty(12); +c.explicitThis(12); +c.implicitThis(12); +d.explicitC(12); +d.explicitProperty(12); +d.explicitThis(12); +d.implicitThis(12); +let reconstructed: { + n: number, + explicitThis(this: C, m: number): number, // note: this: this is not allowed in an object literal type. + implicitThis(m: number): number, + explicitC(this: C, m: number): number, + explicitProperty: (this: {n : number}, m: number) => number, + explicitVoid(this: void, m: number): number, +} = { + n: 12, + explicitThis: c.explicitThis, + implicitThis: c.implicitThis, + explicitC: c.explicitC, + explicitProperty: c.explicitProperty, + explicitVoid: c.explicitVoid +}; +reconstructed.explicitProperty(11); +reconstructed.implicitThis(11); + +// assignment checking +let unboundToSpecified: (this: { y: number }, x: number) => number = x => x + this.y; // ok, this:any +let specifiedToSpecified: (this: {y: number}, x: number) => number = explicitStructural; +let anyToSpecified: (this: { y: number }, x: number) => number = function(x: number): number { return x + 12; }; + +let unspecifiedLambda: (x: number) => number = x => x + 12; +let specifiedLambda: (this: void, x: number) => number = x => x + 12; +let unspecifiedLambdaToSpecified: (this: {y: number}, x: number) => number = unspecifiedLambda; +let specifiedLambdaToSpecified: (this: {y: number}, x: number) => number = specifiedLambda; + + +let explicitCFunction: (this: C, m: number) => number; +let explicitPropertyFunction: (this: {n: number}, m: number) => number; +c.explicitC = explicitCFunction; +c.explicitC = function(this: C, m: number) { return this.n + m }; +c.explicitProperty = explicitPropertyFunction; +c.explicitProperty = function(this: {n: number}, m: number) { return this.n + m }; +c.explicitProperty = reconstructed.explicitProperty; + +// lambdas are assignable to anything +c.explicitC = m => m; +c.explicitThis = m => m; +c.explicitProperty = m => m; + +// this inside lambdas refer to outer scope +// the outer-scoped lambda at top-level is still just `any` +c.explicitC = m => m + this.n; +c.explicitThis = m => m + this.n; +c.explicitProperty = m => m + this.n; + +//NOTE: this=C here, I guess? +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.implicitThis = reconstructed.implicitThis; + +c.explicitC = function(this: B, m: number) { return this.n + m }; + +// this:void compatibility +c.explicitVoid = n => n; + +// class-based assignability +class Base1 { + x: number; + public implicit(): number { return this.x; } + explicit(this: Base1): number { return this.x; } + static implicitStatic(): number { return this.y; } + static explicitStatic(this: typeof Base1): number { return this.y; } + static y: number; + +} +class Derived1 extends Base1 { + y: number +} +class Base2 { + y: number + implicit(): number { return this.y; } + explicit(this: Base1): number { return this.x; } +} +class Derived2 extends Base2 { + x: number +} +let b1 = new Base1(); +let b2 = new Base2(); +let d1 = new Derived1(); +let d2 = new Derived2(); +d2.implicit = d1.implicit // ok, 'x' and 'y' in { x, y } (d assignable to f and vice versa) +d1.implicit = d2.implicit // ok, 'x' and 'y' in { x, y } (f assignable to d and vice versa) + +// bivariance-allowed cases +d1.implicit = b2.implicit // ok, 'y' in D: { x, y } (d assignable e) +d2.implicit = d1.explicit // ok, 'y' in { x, y } (c assignable to f) +b1.implicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) +b1.explicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) + +////// use this-type for construction with new //// +function InterfaceThis(this: I) { + this.a = 12; +} +function LiteralTypeThis(this: {x: string}) { + this.x = "ok"; +} +function AnyThis(this: any) { + this.x = "ok"; +} +let interfaceThis = new InterfaceThis(); +let literalTypeThis = new LiteralTypeThis(); +let anyThis = new AnyThis(); + +//// type parameter inference //// +declare var f: { + (this: void, x: number): number, + call(this: (...argArray: any[]) => U, ...argArray: any[]): U; +}; +let n: number = f.call(12); + +function missingTypeIsImplicitAny(this, a: number) { return a; } \ No newline at end of file diff --git a/tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts b/tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts new file mode 100644 index 0000000000000..3fba9ad8a7399 --- /dev/null +++ b/tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts @@ -0,0 +1,193 @@ +// @strictThis: true +class C { + n: number; + explicitThis(this: this, m: number): number { + return this.n + m; + } + implicitThis(m: number): number { + return this.n + m; + } + explicitC(this: C, m: number): number { + return this.n + m; + } + explicitProperty(this: {n: number}, m: number): number { + return this.n + m; + } + explicitVoid(this: void, m: number): number { + return this.n + m; // 'n' doesn't exist on type 'void'. + } +} +class D { + x: number; + explicitThis(this: this, m: number): number { + return this.x + m; + } + explicitD(this: D, m: number): number { + return this.x + m; + } + implicitD(m: number): number { + return this.x + m; + } +} +interface I { + a: number; + explicitVoid1(this: void): number; + explicitVoid2(this: void): number; + explicitStructural(this: {a: number}): number; + explicitInterface(this: I): number; + explicitThis(this: this): number; // TODO: Allow `this` types for interfaces + implicitMethod(): number; + implicitFunction: () => number; +} +let impl: I = { + a: 12, + explicitVoid1() { + return this.a; // error, no 'a' in 'void' + }, + explicitVoid2: () => this.a, // ok, `this:any` because it refers to an outer object + explicitStructural: () => 12, + explicitInterface: () => 12, + explicitThis() { + return this.a; + }, + implicitMethod() { + return this.a; // ok, I.a: number + }, + implicitFunction: function () { return this.a; } // TODO: error 'a' not found in 'void' +} +let implExplicitStructural = impl.explicitStructural; +implExplicitStructural(); // error, no 'a' in 'void' +let implExplicitInterface = impl.explicitInterface; +implExplicitInterface(); // error, no 'a' in 'void' +let implImplicitMethod = impl.implicitMethod; +implImplicitMethod(); // error, no 'a' in 'void' +function explicitStructural(this: { y: number }, x: number): number { + return x + this.y; +} +function propertyName(this: { y: number }, x: number): number { + return x + this.notFound; +} +function voidThisSpecified(this: void, x: number): number { + return x + this.notSpecified; +} +function noThisSpecified(x: number): number { + // this:void unless loose-this is on + return x + this.notSpecified; +} +let ok: {y: number, f: (this: { y: number }, x: number) => number} = { y: 12, explicitStructural }; +let wrongPropertyType: {y: string, f: (this: { y: number }, x: number) => number} = { y: 'foo', explicitStructural }; +let wrongPropertyName: {wrongName: number, f: (this: { y: number }, x: number) => number} = { wrongName: 12, explicitStructural }; + +ok.f(); // not enough arguments +ok.f('wrong type'); +ok.f(13, 'too many arguments'); +wrongPropertyType.f(13); +wrongPropertyName.f(13); + +let c = new C(); +c.explicitC(); // not enough arguments +c.explicitC('wrong type'); +c.explicitC(13, 'too many arguments'); +c.explicitThis(); // not enough arguments +c.explicitThis('wrong type 2'); +c.explicitThis(14, 'too many arguments 2'); +c.implicitThis(); // not enough arguments +c.implicitThis('wrong type 2'); +c.implicitThis(14, 'too many arguments 2'); +c.explicitProperty(); // not enough arguments +c.explicitProperty('wrong type 3'); +c.explicitProperty(15, 'too many arguments 3'); + +// oops, this triggers contextual typing, which needs to be updated to understand that =>'s `this` is void. +let specifiedToImplicitVoid: (x: number) => number = explicitStructural; + +let reconstructed: { + n: number, + explicitThis(this: C, m: number): number, // note: this: this is not allowed in an object literal type. + implicitThis(m: number): number, + explicitC(this: C, m: number): number, + explicitProperty: (this: {n : number}, m: number) => number, + explicitVoid(this: void, m: number): number, +} = { + n: 12, + explicitThis: c.explicitThis, + implicitThis: c.implicitThis, // error not assignable -- c.this:c not assignable to this:void. + explicitC: c.explicitC, + explicitProperty: c.explicitProperty, + explicitVoid: c.explicitVoid +};; + +// lambdas have this: void for assignability purposes (and this unbound (free) for body checking) +let d = new D(); +let explicitXProperty: (this: { x: number }, m: number) => number; + +// from differing object types +c.explicitC = function(this: D, m: number) { return this.x + m }; +c.explicitProperty = explicitXProperty; + +c.explicitC = d.implicitD; +c.explicitC = d.explicitD; +c.explicitC = d.explicitThis; +c.explicitThis = d.implicitD; +c.explicitThis = d.explicitD; +c.explicitThis = d.explicitThis; +c.explicitProperty = d.explicitD; +c.explicitProperty = d.implicitD; +c.explicitThis = d.explicitThis; +c.explicitVoid = d.implicitD; +c.explicitVoid = d.explicitD; +c.explicitVoid = d.explicitThis; + +/// class-based implicit assignability (with inheritance!) /// + +class Base1 { + x: number + public implicit(): number { return this.x; } + explicit(this: Base1): number { return this.x; } + static implicitStatic(): number { return this.x; } + static explicitStatic(this: typeof Base1): number { return this.x; } +} +class Derived1 extends Base1 { + y: number +} +class Base2 { + y: number + implicit(): number { return this.y; } + explicit(this: Base1): number { return this.x; } +} +class Derived2 extends Base2 { + x: number +} + + +let b1 = new Base1(); +let d1 = new Derived1(); +let b2 = new Base2(); +let d2 = new Derived2(); + +b1.implicit = b2.implicit // error, 'this.y' not in C: { x } (c assignable to e) +b1.explicit = b2.implicit // error, 'y' not in C: { x } (c assignable to e) + +d1.explicit = b2.implicit // error, 'y' not in C: { x } (c assignable to e) + +////// use this-type for construction with new //// +function VoidThis(this: void) { + +} +function ImplicitVoidThis() { + +} +let voidThis = new VoidThis(); +let implicitVoidThis = new ImplicitVoidThis(); + + +///// parse errors ///// +function notFirst(a: number, this: C): number { return this.n; } +function modifiers(async this: C): number { return this.n; } +function restParam(...this: C): number { return this.n; } +function optional(this?: C): number { return this.n; } +function decorated(@deco() this: C): number { return this.n; } +function initializer(this: C = new C()): number { return this.n; } + +// can't name parameters 'this' in a lambda. +c.explicitProperty = (this, m) => m + this.n; diff --git a/tests/cases/fourslash/memberListOnExplicitThis.ts b/tests/cases/fourslash/memberListOnExplicitThis.ts new file mode 100644 index 0000000000000..cf57717183c1b --- /dev/null +++ b/tests/cases/fourslash/memberListOnExplicitThis.ts @@ -0,0 +1,30 @@ +// @strictThis: true +/// + +////interface Restricted { +//// n: number; +////} +////class C1 implements Restricted { +//// n: number; +//// m: number; +//// f() {this./*1*/} // test on 'this.' +//// g(this: Restricted) {this./*2*/} +////} +////function f() {this./*3*/} +////function g(this: Restricted) {this./*4*/} + +goTo.marker('1'); +verify.memberListContains('f', '(method) C1.f(this: this): void'); +verify.memberListContains('g', '(method) C1.g(this: Restricted): void'); +verify.memberListContains('n', '(property) C1.n: number'); +verify.memberListContains('m', '(property) C1.m: number'); + +goTo.marker('2'); +verify.memberListContains('n', '(property) Restricted.n: number'); + +goTo.marker('3'); +verify.memberListIsEmpty(); + +goTo.marker('4'); +verify.memberListContains('n', '(property) Restricted.n: number'); + From a4f1154377bc62320ddb73d2ac448f3bc0089768 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 29 Jan 2016 14:51:35 -0800 Subject: [PATCH 09/41] Fix free function bug in cachingInServerLSHost --- tests/cases/unittests/cachingInServerLSHost.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/cases/unittests/cachingInServerLSHost.ts b/tests/cases/unittests/cachingInServerLSHost.ts index 59f97f434e6cc..6d7b3fdbc28b1 100644 --- a/tests/cases/unittests/cachingInServerLSHost.ts +++ b/tests/cases/unittests/cachingInServerLSHost.ts @@ -123,7 +123,7 @@ module ts { } fileExistsIsCalled = true; assert.isTrue(fileName.indexOf('/f2.') !== -1); - return originalFileExists(fileName); + return originalFileExists.call(serverHost, fileName); }; let newContent = `import {x} from "f2"`; rootScriptInfo.editContent(0, rootScriptInfo.content.length, newContent); @@ -147,7 +147,7 @@ module ts { } fileExistsCalled = true; assert.isTrue(fileName.indexOf('/f1.') !== -1); - return originalFileExists(fileName); + return originalFileExists.call(serverHost, fileName); }; let newContent = `import {x} from "f1"`; @@ -192,7 +192,7 @@ module ts { fileExistsCalledForBar = fileName.indexOf("/bar.") !== -1; } - return originalFileExists(fileName); + return originalFileExists.call(serverHost, fileName); }; let { project, rootScriptInfo } = createProject(root.name, serverHost); From d030889166b56fe3e4a2fb080711807245422c98 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 29 Jan 2016 14:52:47 -0800 Subject: [PATCH 10/41] Update baselines 1. Display of `this` changes for quick info. 2. The type of Function.call/apply/bind is more precise. --- .../assignmentToObjectAndFunction.errors.txt | 4 +- ...ArrowFunctionCapturesArguments_es6.symbols | 4 +- ...ncArrowFunctionCapturesArguments_es6.types | 12 +-- ...nctionsInFunctionParameterDefaults.symbols | 4 +- ...functionsInFunctionParameterDefaults.types | 4 +- .../baselines/reference/functionType.symbols | 4 +- tests/baselines/reference/functionType.types | 6 +- .../genericTypeParameterEquivalence2.symbols | 4 +- .../genericTypeParameterEquivalence2.types | 6 +- ...llSignatureAppearsToBeFunctionType.symbols | 8 +- ...CallSignatureAppearsToBeFunctionType.types | 8 +- .../returnTypeParameterWithModules.symbols | 4 +- .../returnTypeParameterWithModules.types | 4 +- tests/cases/fourslash/commentsClassMembers.ts | 2 +- .../fourslash/instanceTypesForGenericType1.ts | 2 +- tests/cases/fourslash/quickInfoOnThis.ts | 77 +++++++++++++++++-- tests/cases/fourslash/thisBindingInLambda.ts | 2 +- 17 files changed, 108 insertions(+), 47 deletions(-) diff --git a/tests/baselines/reference/assignmentToObjectAndFunction.errors.txt b/tests/baselines/reference/assignmentToObjectAndFunction.errors.txt index 2e85ee101f539..454ac41b5b82a 100644 --- a/tests/baselines/reference/assignmentToObjectAndFunction.errors.txt +++ b/tests/baselines/reference/assignmentToObjectAndFunction.errors.txt @@ -5,7 +5,7 @@ tests/cases/compiler/assignmentToObjectAndFunction.ts(8,5): error TS2322: Type ' Property 'apply' is missing in type '{}'. tests/cases/compiler/assignmentToObjectAndFunction.ts(29,5): error TS2322: Type 'typeof bad' is not assignable to type 'Function'. Types of property 'apply' are incompatible. - Type 'number' is not assignable to type '(thisArg: any, argArray?: any) => any'. + Type 'number' is not assignable to type '{ (this: (this: T, ...argArray: any[]) => U, thisArg: T, argArray?: any): U; (this: Function, thisArg: any, argArray?: any): any; }'. ==== tests/cases/compiler/assignmentToObjectAndFunction.ts (3 errors) ==== @@ -48,4 +48,4 @@ tests/cases/compiler/assignmentToObjectAndFunction.ts(29,5): error TS2322: Type ~~~~~~~~~~ !!! error TS2322: Type 'typeof bad' is not assignable to type 'Function'. !!! error TS2322: Types of property 'apply' are incompatible. -!!! error TS2322: Type 'number' is not assignable to type '(thisArg: any, argArray?: any) => any'. \ No newline at end of file +!!! error TS2322: Type 'number' is not assignable to type '{ (this: (this: T, ...argArray: any[]) => U, thisArg: T, argArray?: any): U; (this: Function, thisArg: any, argArray?: any): any; }'. \ No newline at end of file diff --git a/tests/baselines/reference/asyncArrowFunctionCapturesArguments_es6.symbols b/tests/baselines/reference/asyncArrowFunctionCapturesArguments_es6.symbols index 2f516d7d7587b..bc061211b88c5 100644 --- a/tests/baselines/reference/asyncArrowFunctionCapturesArguments_es6.symbols +++ b/tests/baselines/reference/asyncArrowFunctionCapturesArguments_es6.symbols @@ -10,9 +10,9 @@ class C { var fn = async () => await other.apply(this, arguments); >fn : Symbol(fn, Decl(asyncArrowFunctionCapturesArguments_es6.ts, 3, 9)) ->other.apply : Symbol(Function.apply, Decl(lib.d.ts, --, --)) +>other.apply : Symbol(Function.apply, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >other : Symbol(other, Decl(asyncArrowFunctionCapturesArguments_es6.ts, 1, 13)) ->apply : Symbol(Function.apply, Decl(lib.d.ts, --, --)) +>apply : Symbol(Function.apply, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >this : Symbol(C, Decl(asyncArrowFunctionCapturesArguments_es6.ts, 0, 0)) >arguments : Symbol(arguments) } diff --git a/tests/baselines/reference/asyncArrowFunctionCapturesArguments_es6.types b/tests/baselines/reference/asyncArrowFunctionCapturesArguments_es6.types index 76853858c5cf2..18a08ffface58 100644 --- a/tests/baselines/reference/asyncArrowFunctionCapturesArguments_es6.types +++ b/tests/baselines/reference/asyncArrowFunctionCapturesArguments_es6.types @@ -9,13 +9,13 @@ class C { >other : () => void var fn = async () => await other.apply(this, arguments); ->fn : () => Promise ->async () => await other.apply(this, arguments) : () => Promise ->await other.apply(this, arguments) : any ->other.apply(this, arguments) : any ->other.apply : (thisArg: any, argArray?: any) => any +>fn : () => Promise +>async () => await other.apply(this, arguments) : () => Promise +>await other.apply(this, arguments) : void +>other.apply(this, arguments) : void +>other.apply : { (this: (this: T, ...argArray: any[]) => U, thisArg: T, argArray?: any): U; (this: Function, thisArg: any, argArray?: any): any; } >other : () => void ->apply : (thisArg: any, argArray?: any) => any +>apply : { (this: (this: T, ...argArray: any[]) => U, thisArg: T, argArray?: any): U; (this: Function, thisArg: any, argArray?: any): any; } >this : this >arguments : IArguments } diff --git a/tests/baselines/reference/fatarrowfunctionsInFunctionParameterDefaults.symbols b/tests/baselines/reference/fatarrowfunctionsInFunctionParameterDefaults.symbols index ea0ed9a605cb6..b836bc88573d7 100644 --- a/tests/baselines/reference/fatarrowfunctionsInFunctionParameterDefaults.symbols +++ b/tests/baselines/reference/fatarrowfunctionsInFunctionParameterDefaults.symbols @@ -12,7 +12,7 @@ function fn(x = () => this, y = x()) { } fn.call(4); // Should be 4 ->fn.call : Symbol(Function.call, Decl(lib.d.ts, --, --)) +>fn.call : Symbol(Function.call, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >fn : Symbol(fn, Decl(fatarrowfunctionsInFunctionParameterDefaults.ts, 0, 0)) ->call : Symbol(Function.call, Decl(lib.d.ts, --, --)) +>call : Symbol(Function.call, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) diff --git a/tests/baselines/reference/fatarrowfunctionsInFunctionParameterDefaults.types b/tests/baselines/reference/fatarrowfunctionsInFunctionParameterDefaults.types index 55d72e854d302..58c576bf24e2c 100644 --- a/tests/baselines/reference/fatarrowfunctionsInFunctionParameterDefaults.types +++ b/tests/baselines/reference/fatarrowfunctionsInFunctionParameterDefaults.types @@ -16,8 +16,8 @@ function fn(x = () => this, y = x()) { fn.call(4); // Should be 4 >fn.call(4) : any ->fn.call : (thisArg: any, ...argArray: any[]) => any +>fn.call : { (this: (this: T, ...argArray: any[]) => U, thisArg: T, ...argArray: any[]): U; (this: Function, thisArg: any, ...argArray: any[]): any; } >fn : (x?: () => any, y?: any) => any ->call : (thisArg: any, ...argArray: any[]) => any +>call : { (this: (this: T, ...argArray: any[]) => U, thisArg: T, ...argArray: any[]): U; (this: Function, thisArg: any, ...argArray: any[]): any; } >4 : number diff --git a/tests/baselines/reference/functionType.symbols b/tests/baselines/reference/functionType.symbols index 30a5a7cc4471d..65347d39b5a59 100644 --- a/tests/baselines/reference/functionType.symbols +++ b/tests/baselines/reference/functionType.symbols @@ -3,9 +3,9 @@ function salt() {} >salt : Symbol(salt, Decl(functionType.ts, 0, 0)) salt.apply("hello", []); ->salt.apply : Symbol(Function.apply, Decl(lib.d.ts, --, --)) +>salt.apply : Symbol(Function.apply, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >salt : Symbol(salt, Decl(functionType.ts, 0, 0)) ->apply : Symbol(Function.apply, Decl(lib.d.ts, --, --)) +>apply : Symbol(Function.apply, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) (new Function("return 5"))(); >Function : Symbol(Function, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) diff --git a/tests/baselines/reference/functionType.types b/tests/baselines/reference/functionType.types index e7ea7a47edfb2..9183ec4a13e37 100644 --- a/tests/baselines/reference/functionType.types +++ b/tests/baselines/reference/functionType.types @@ -3,10 +3,10 @@ function salt() {} >salt : () => void salt.apply("hello", []); ->salt.apply("hello", []) : any ->salt.apply : (thisArg: any, argArray?: any) => any +>salt.apply("hello", []) : void +>salt.apply : { (this: (this: T, ...argArray: any[]) => U, thisArg: T, argArray?: any): U; (this: Function, thisArg: any, argArray?: any): any; } >salt : () => void ->apply : (thisArg: any, argArray?: any) => any +>apply : { (this: (this: T, ...argArray: any[]) => U, thisArg: T, argArray?: any): U; (this: Function, thisArg: any, argArray?: any): any; } >"hello" : string >[] : undefined[] diff --git a/tests/baselines/reference/genericTypeParameterEquivalence2.symbols b/tests/baselines/reference/genericTypeParameterEquivalence2.symbols index cd558fdd10ada..1aa22b1e9946c 100644 --- a/tests/baselines/reference/genericTypeParameterEquivalence2.symbols +++ b/tests/baselines/reference/genericTypeParameterEquivalence2.symbols @@ -24,9 +24,9 @@ function compose(f: (b: B) => C, g: (a:A) => B): (a:A) => C { return f(g.apply(null, a)); >f : Symbol(f, Decl(genericTypeParameterEquivalence2.ts, 1, 26)) ->g.apply : Symbol(Function.apply, Decl(lib.d.ts, --, --)) +>g.apply : Symbol(Function.apply, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >g : Symbol(g, Decl(genericTypeParameterEquivalence2.ts, 1, 41)) ->apply : Symbol(Function.apply, Decl(lib.d.ts, --, --)) +>apply : Symbol(Function.apply, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >a : Symbol(a, Decl(genericTypeParameterEquivalence2.ts, 2, 21)) }; diff --git a/tests/baselines/reference/genericTypeParameterEquivalence2.types b/tests/baselines/reference/genericTypeParameterEquivalence2.types index 3b2c533543d31..9fdb03b0fbe49 100644 --- a/tests/baselines/reference/genericTypeParameterEquivalence2.types +++ b/tests/baselines/reference/genericTypeParameterEquivalence2.types @@ -26,10 +26,10 @@ function compose(f: (b: B) => C, g: (a:A) => B): (a:A) => C { return f(g.apply(null, a)); >f(g.apply(null, a)) : C >f : (b: B) => C ->g.apply(null, a) : any ->g.apply : (thisArg: any, argArray?: any) => any +>g.apply(null, a) : B +>g.apply : { (this: (this: T, ...argArray: any[]) => U, thisArg: T, argArray?: any): U; (this: Function, thisArg: any, argArray?: any): any; } >g : (a: A) => B ->apply : (thisArg: any, argArray?: any) => any +>apply : { (this: (this: T, ...argArray: any[]) => U, thisArg: T, argArray?: any): U; (this: Function, thisArg: any, argArray?: any): any; } >null : null >a : A diff --git a/tests/baselines/reference/objectTypeWithCallSignatureAppearsToBeFunctionType.symbols b/tests/baselines/reference/objectTypeWithCallSignatureAppearsToBeFunctionType.symbols index 60b7b08397aef..08d3d75e9dcf5 100644 --- a/tests/baselines/reference/objectTypeWithCallSignatureAppearsToBeFunctionType.symbols +++ b/tests/baselines/reference/objectTypeWithCallSignatureAppearsToBeFunctionType.symbols @@ -20,9 +20,9 @@ var r2b: (x: any, y?: any) => any = i.apply; >r2b : Symbol(r2b, Decl(objectTypeWithCallSignatureAppearsToBeFunctionType.ts, 9, 3)) >x : Symbol(x, Decl(objectTypeWithCallSignatureAppearsToBeFunctionType.ts, 9, 10)) >y : Symbol(y, Decl(objectTypeWithCallSignatureAppearsToBeFunctionType.ts, 9, 17)) ->i.apply : Symbol(Function.apply, Decl(lib.d.ts, --, --)) +>i.apply : Symbol(Function.apply, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >i : Symbol(i, Decl(objectTypeWithCallSignatureAppearsToBeFunctionType.ts, 7, 3)) ->apply : Symbol(Function.apply, Decl(lib.d.ts, --, --)) +>apply : Symbol(Function.apply, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) var b: { >b : Symbol(b, Decl(objectTypeWithCallSignatureAppearsToBeFunctionType.ts, 11, 3)) @@ -38,7 +38,7 @@ var rb4: (x: any, y?: any) => any = b.apply; >rb4 : Symbol(rb4, Decl(objectTypeWithCallSignatureAppearsToBeFunctionType.ts, 16, 3)) >x : Symbol(x, Decl(objectTypeWithCallSignatureAppearsToBeFunctionType.ts, 16, 10)) >y : Symbol(y, Decl(objectTypeWithCallSignatureAppearsToBeFunctionType.ts, 16, 17)) ->b.apply : Symbol(Function.apply, Decl(lib.d.ts, --, --)) +>b.apply : Symbol(Function.apply, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >b : Symbol(b, Decl(objectTypeWithCallSignatureAppearsToBeFunctionType.ts, 11, 3)) ->apply : Symbol(Function.apply, Decl(lib.d.ts, --, --)) +>apply : Symbol(Function.apply, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) diff --git a/tests/baselines/reference/objectTypeWithCallSignatureAppearsToBeFunctionType.types b/tests/baselines/reference/objectTypeWithCallSignatureAppearsToBeFunctionType.types index 74d8ef57d67bc..496734c9183dd 100644 --- a/tests/baselines/reference/objectTypeWithCallSignatureAppearsToBeFunctionType.types +++ b/tests/baselines/reference/objectTypeWithCallSignatureAppearsToBeFunctionType.types @@ -21,9 +21,9 @@ var r2b: (x: any, y?: any) => any = i.apply; >r2b : (x: any, y?: any) => any >x : any >y : any ->i.apply : (thisArg: any, argArray?: any) => any +>i.apply : { (this: (this: T, ...argArray: any[]) => U, thisArg: T, argArray?: any): U; (this: Function, thisArg: any, argArray?: any): any; } >i : I ->apply : (thisArg: any, argArray?: any) => any +>apply : { (this: (this: T, ...argArray: any[]) => U, thisArg: T, argArray?: any): U; (this: Function, thisArg: any, argArray?: any): any; } var b: { >b : () => void @@ -40,7 +40,7 @@ var rb4: (x: any, y?: any) => any = b.apply; >rb4 : (x: any, y?: any) => any >x : any >y : any ->b.apply : (thisArg: any, argArray?: any) => any +>b.apply : { (this: (this: T, ...argArray: any[]) => U, thisArg: T, argArray?: any): U; (this: Function, thisArg: any, argArray?: any): any; } >b : () => void ->apply : (thisArg: any, argArray?: any) => any +>apply : { (this: (this: T, ...argArray: any[]) => U, thisArg: T, argArray?: any): U; (this: Function, thisArg: any, argArray?: any): any; } diff --git a/tests/baselines/reference/returnTypeParameterWithModules.symbols b/tests/baselines/reference/returnTypeParameterWithModules.symbols index 7f8fab382a31d..e3b7c50948fea 100644 --- a/tests/baselines/reference/returnTypeParameterWithModules.symbols +++ b/tests/baselines/reference/returnTypeParameterWithModules.symbols @@ -12,13 +12,13 @@ module M1 { >A : Symbol(A, Decl(returnTypeParameterWithModules.ts, 1, 27)) return Array.prototype.reduce.apply(ar, e ? [f, e] : [f]); ->Array.prototype.reduce.apply : Symbol(Function.apply, Decl(lib.d.ts, --, --)) +>Array.prototype.reduce.apply : Symbol(Function.apply, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >Array.prototype.reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >Array.prototype : Symbol(ArrayConstructor.prototype, Decl(lib.d.ts, --, --)) >Array : Symbol(Array, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >prototype : Symbol(ArrayConstructor.prototype, Decl(lib.d.ts, --, --)) >reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) ->apply : Symbol(Function.apply, Decl(lib.d.ts, --, --)) +>apply : Symbol(Function.apply, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >ar : Symbol(ar, Decl(returnTypeParameterWithModules.ts, 1, 30)) >e : Symbol(e, Decl(returnTypeParameterWithModules.ts, 1, 36)) >f : Symbol(f, Decl(returnTypeParameterWithModules.ts, 1, 33)) diff --git a/tests/baselines/reference/returnTypeParameterWithModules.types b/tests/baselines/reference/returnTypeParameterWithModules.types index be09b8f46b0d7..ffb058daa0887 100644 --- a/tests/baselines/reference/returnTypeParameterWithModules.types +++ b/tests/baselines/reference/returnTypeParameterWithModules.types @@ -13,13 +13,13 @@ module M1 { return Array.prototype.reduce.apply(ar, e ? [f, e] : [f]); >Array.prototype.reduce.apply(ar, e ? [f, e] : [f]) : any ->Array.prototype.reduce.apply : (thisArg: any, argArray?: any) => any +>Array.prototype.reduce.apply : { (this: (this: T, ...argArray: any[]) => U, thisArg: T, argArray?: any): U; (this: Function, thisArg: any, argArray?: any): any; } >Array.prototype.reduce : { (callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any, initialValue?: any): any; (callbackfn: (previousValue: U, currentValue: any, currentIndex: number, array: any[]) => U, initialValue: U): U; } >Array.prototype : any[] >Array : ArrayConstructor >prototype : any[] >reduce : { (callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any, initialValue?: any): any; (callbackfn: (previousValue: U, currentValue: any, currentIndex: number, array: any[]) => U, initialValue: U): U; } ->apply : (thisArg: any, argArray?: any) => any +>apply : { (this: (this: T, ...argArray: any[]) => U, thisArg: T, argArray?: any): U; (this: Function, thisArg: any, argArray?: any): any; } >ar : any >e ? [f, e] : [f] : any[] >e : any diff --git a/tests/cases/fourslash/commentsClassMembers.ts b/tests/cases/fourslash/commentsClassMembers.ts index 54b4f0253d4f0..d719253a57b47 100644 --- a/tests/cases/fourslash/commentsClassMembers.ts +++ b/tests/cases/fourslash/commentsClassMembers.ts @@ -694,7 +694,7 @@ verify.completionListContains("a", "(parameter) a: number", "this is first param verify.quickInfoIs("(parameter) a: number", "this is first parameter a\nmore info about a"); goTo.marker('116'); -verify.quickInfoIs("class cWithConstructorProperty", ""); +verify.quickInfoIs("this: this", ""); goTo.marker('117'); verify.quickInfoIs("(local var) bbbb: number", ""); diff --git a/tests/cases/fourslash/instanceTypesForGenericType1.ts b/tests/cases/fourslash/instanceTypesForGenericType1.ts index 96ee175383e18..a3d119785bfe8 100644 --- a/tests/cases/fourslash/instanceTypesForGenericType1.ts +++ b/tests/cases/fourslash/instanceTypesForGenericType1.ts @@ -11,4 +11,4 @@ goTo.marker('1'); verify.quickInfoIs('(property) G.self: G'); goTo.marker('2'); -verify.quickInfoIs('class G'); \ No newline at end of file +verify.quickInfoIs('this: this'); \ No newline at end of file diff --git a/tests/cases/fourslash/quickInfoOnThis.ts b/tests/cases/fourslash/quickInfoOnThis.ts index c4eecfca5d5df..cef78efe0cc7f 100644 --- a/tests/cases/fourslash/quickInfoOnThis.ts +++ b/tests/cases/fourslash/quickInfoOnThis.ts @@ -1,15 +1,76 @@ +// @strictThis: true /// - -////function someFn1(someFn: { (): void; }) { } +////interface Restricted { +//// n: number; +////} +////function wrapper(wrapped: { (): void; }) { } ////class Foo { -//// public bar() { -//// someFn1( -//// function doSomething() { -//// console.log(th/**/is); +//// n: number; +//// public implicitThis() { +//// wrapper( +//// function implicitVoid() { +//// console.log(th/*1*/is); //// } //// ) +//// console.log(th/*2*/is); +//// } +//// public explicitInterface(th/*3*/is: Restricted) { +//// console.log(th/*4*/is); +//// } +//// public explicitClass(th/*5*/is: Foo) { +//// console.log(th/*6*/is); +//// } +////} +////class Bar { +//// public implicitThis() { +//// console.log(th/*7*/is); //// } +//// public explicitThis(this: Bar) { +//// console.log(thi/*8*/s); +//// } +////} +//// +////function implicitVoid(x: number): void { +//// return th/*9*/is; +////} +////function explicitVoid(th/*10*/is: void, x: number): void { +//// return th/*11*/is; ////} +////function explicitInterface(th/*12*/is: Restricted): void { +//// console.log(thi/*13*/s); +////} +////function explicitLiteral(th/*14*/is: { n: number }): void { +//// console.log(th/*15*/is); +////} + +goTo.marker('1'); +verify.quickInfoIs('void'); +goTo.marker('2'); +verify.quickInfoIs('this: this'); +goTo.marker('3'); +verify.quickInfoIs('(parameter) this: Restricted'); +goTo.marker('4'); +verify.quickInfoIs('this: Restricted'); +goTo.marker('5'); +verify.quickInfoIs('(parameter) this: Foo'); +goTo.marker('6'); +verify.quickInfoIs('this: Foo'); +goTo.marker('7'); +verify.quickInfoIs('this: this'); +goTo.marker('8'); +verify.quickInfoIs('this: Bar'); +goTo.marker('9'); +verify.quickInfoIs('void'); +goTo.marker('10'); +verify.quickInfoIs('(parameter) this: void'); +goTo.marker('11'); +verify.quickInfoIs('void'); +goTo.marker('12'); +verify.quickInfoIs('(parameter) this: Restricted'); +goTo.marker('13'); +verify.quickInfoIs('this: Restricted'); +goTo.marker('14'); -goTo.marker(); -verify.quickInfoIs('any'); +verify.quickInfoIs('(parameter) this: {\n n: number;\n}'); +goTo.marker('15'); +verify.quickInfoIs('this: {\n n: number;\n}'); \ No newline at end of file diff --git a/tests/cases/fourslash/thisBindingInLambda.ts b/tests/cases/fourslash/thisBindingInLambda.ts index f6dfdbdec0889..d9c43796bd8e3 100644 --- a/tests/cases/fourslash/thisBindingInLambda.ts +++ b/tests/cases/fourslash/thisBindingInLambda.ts @@ -9,4 +9,4 @@ ////} goTo.marker(); -verify.quickInfoIs('class Greeter'); +verify.quickInfoIs('this: this'); From 675e0816d40cbe1fcd269dc98fff5e8e19bbb9cd Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Tue, 2 Feb 2016 14:46:44 -0800 Subject: [PATCH 11/41] Make this-type of bind's return explicit --- src/lib/core.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/core.d.ts b/src/lib/core.d.ts index fe2fd6b79f627..5a94b21b0fb04 100644 --- a/src/lib/core.d.ts +++ b/src/lib/core.d.ts @@ -232,7 +232,7 @@ interface Function { * @param thisArg An object to which the this keyword can refer inside the new function. * @param argArray A list of arguments to be passed to the new function. */ - bind(this: (this: T, ...argArray: any[]) => U, thisArg: T, ...argArray: any[]): (...argArray: any[]) => U; + bind(this: (this: T, ...argArray: any[]) => U, thisArg: T, ...argArray: any[]): (this: void, ...argArray: any[]) => U; bind(this: Function, thisArg: any, ...argArray: any[]): any; prototype: any; From f6361cec665339077ee9df83f0fd887834c5c5a7 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Tue, 2 Feb 2016 16:00:52 -0800 Subject: [PATCH 12/41] Undo strictThis-clean changes Also fix other lint. --- src/compiler/checker.ts | 2 +- src/compiler/core.ts | 19 ++++++----- src/compiler/program.ts | 3 +- src/compiler/sourcemap.ts | 8 ++--- src/compiler/sys.ts | 2 +- src/compiler/types.ts | 16 +++++----- src/compiler/utilities.ts | 20 ++++++------ src/harness/harness.ts | 26 +++++++-------- src/harness/loggedIO.ts | 32 +++++++++---------- src/server/editorServices.ts | 2 +- src/server/node.d.ts | 4 +-- .../formatting/ruleOperationContext.ts | 4 +-- src/services/services.ts | 6 ++-- src/services/utilities.ts | 2 +- 14 files changed, 71 insertions(+), 75 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 3940be5d69852..bfa398f190d89 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4115,7 +4115,7 @@ namespace ts { else { parameters.push(paramSymbol); } - + if (param.type && param.type.kind === SyntaxKind.StringLiteralType) { hasStringLiterals = true; } diff --git a/src/compiler/core.ts b/src/compiler/core.ts index ab8de44ec98f0..21536da36ff26 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -818,26 +818,25 @@ namespace ts { getSignatureConstructor(): new (checker: TypeChecker) => Signature; } - // TODO: Add a 'this' parameter after I update the previous-version compiler function Symbol(flags: SymbolFlags, name: string) { - (this).flags = flags; - (this).name = name; - (this).declarations = undefined; + this.flags = flags; + this.name = name; + this.declarations = undefined; } function Type(checker: TypeChecker, flags: TypeFlags) { - (this).flags = flags; + this.flags = flags; } function Signature(checker: TypeChecker) { } function Node(kind: SyntaxKind, pos: number, end: number) { - (this).kind = kind; - (this).pos = pos; - (this).end = end; - (this).flags = NodeFlags.None; - (this).parent = undefined; + this.kind = kind; + this.pos = pos; + this.end = end; + this.flags = NodeFlags.None; + this.parent = undefined; } export let objectAllocator: ObjectAllocator = { diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 88c77aa57598f..803ae47b0fd5f 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -933,9 +933,8 @@ namespace ts { return noDiagnosticsTypeChecker || (noDiagnosticsTypeChecker = createTypeChecker(program, /*produceDiagnostics:*/ false)); } - // TODO: needs to have this: Program function emit(sourceFile?: SourceFile, writeFileCallback?: WriteFileCallback, cancellationToken?: CancellationToken): EmitResult { - return runWithCancellationToken(() => emitWorker((this), sourceFile, writeFileCallback, cancellationToken)); + return runWithCancellationToken(() => emitWorker(this, sourceFile, writeFileCallback, cancellationToken)); } function isEmitBlocked(emitFileName: string): boolean { diff --git a/src/compiler/sourcemap.ts b/src/compiler/sourcemap.ts index fb61f8b78b825..8abf1432b0c73 100644 --- a/src/compiler/sourcemap.ts +++ b/src/compiler/sourcemap.ts @@ -4,10 +4,10 @@ namespace ts { export interface SourceMapWriter { getSourceMapData(): SourceMapData; - setSourceFile: (sourceFile: SourceFile) => void; - emitPos: (pos: number) => void; - emitStart: (range: TextRange) => void; - emitEnd: (range: TextRange, stopOverridingSpan?: boolean) => void; + setSourceFile(sourceFile: SourceFile): void; + emitPos(pos: number): void; + emitStart(range: TextRange): void; + emitEnd(range: TextRange, stopOverridingSpan?: boolean): void; changeEmitSourcePos(): void; getText(): string; getSourceMappingURL(): string; diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 1a9da39bf9a0e..bf25d39aa4395 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -63,7 +63,7 @@ namespace ts { useCaseSensitiveFileNames?: boolean; echo(s: string): void; quit(exitCode?: number): void; - fileExists: (path: string) => boolean; + fileExists(path: string): boolean; directoryExists(path: string): boolean; createDirectory(path: string): void; resolvePath(path: string): string; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 9c2612d96b607..6e0ccc3bf664a 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1593,8 +1593,8 @@ namespace ts { } export interface ScriptReferenceHost { - getCompilerOptions: () => CompilerOptions; - getSourceFile: (fileName: string) => SourceFile; + getCompilerOptions(): CompilerOptions; + getSourceFile(fileName: string): SourceFile; getCurrentDirectory(): string; } @@ -1625,7 +1625,7 @@ namespace ts { /** * Get a list of files in the program */ - getSourceFiles: () => SourceFile[]; + getSourceFiles(): SourceFile[]; /** * Emits the JavaScript and declaration files. If targetSourceFile is not specified, then @@ -1650,7 +1650,7 @@ namespace ts { */ getTypeChecker(): TypeChecker; - /* @internal */ getCommonSourceDirectory: () => string; + /* @internal */ getCommonSourceDirectory(): string; // For testing purposes only. Should not be used by any other consumers (including the // language service). @@ -1905,11 +1905,11 @@ namespace ts { getReferencedImportDeclaration(node: Identifier): Declaration; getReferencedDeclarationWithCollidingName(node: Identifier): Declaration; isDeclarationWithCollidingName(node: Declaration): boolean; - isValueAliasDeclaration: (node: Node) => boolean; - isReferencedAliasDeclaration: (node: Node, checkChildren?: boolean) => boolean; + isValueAliasDeclaration(node: Node): boolean; + isReferencedAliasDeclaration(node: Node, checkChildren?: boolean): boolean; isTopLevelValueImportEqualsWithEntityName(node: ImportEqualsDeclaration): boolean; getNodeCheckFlags(node: Node): NodeCheckFlags; - isDeclarationVisible: (node: Declaration) => boolean; + isDeclarationVisible(node: Declaration): boolean; collectLinkedAliases(node: Identifier): Node[]; isImplementationOfOverload(node: FunctionLikeDeclaration): boolean; writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void; @@ -2430,7 +2430,7 @@ namespace ts { rootDir?: string; sourceMap?: boolean; sourceRoot?: string; - strictThis?: boolean, + strictThis?: boolean; suppressExcessPropertyErrors?: boolean; suppressImplicitAnyIndexErrors?: boolean; target?: ScriptTarget; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index bce821c375676..bab66eb0688bc 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -32,11 +32,11 @@ namespace ts { } export interface EmitHost extends ScriptReferenceHost { - getSourceFiles: () => SourceFile[]; + getSourceFiles(): SourceFile[]; - getCommonSourceDirectory: () => string; - getCanonicalFileName: (fileName: string) => string; - getNewLine: () => string; + getCommonSourceDirectory(): string; + getCanonicalFileName(fileName: string): string; + getNewLine(): string; isEmitBlocked(emitFileName: string): boolean; @@ -1869,11 +1869,11 @@ namespace ts { } export interface EmitTextWriter { - write: (s: string) => void; - writeTextOfNode: (text: string, node: Node) => void; - writeLine: () => void; - increaseIndent: () => void; - decreaseIndent: () => void; + write(s: string): void; + writeTextOfNode(text: string, node: Node): void; + writeLine(): void; + increaseIndent(): void; + decreaseIndent(): void; getText(): string; rawWrite(s: string): void; writeLiteral(s: string): void; @@ -2490,7 +2490,7 @@ namespace ts { * as the fallback implementation does not check for circular references by default. */ export const stringify: (value: any) => string = typeof JSON !== "undefined" && JSON.stringify - ? JSON.stringify + ? JSON.stringify : stringifyFallback; /** diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 3b211a0d91ac2..2b0c95c0a61b0 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -417,24 +417,24 @@ namespace Harness.Path { namespace Harness { export interface IO { - args(): string[]; newLine(): string; - readFile(this: ts.System | IO, path: string): string; - writeFile(path: string, contents: string): void; + getCurrentDirectory(): string; + useCaseSensitiveFileNames(): boolean; resolvePath(path: string): string; - fileExists: (fileName: string) => boolean; - directoryExists: (path: string) => boolean; + readFile(path: string): string; + writeFile(path: string, contents: string): void; + directoryName(path: string): string; createDirectory(path: string): void; - getExecutingFilePath(this: ts.System | IO): string; - getCurrentDirectory(): string; - readDirectory(path: string, extension?: string, exclude?: string[]): string[]; - getMemoryUsage?(): number; - exit(exitCode?: number): void; + fileExists(fileName: string): boolean; + directoryExists(path: string): boolean; deleteFile(fileName: string): void; - directoryName: (path: string) => string; listFiles(path: string, filter: RegExp, options?: { recursive?: boolean }): string[]; - log: (text: string) => void; - useCaseSensitiveFileNames(): boolean; + log(text: string): void; + getMemoryUsage?(): number; + args(): string[]; + getExecutingFilePath(): string; + exit(exitCode?: number): void; + readDirectory(path: string, extension?: string, exclude?: string[]): string[]; } export var IO: IO; diff --git a/src/harness/loggedIO.ts b/src/harness/loggedIO.ts index dbc05112f3ef0..cc5e06ab920f9 100644 --- a/src/harness/loggedIO.ts +++ b/src/harness/loggedIO.ts @@ -70,11 +70,11 @@ interface IOLog { interface PlaybackControl { startReplayFromFile(logFileName: string): void; - startReplayFromString(this: PlaybackControl, logContents: string): void; - startReplayFromData(this: PlaybackControl, log: IOLog): void; + startReplayFromString(logContents: string): void; + startReplayFromData(log: IOLog): void; endReplay(): void; startRecord(logFileName: string): void; - endRecord(this: PlaybackControl): void; + endRecord(): void; } namespace Playback { @@ -127,8 +127,6 @@ namespace Playback { function initWrapper(wrapper: PlaybackSystem, underlying: ts.System): void; function initWrapper(wrapper: PlaybackIO, underlying: Harness.IO): void; function initWrapper(wrapper: PlaybackSystem | PlaybackIO, underlying: ts.System | Harness.IO): void { - // TODO: Define a common interface over ts.System | Harness.IO and stop passing a union type. - const underlyingShim: any = underlying; ts.forEach(Object.keys(underlying), prop => { (wrapper)[prop] = (underlying)[prop]; }); @@ -156,20 +154,20 @@ namespace Playback { }; wrapper.startReplayFromFile = logFn => { - wrapper.startReplayFromString(underlyingShim.readFile(logFn)); + wrapper.startReplayFromString(underlying.readFile(logFn)); }; wrapper.endRecord = () => { if (recordLog !== undefined) { let i = 0; const fn = () => recordLogFileNameBase + i + ".json"; - while (underlyingShim.fileExists(fn())) i++; - underlyingShim.writeFile(fn(), JSON.stringify(recordLog)); + while (underlying.fileExists(fn())) i++; + underlying.writeFile(fn(), JSON.stringify(recordLog)); recordLog = undefined; } }; wrapper.fileExists = recordReplay(wrapper.fileExists, underlying)( - path => callAndRecord(underlyingShim.fileExists(path), recordLog.fileExists, { path }), + path => callAndRecord(underlying.fileExists(path), recordLog.fileExists, { path }), memoize(path => { // If we read from the file, it must exist if (findResultByPath(wrapper, replayLog.filesRead, path, null) !== null) { @@ -186,10 +184,10 @@ namespace Playback { return replayLog.executingPath; } else if (recordLog !== undefined) { - return recordLog.executingPath = underlyingShim.getExecutingFilePath(); + return recordLog.executingPath = underlying.getExecutingFilePath(); } else { - return underlyingShim.getExecutingFilePath(); + return underlying.getExecutingFilePath(); } }; @@ -198,20 +196,20 @@ namespace Playback { return replayLog.currentDirectory || ""; } else if (recordLog !== undefined) { - return recordLog.currentDirectory = underlyingShim.getCurrentDirectory(); + return recordLog.currentDirectory = underlying.getCurrentDirectory(); } else { - return underlyingShim.getCurrentDirectory(); + return underlying.getCurrentDirectory(); } }; wrapper.resolvePath = recordReplay(wrapper.resolvePath, underlying)( - path => callAndRecord(underlyingShim.resolvePath(path), recordLog.pathsResolved, { path }), + path => callAndRecord(underlying.resolvePath(path), recordLog.pathsResolved, { path }), memoize(path => findResultByFields(replayLog.pathsResolved, { path }, !ts.isRootedDiskPath(ts.normalizeSlashes(path)) && replayLog.currentDirectory ? replayLog.currentDirectory + "/" + path : ts.normalizeSlashes(path)))); wrapper.readFile = recordReplay(wrapper.readFile, underlying)( path => { - const result = underlyingShim.readFile(path); + const result = underlying.readFile(path); const logEntry = { path, codepage: 0, result: { contents: result, codepage: 0 } }; recordLog.filesRead.push(logEntry); return result; @@ -228,14 +226,14 @@ namespace Playback { (path, extension, exclude) => findResultByPath(wrapper, replayLog.directoriesRead.filter(d => d.extension === extension && ts.arrayIsEqualTo(d.exclude, exclude)), path)); wrapper.writeFile = recordReplay(wrapper.writeFile, underlying)( - (path: string, contents: string) => callAndRecord(underlyingShim.writeFile(path, contents), recordLog.filesWritten, { path, contents, bom: false }), + (path: string, contents: string) => callAndRecord(underlying.writeFile(path, contents), recordLog.filesWritten, { path, contents, bom: false }), (path: string, contents: string) => noOpReplay("writeFile")); wrapper.exit = (exitCode) => { if (recordLog !== undefined) { wrapper.endRecord(); } - underlyingShim.exit(exitCode); + underlying.exit(exitCode); }; } diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 5516b18e0de3d..e2ec5cc159f8f 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -1834,7 +1834,7 @@ namespace ts.server { if (!rangeEnd) { rangeEnd = this.root.charCount(); } - const walkFns: ILineIndexWalker = { + const walkFns = { goSubtree: true, done: false, leaf: function (relativeStart: number, relativeLength: number, ll: LineLeaf) { diff --git a/src/server/node.d.ts b/src/server/node.d.ts index 8e4d8c28e9b9d..0bde0bb6602cc 100644 --- a/src/server/node.d.ts +++ b/src/server/node.d.ts @@ -68,7 +68,7 @@ interface BufferConstructor { new (array: any[]): Buffer; prototype: Buffer; isBuffer(obj: any): boolean; - byteLength: (string: string, encoding?: string) => number; + byteLength(string: string, encoding?: string): number; concat(list: Buffer[], totalLength?: number): Buffer; } declare var Buffer: BufferConstructor; @@ -190,7 +190,7 @@ declare namespace NodeJS { nextTick(callback: Function): void; umask(mask?: number): number; uptime(): number; - hrtime: (time?: number[]) => number[]; + hrtime(time?: number[]): number[]; // Worker send? (message: any, sendHandle?: any): void; diff --git a/src/services/formatting/ruleOperationContext.ts b/src/services/formatting/ruleOperationContext.ts index 3108095e8e6c6..47330faa0dda0 100644 --- a/src/services/formatting/ruleOperationContext.ts +++ b/src/services/formatting/ruleOperationContext.ts @@ -6,8 +6,8 @@ namespace ts.formatting { export class RuleOperationContext { private customContextChecks: { (context: FormattingContext): boolean; }[]; - constructor(...funcs: { (this: typeof Rules, context: FormattingContext): boolean; }[]) { - this.customContextChecks = <{ (this: any, context: FormattingContext): boolean }[]>funcs; + constructor(...funcs: { (context: FormattingContext): boolean; }[]) { + this.customContextChecks = funcs; } static Any: RuleOperationContext = new RuleOperationContext(); diff --git a/src/services/services.ts b/src/services/services.ts index 1a43f9a744b84..496dd7172ea81 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -19,15 +19,15 @@ namespace ts { getChildCount(sourceFile?: SourceFile): number; getChildAt(index: number, sourceFile?: SourceFile): Node; getChildren(sourceFile?: SourceFile): Node[]; - getStart(this: Node, sourceFile?: SourceFile): number; + getStart(sourceFile?: SourceFile): number; getFullStart(): number; - getEnd(this: Node): number; + getEnd(): number; getWidth(sourceFile?: SourceFile): number; getFullWidth(): number; getLeadingTriviaWidth(sourceFile?: SourceFile): number; getFullText(sourceFile?: SourceFile): string; getText(sourceFile?: SourceFile): string; - getFirstToken(this: Node, sourceFile?: SourceFile): Node; + getFirstToken(sourceFile?: SourceFile): Node; getLastToken(sourceFile?: SourceFile): Node; } diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 0363e45a64aee..afdc85fffd805 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -769,7 +769,7 @@ namespace ts { * The default is CRLF. */ export function getNewLineOrDefaultFromHost(host: LanguageServiceHost | LanguageServiceShimHost) { - return (host).getNewLine ? (host).getNewLine() : carriageReturnLineFeed; + return host.getNewLine ? host.getNewLine() : carriageReturnLineFeed; } export function lineBreakPart() { From 0af56c0ee201209d997193160567a7547a766fd2 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Tue, 2 Feb 2016 16:27:01 -0800 Subject: [PATCH 13/41] Update error numbers in new tests after merge --- .../reference/thisTypeInFunctionsNegative.errors.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt b/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt index 49a4380977a87..ce3b3eed6f826 100644 --- a/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt +++ b/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt @@ -91,8 +91,8 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(168,1): er tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(170,1): error TS2322: Type '(this: Base2) => number' is not assignable to type '(this: Base1) => number'. Types of parameters 'this' and 'this' are incompatible. Type 'Base1' is not assignable to type 'Base2'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(179,16): error TS2671: 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 TS2671: A function that is called with the 'new' keyword cannot have a 'this' type that is void. +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(185,26): error TS1003: Identifier expected. tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(185,30): error TS1005: ',' expected. @@ -442,10 +442,10 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(192,35): e } let voidThis = new VoidThis(); ~~~~~~~~~~~~~~ -!!! error TS2671: A function that is called with the 'new' keyword cannot have a 'this' type that is void. +!!! error TS2672: A function that is called with the 'new' keyword cannot have a 'this' type that is void. let implicitVoidThis = new ImplicitVoidThis(); ~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2671: A function that is called with the 'new' keyword cannot have a 'this' type that is void. +!!! error TS2672: A function that is called with the 'new' keyword cannot have a 'this' type that is void. ///// parse errors ///// From 8c87da523bd927a5579f6286946339ccc6d52de5 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 4 Feb 2016 15:43:43 -0800 Subject: [PATCH 14/41] 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. --- src/compiler/checker.ts | 66 ++++++++++--------- .../reference/contextualTyping24.errors.txt | 2 +- .../baselines/reference/contextualTyping24.js | 2 +- .../looseThisTypeInFunctions.errors.txt | 32 +++++++-- .../reference/looseThisTypeInFunctions.js | 31 ++++++++- .../reference/thisTypeInFunctions.js | 8 +-- .../reference/thisTypeInFunctions.symbols | 8 +-- .../reference/thisTypeInFunctions.types | 26 ++++---- .../thisTypeInFunctionsNegative.errors.txt | 6 +- tests/cases/compiler/contextualTyping24.ts | 2 +- .../thisType/looseThisTypeInFunctions.ts | 17 ++++- .../types/thisType/thisTypeInFuncTemp.ts | 27 ++++++++ .../types/thisType/thisTypeInFunctions.ts | 8 +-- 13 files changed, 162 insertions(+), 73 deletions(-) create mode 100644 tests/cases/conformance/types/thisType/thisTypeInFuncTemp.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9188cfff55d0f..2303aa539f656 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -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((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 || (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 && (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 ((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. diff --git a/tests/baselines/reference/contextualTyping24.errors.txt b/tests/baselines/reference/contextualTyping24.errors.txt index a172600e1c578..b4d0d5344562e 100644 --- a/tests/baselines/reference/contextualTyping24.errors.txt +++ b/tests/baselines/reference/contextualTyping24.errors.txt @@ -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. diff --git a/tests/baselines/reference/contextualTyping24.js b/tests/baselines/reference/contextualTyping24.js index 04c4ecba21b5d..14c1feeb03187 100644 --- a/tests/baselines/reference/contextualTyping24.js +++ b/tests/baselines/reference/contextualTyping24.js @@ -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; diff --git a/tests/baselines/reference/looseThisTypeInFunctions.errors.txt b/tests/baselines/reference/looseThisTypeInFunctions.errors.txt index 058a1555ed678..317446050a8e3 100644 --- a/tests/baselines/reference/looseThisTypeInFunctions.errors.txt +++ b/tests/baselines/reference/looseThisTypeInFunctions.errors.txt @@ -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'. + } \ No newline at end of file diff --git a/tests/baselines/reference/looseThisTypeInFunctions.js b/tests/baselines/reference/looseThisTypeInFunctions.js index 66677293c5b70..ecb9f650716de 100644 --- a/tests/baselines/reference/looseThisTypeInFunctions.js +++ b/tests/baselines/reference/looseThisTypeInFunctions.js @@ -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 +}; diff --git a/tests/baselines/reference/thisTypeInFunctions.js b/tests/baselines/reference/thisTypeInFunctions.js index 0798843fc44f5..f3ad84acb55aa 100644 --- a/tests/baselines/reference/thisTypeInFunctions.js +++ b/tests/baselines/reference/thisTypeInFunctions.js @@ -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 }; diff --git a/tests/baselines/reference/thisTypeInFunctions.symbols b/tests/baselines/reference/thisTypeInFunctions.symbols index 1d9ebbd0cf4c2..bb6a9acfdd06d 100644 --- a/tests/baselines/reference/thisTypeInFunctions.symbols +++ b/tests/baselines/reference/thisTypeInFunctions.symbols @@ -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)) diff --git a/tests/baselines/reference/thisTypeInFunctions.types b/tests/baselines/reference/thisTypeInFunctions.types index 36b458b91e0d7..b0fc9fc3300af 100644 --- a/tests/baselines/reference/thisTypeInFunctions.types +++ b/tests/baselines/reference/thisTypeInFunctions.types @@ -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 diff --git a/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt b/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt index ce3b3eed6f826..4e8efd187eb05 100644 --- a/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt +++ b/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt @@ -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. diff --git a/tests/cases/compiler/contextualTyping24.ts b/tests/cases/compiler/contextualTyping24.ts index be28ff3b04cc0..fad23fa313cd5 100644 --- a/tests/cases/compiler/contextualTyping24.ts +++ b/tests/cases/compiler/contextualTyping24.ts @@ -1 +1 @@ -var foo:(a:{():number; (i:number):number; })=>number; foo = function(a:string){return 5}; \ No newline at end of file +var foo:(a:{():number; (i:number):number; })=>number; foo = function(this: void, a:string){return 5}; \ No newline at end of file diff --git a/tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts b/tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts index 34d1ebd4a8ee6..3e8bdb1117085 100644 --- a/tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts +++ b/tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts @@ -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 +} diff --git a/tests/cases/conformance/types/thisType/thisTypeInFuncTemp.ts b/tests/cases/conformance/types/thisType/thisTypeInFuncTemp.ts new file mode 100644 index 0000000000000..2f4873031fb6f --- /dev/null +++ b/tests/cases/conformance/types/thisType/thisTypeInFuncTemp.ts @@ -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!!) \ No newline at end of file diff --git a/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts b/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts index 623c880d33944..f92b8ab4e15f6 100644 --- a/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts +++ b/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts @@ -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 }; From 2f74da112db6491d53321dc947660fb7c3f8e5d3 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 4 Feb 2016 16:01:10 -0800 Subject: [PATCH 15/41] Add specific error messages for out-of-place this Also remove lint in checker. --- src/compiler/checker.ts | 7 +- src/compiler/diagnosticMessages.json | 8 +++ .../thisTypeInFunctionsNegative.errors.txt | 64 +++++++++++-------- .../reference/thisTypeInFunctionsNegative.js | 16 ++++- .../thisType/thisTypeInFunctionsNegative.ts | 7 +- 5 files changed, 69 insertions(+), 33 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2303aa539f656..4508b25383f98 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11624,8 +11624,11 @@ namespace ts { error(node, Diagnostics.A_binding_pattern_parameter_cannot_be_optional_in_an_implementation_signature); } if ((node.name).text === "this") { - if(indexOf(func.parameters, node) !== 0 || func.kind === SyntaxKind.Constructor) { - error(node, Diagnostics.this_cannot_be_referenced_in_current_location); + if (indexOf(func.parameters, node) !== 0) { + error(node, Diagnostics.this_parameter_must_be_the_first_parameter); + } + if (func.kind === SyntaxKind.Constructor) { + error(node, Diagnostics.A_constructor_cannot_have_a_this_parameter); } } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 804b820f11eee..116270d0c4d6e 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1827,6 +1827,14 @@ "category": "Error", "code": 2672 }, + "'this' parameter must be the first parameter.": { + "category": "Error", + "code": 2673 + }, + "A constructor cannot have a 'this' parameter.": { + "category": "Error", + "code": 2674 + }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", "code": 4000 diff --git a/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt b/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt index 4e8efd187eb05..0b755b9e0bde3 100644 --- a/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt +++ b/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt @@ -93,33 +93,34 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(170,1): er Type 'Base1' is not assignable to type 'Base2'. 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'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(186,20): error TS2370: A rest parameter must be of an array type. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(186,23): error TS1003: Identifier expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(186,27): error TS1005: ',' expected. -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(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'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(189,30): error TS1005: ',' expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(189,32): error TS1138: Parameter declaration expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(189,39): error TS1005: ';' expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(189,40): error TS1128: Declaration or statement expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(189,42): error TS2304: Cannot find name 'number'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(189,49): error TS1005: ';' expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(192,1): error TS7027: Unreachable code detected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(192,29): error TS2304: Cannot find name 'm'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(192,32): error TS1005: ';' expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(192,35): error TS2304: Cannot find name 'm'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(184,17): error TS2674: A constructor cannot have a 'this' parameter. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(187,30): error TS2673: 'this' parameter must be the first parameter. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(187,61): error TS2339: Property 'n' does not exist on type 'void'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(190,26): error TS1003: Identifier expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(190,30): error TS1005: ',' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(190,57): error TS2339: Property 'n' does not exist on type 'void'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(191,20): error TS2370: A rest parameter must be of an array type. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(191,23): error TS1003: Identifier expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(191,27): error TS1005: ',' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(191,54): error TS2339: Property 'n' does not exist on type 'void'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(192,23): error TS1005: ',' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(192,24): error TS1138: Parameter declaration expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(193,28): error TS1003: Identifier expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(193,32): error TS1005: ',' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(193,59): error TS2339: Property 'n' does not exist on type 'void'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(194,30): error TS1005: ',' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(194,32): error TS1138: Parameter declaration expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(194,39): error TS1005: ';' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(194,40): error TS1128: Declaration or statement expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(194,42): error TS2304: Cannot find name 'number'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(194,49): error TS1005: ';' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(197,1): error TS7027: Unreachable code detected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(197,29): error TS2304: Cannot find name 'm'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(197,32): error TS1005: ';' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(197,35): error TS2304: Cannot find name 'm'. -==== tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts (75 errors) ==== +==== tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts (76 errors) ==== class C { n: number; explicitThis(this: this, m: number): number { @@ -447,13 +448,20 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(192,35): e ~~~~~~~~~~~~~~~~~~~~~~ !!! error TS2672: A function that is called with the 'new' keyword cannot have a 'this' type that is void. - - ///// parse errors ///// + ///// syntax-ish errors ///// + class ThisConstructor { + constructor(this: ThisConstructor, private n: number) { + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2674: A constructor cannot have a 'this' parameter. + } + } function notFirst(a: number, this: C): number { return this.n; } ~~~~~~~ -!!! error TS2332: 'this' cannot be referenced in current location. +!!! error TS2673: 'this' parameter must be the first parameter. ~ !!! error TS2339: Property 'n' does not exist on type 'void'. + + ///// parse errors ///// function modifiers(async this: C): number { return this.n; } ~~~~ !!! error TS1003: Identifier expected. diff --git a/tests/baselines/reference/thisTypeInFunctionsNegative.js b/tests/baselines/reference/thisTypeInFunctionsNegative.js index 43d83daef0d9f..c0892d9e4c835 100644 --- a/tests/baselines/reference/thisTypeInFunctionsNegative.js +++ b/tests/baselines/reference/thisTypeInFunctionsNegative.js @@ -180,9 +180,14 @@ function ImplicitVoidThis() { let voidThis = new VoidThis(); let implicitVoidThis = new ImplicitVoidThis(); +///// syntax-ish errors ///// +class ThisConstructor { + constructor(this: ThisConstructor, private n: number) { + } +} +function notFirst(a: number, this: C): number { return this.n; } ///// parse errors ///// -function notFirst(a: number, this: C): number { return this.n; } function modifiers(async this: C): number { return this.n; } function restParam(...this: C): number { return this.n; } function optional(this?: C): number { return this.n; } @@ -364,8 +369,15 @@ function ImplicitVoidThis() { } var voidThis = new VoidThis(); var implicitVoidThis = new ImplicitVoidThis(); -///// parse errors ///// +///// syntax-ish errors ///// +var ThisConstructor = (function () { + function ThisConstructor(n) { + this.n = n; + } + return ThisConstructor; +}()); function notFirst(a, this) { return this.n; } +///// parse errors ///// function modifiers(, C) { if ( === void 0) { = this; } return this.n; diff --git a/tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts b/tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts index 3fba9ad8a7399..3afc5a5c69b4a 100644 --- a/tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts +++ b/tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts @@ -180,9 +180,14 @@ function ImplicitVoidThis() { let voidThis = new VoidThis(); let implicitVoidThis = new ImplicitVoidThis(); +///// syntax-ish errors ///// +class ThisConstructor { + constructor(this: ThisConstructor, private n: number) { + } +} +function notFirst(a: number, this: C): number { return this.n; } ///// parse errors ///// -function notFirst(a: number, this: C): number { return this.n; } function modifiers(async this: C): number { return this.n; } function restParam(...this: C): number { return this.n; } function optional(this?: C): number { return this.n; } From 71488fc3b1b75202efceb9b93ad84e571cad07cf Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 5 Feb 2016 09:38:17 -0800 Subject: [PATCH 16/41] Refactorings from review comments 1. Add `getThisArgumentOfCall` (and correct the code) 2. Remove `getParameterTypeAtIndex` in favour of `getTypeAtPosition`. Simplify calling code. --- src/compiler/checker.ts | 61 ++++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 28 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4508b25383f98..f595a588dd7d5 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3559,10 +3559,6 @@ namespace ts { sig.minArgumentCount, sig.hasRestParameter, sig.hasStringLiterals); } - function getParameterTypeAtIndex(signature: Signature, i: number, max: number, outOfRangeType?: Type): Type { - return i < max ? getTypeOfSymbol(signature.parameters[i]) : (outOfRangeType || getRestTypeOfSignature(signature)); - } - function getDefaultConstructSignatures(classType: InterfaceType): Signature[] { const baseConstructorType = getBaseConstructorTypeOfClass(classType); const baseSignatures = getSignaturesOfType(baseConstructorType, SignatureKind.Construct); @@ -5301,14 +5297,12 @@ namespace ts { target = getErasedSignature(target); let result = Ternary.True; - if (source.thisType || target.thisType) { + if (source.thisType && target.thisType) { 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(t, s, reportErrors); + let related = compareTypes(target.thisType, source.thisType, reportErrors); if (!related) { - related = compareTypes(s, t, /*reportErrors*/ false); + related = compareTypes(source.thisType, target.thisType, /*reportErrors*/ false); if (!related) { errorReporter(Diagnostics.Types_of_parameters_0_and_1_are_incompatible, "this", "this"); return Ternary.False; @@ -6474,27 +6468,23 @@ namespace ts { } function forEachMatchingParameterType(source: Signature, target: Signature, callback: (s: Type, t: Type) => void) { - let sourceMax = source.parameters.length; - let targetMax = target.parameters.length; + const sourceMax = source.parameters.length; + const targetMax = target.parameters.length; let count: number; if (source.hasRestParameter && target.hasRestParameter) { - count = sourceMax > targetMax ? sourceMax : targetMax; - sourceMax--; - targetMax--; + count = Math.max(sourceMax, targetMax); } else if (source.hasRestParameter) { - sourceMax--; count = targetMax; } else if (target.hasRestParameter) { - targetMax--; count = sourceMax; } else { - count = sourceMax < targetMax ? sourceMax : targetMax; + count = Math.min(sourceMax, targetMax); } for (let i = 0; i < count; i++) { - callback(getParameterTypeAtIndex(source, i, sourceMax), getParameterTypeAtIndex(target, i, targetMax)); + callback(getTypeAtPosition(source, i), getTypeAtPosition(target, i)); } } @@ -9416,7 +9406,7 @@ namespace ts { context.failedTypeParameterIndex = undefined; } - const calleeNode = node.kind === SyntaxKind.CallExpression && ((node).expression).expression; + const calleeNode = getThisArgumentOfCall(node); if (signature.thisType) { const mapper = excludeCallee !== undefined ? identityMapper : inferenceMapper; const calleeType: Type = calleeNode ? checkExpressionWithContextualType(calleeNode, signature.thisType, mapper) : voidType; @@ -9503,13 +9493,13 @@ namespace ts { function checkApplicableSignature(node: CallLikeExpression, args: Expression[], signature: Signature, relation: Map, excludeArgument: boolean[], reportErrors: boolean) { const headMessage = Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1; if (signature.thisType && signature.thisType !== voidType && node.kind !== SyntaxKind.NewExpression) { - // If the source is not of the form `x.f`, then sourceType = voidType - // If the target is voidType, then the check is skipped -- anything is compatible. - // If the the expression is a new expression, then the check is skipped. - const calleeNode = node.kind === SyntaxKind.CallExpression && ((node).expression).expression; - const calleeType: Type = calleeNode ? checkExpressionWithContextualType(calleeNode, signature.thisType, undefined) : voidType; + // If the source's this is not of the form `x.f` or `x[f]`, then sourceType = voidType + // If the target's this is voidType, then the check is skipped -- anything is compatible. + // If the expression is a new expression, then the check is skipped. + const calleeNode = getThisArgumentOfCall(node); + const calleeType = calleeNode ? checkExpression(calleeNode) : voidType; const errorNode = reportErrors ? (calleeNode || node) : undefined; - if (!checkTypeRelatedTo(calleeType, getApparentType(signature.thisType), relation, errorNode, headMessage)) { + if (!checkTypeRelatedTo(calleeType, signature.thisType, relation, errorNode, headMessage)) { return false; } } @@ -9541,6 +9531,21 @@ namespace ts { return true; } + /** + * Returns the this argument in calls like x.f(...) and x[f](...). Undefined otherwise. + */ + function getThisArgumentOfCall(node: CallLikeExpression): LeftHandSideExpression { + if (node.kind === SyntaxKind.CallExpression) { + const callee = (node).expression; + if (callee.kind === SyntaxKind.PropertyAccessExpression) { + return (callee as PropertyAccessExpression).expression; + } + else if (callee.kind === SyntaxKind.ElementAccessExpression) { + return (callee as ElementAccessExpression).expression; + } + } + } + /** * Returns the effective arguments for an expression that works like a function invocation. * @@ -9888,7 +9893,7 @@ namespace ts { let excludeCallee: boolean; let excludeArgument: boolean[]; if (!isDecorator) { - const calleeNode = node.kind === SyntaxKind.CallExpression && ((node).expression).expression; + const calleeNode = getThisArgumentOfCall(node); if (calleeNode && isContextSensitive(calleeNode)) { excludeCallee = true; } @@ -10397,8 +10402,8 @@ namespace ts { function getTypeAtPosition(signature: Signature, pos: number): Type { return signature.hasRestParameter ? - getParameterTypeAtIndex(signature, pos, signature.parameters.length - 1) : - getParameterTypeAtIndex(signature, pos, signature.parameters.length, anyType); + pos < signature.parameters.length - 1 ? getTypeOfSymbol(signature.parameters[pos]) : getRestTypeOfSignature(signature) : + pos < signature.parameters.length ? getTypeOfSymbol(signature.parameters[pos]) : anyType; } function assignContextualParameterTypes(signature: Signature, context: Signature, mapper: TypeMapper) { From 5821b87eda234e51f8822a6783f2f1864863b2a8 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 5 Feb 2016 13:53:33 -0800 Subject: [PATCH 17/41] Do not contextually type object callee arguments --- src/compiler/checker.ts | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f595a588dd7d5..32e82d9d537e1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -9380,7 +9380,7 @@ namespace ts { return getSignatureInstantiation(signature, getInferredTypes(context)); } - function inferTypeArguments(node: CallLikeExpression, signature: Signature, args: Expression[], excludeCallee: boolean, excludeArgument: boolean[], context: InferenceContext): void { + function inferTypeArguments(node: CallLikeExpression, signature: Signature, args: Expression[], excludeArgument: boolean[], context: InferenceContext): void { const typeParameters = signature.typeParameters; const inferenceMapper = getInferenceMapper(context); @@ -9406,11 +9406,10 @@ namespace ts { context.failedTypeParameterIndex = undefined; } - const calleeNode = getThisArgumentOfCall(node); if (signature.thisType) { - const mapper = excludeCallee !== undefined ? identityMapper : inferenceMapper; - const calleeType: Type = calleeNode ? checkExpressionWithContextualType(calleeNode, signature.thisType, mapper) : voidType; - inferTypes(context, calleeType, signature.thisType); + const thisArgumentNode = getThisArgumentOfCall(node); + const thisArgumentType = thisArgumentNode ? checkExpression(thisArgumentNode) : voidType; + inferTypes(context, thisArgumentType, signature.thisType); } // We perform two passes over the arguments. In the first pass we infer from all arguments, but use @@ -9442,11 +9441,6 @@ namespace ts { // Decorators will not have `excludeArgument`, as their arguments cannot be contextually typed. // Tagged template expressions will always have `undefined` for `excludeArgument[0]`. if (excludeArgument) { - if (signature.thisType && calleeNode) { - if (excludeCallee === false) { - inferTypes(context, checkExpressionWithContextualType(calleeNode, signature.thisType, inferenceMapper), signature.thisType); - } - } for (let i = 0; i < argCount; i++) { // No need to check for omitted args and template expressions, their exclusion value is always undefined if (excludeArgument[i] === false) { @@ -9496,10 +9490,10 @@ namespace ts { // If the source's this is not of the form `x.f` or `x[f]`, then sourceType = voidType // If the target's this is voidType, then the check is skipped -- anything is compatible. // If the expression is a new expression, then the check is skipped. - const calleeNode = getThisArgumentOfCall(node); - const calleeType = calleeNode ? checkExpression(calleeNode) : voidType; - const errorNode = reportErrors ? (calleeNode || node) : undefined; - if (!checkTypeRelatedTo(calleeType, signature.thisType, relation, errorNode, headMessage)) { + const thisArgumentNode = getThisArgumentOfCall(node); + const thisArgumentType = thisArgumentNode ? checkExpression(thisArgumentNode) : voidType; + const errorNode = reportErrors ? (thisArgumentNode || node) : undefined; + if (!checkTypeRelatedTo(thisArgumentType, signature.thisType, relation, errorNode, headMessage)) { return false; } } @@ -9890,13 +9884,8 @@ namespace ts { // // For a decorator, no arguments are susceptible to contextual typing due to the fact // decorators are applied to a declaration by the emitter, and not to an expression. - let excludeCallee: boolean; let excludeArgument: boolean[]; if (!isDecorator) { - const calleeNode = getThisArgumentOfCall(node); - if (calleeNode && isContextSensitive(calleeNode)) { - excludeCallee = true; - } // We do not need to call `getEffectiveArgumentCount` here as it only // applies when calculating the number of arguments for a decorator. for (let i = isTaggedTemplate ? 1 : 0; i < args.length; i++) { @@ -10045,7 +10034,7 @@ namespace ts { typeArgumentsAreValid = checkTypeArguments(candidate, typeArguments, typeArgumentTypes, /*reportErrors*/ false); } else { - inferTypeArguments(node, candidate, args, excludeCallee, excludeArgument, inferenceContext); + inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext); typeArgumentsAreValid = inferenceContext.failedTypeParameterIndex === undefined; typeArgumentTypes = inferenceContext.inferredTypes; } From 80de700be03700f483d1852a130f490a266e66b4 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 5 Feb 2016 16:18:21 -0800 Subject: [PATCH 18/41] Get contextual type of this parameter correctly Now the language service also sees the contextual type. Note that with this change, the type display for contextually typed this parameters goes away because there is no symbol. I'll fix type display next. --- src/compiler/checker.ts | 23 +++++++--- .../reference/thisTypeInFunctions.types | 42 +++++++++---------- tests/cases/fourslash/quickInfoOnThis.ts | 16 ++++++- 3 files changed, 53 insertions(+), 28 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 32e82d9d537e1..be98dc985b56e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7383,6 +7383,10 @@ namespace ts { captureLexicalThis(node, container); } if (isFunctionLike(container)) { + const type = getContextuallyTypedThisType(container); + if (type) { + return type; + } const signature = getSignatureFromDeclaration(container); if (signature.thisType) { return signature.thisType; @@ -7633,6 +7637,19 @@ namespace ts { } } + function getContextuallyTypedThisType(func: FunctionLikeDeclaration): Type { + if ((isFunctionExpressionOrArrowFunction(func) || isObjectLiteralMethod(func)) && + isContextSensitive(func) && + func.kind !== SyntaxKind.ArrowFunction) { + const contextualSignature = getContextualSignature(func); + if (contextualSignature) { + return contextualSignature.thisType; + } + } + + return undefined; + } + // Return contextual type of parameter or undefined if no contextual type is available function getContextuallyTypedParameterType(parameter: ParameterDeclaration): Type { const func = parameter.parent; @@ -10396,12 +10413,6 @@ namespace ts { } function assignContextualParameterTypes(signature: Signature, context: Signature, mapper: TypeMapper) { - if (context.thisType) { - if (signature.declaration.kind !== SyntaxKind.ArrowFunction) { - // do not contextually type thisType for ArrowFunction. - signature.thisType = context.thisType; - } - } const len = signature.parameters.length - (signature.hasRestParameter ? 1 : 0); for (let i = 0; i < len; i++) { const parameter = signature.parameters[i]; diff --git a/tests/baselines/reference/thisTypeInFunctions.types b/tests/baselines/reference/thisTypeInFunctions.types index b0fc9fc3300af..e1044bb3d90f5 100644 --- a/tests/baselines/reference/thisTypeInFunctions.types +++ b/tests/baselines/reference/thisTypeInFunctions.types @@ -143,7 +143,7 @@ function implicitThis(n: number): number { let impl: I = { >impl : I >I : I ->{ a: 12, explicitVoid2: () => this.a, // ok, this: any because it refers to some outer object (window?) explicitVoid1() { return 12; }, explicitStructural() { return this.a; }, explicitInterface() { return this.a; }, explicitThis() { return this.a; }, implicitMethod() { return this.a; }, implicitFunction: () => this.a, // ok, this: any because it refers to some outer object (window?)} : { a: number; explicitVoid2: () => any; explicitVoid1(): number; explicitStructural(this: { a: number; }): number; explicitInterface(this: I): number; explicitThis(this: I): number; implicitMethod(this: I): number; implicitFunction: () => any; } +>{ a: 12, explicitVoid2: () => this.a, // ok, this: any because it refers to some outer object (window?) explicitVoid1() { return 12; }, explicitStructural() { return this.a; }, explicitInterface() { return this.a; }, explicitThis() { return this.a; }, implicitMethod() { return this.a; }, implicitFunction: () => this.a, // ok, this: any because it refers to some outer object (window?)} : { a: number; explicitVoid2: () => any; explicitVoid1(): number; explicitStructural(): number; explicitInterface(): number; explicitThis(): number; implicitMethod(): number; implicitFunction: () => any; } a: 12, >a : number @@ -161,7 +161,7 @@ let impl: I = { >12 : number explicitStructural() { ->explicitStructural : (this: { a: number; }) => number +>explicitStructural : () => number return this.a; >this.a : number @@ -170,7 +170,7 @@ let impl: I = { }, explicitInterface() { ->explicitInterface : (this: I) => number +>explicitInterface : () => number return this.a; >this.a : number @@ -179,7 +179,7 @@ let impl: I = { }, explicitThis() { ->explicitThis : (this: I) => number +>explicitThis : () => number return this.a; >this.a : number @@ -188,7 +188,7 @@ let impl: I = { }, implicitMethod() { ->implicitMethod : (this: I) => number +>implicitMethod : () => number return this.a; >this.a : number @@ -220,21 +220,21 @@ impl.explicitVoid2 = () => 12; >12 : number impl.explicitStructural = function() { return this.a; }; ->impl.explicitStructural = function() { return this.a; } : (this: { a: number; }) => number +>impl.explicitStructural = function() { return this.a; } : () => number >impl.explicitStructural : (this: { a: number; }) => number >impl : I >explicitStructural : (this: { a: number; }) => number ->function() { return this.a; } : (this: { a: number; }) => number +>function() { return this.a; } : () => number >this.a : number >this : { a: number; } >a : number impl.explicitInterface = function() { return this.a; }; ->impl.explicitInterface = function() { return this.a; } : (this: I) => number +>impl.explicitInterface = function() { return this.a; } : () => number >impl.explicitInterface : (this: I) => number >impl : I >explicitInterface : (this: I) => number ->function() { return this.a; } : (this: I) => number +>function() { return this.a; } : () => number >this.a : number >this : I >a : number @@ -256,21 +256,21 @@ impl.explicitInterface = () => 12; >12 : number impl.explicitThis = function () { return this.a; }; ->impl.explicitThis = function () { return this.a; } : (this: I) => number +>impl.explicitThis = function () { return this.a; } : () => number >impl.explicitThis : (this: I) => number >impl : I >explicitThis : (this: I) => number ->function () { return this.a; } : (this: I) => number +>function () { return this.a; } : () => number >this.a : number >this : I >a : number impl.implicitMethod = function () { return this.a; }; ->impl.implicitMethod = function () { return this.a; } : (this: I) => number +>impl.implicitMethod = function () { return this.a; } : () => number >impl.implicitMethod : (this: I) => number >impl : I >implicitMethod : (this: I) => number ->function () { return this.a; } : (this: I) => number +>function () { return this.a; } : () => number >this.a : number >this : I >a : number @@ -719,11 +719,11 @@ c.explicitThis = function(this: C, m: number) { return this.n + m }; // this:any compatibility c.explicitC = function(m) { return this.n + m }; ->c.explicitC = function(m) { return this.n + m } : (this: C, m: number) => number +>c.explicitC = function(m) { return this.n + m } : (m: number) => number >c.explicitC : (this: C, m: number) => number >c : C >explicitC : (this: C, m: number) => number ->function(m) { return this.n + m } : (this: C, m: number) => number +>function(m) { return this.n + m } : (m: number) => number >m : number >this.n + m : number >this.n : number @@ -732,11 +732,11 @@ c.explicitC = function(m) { return this.n + m }; >m : 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 = function(m) { return this.n + m } : (m: number) => number >c.explicitProperty : (this: { n: number; }, m: number) => number >c : C >explicitProperty : (this: { n: number; }, m: number) => number ->function(m) { return this.n + m } : (this: { n: number; }, m: number) => number +>function(m) { return this.n + m } : (m: number) => number >m : number >this.n + m : number >this.n : number @@ -745,11 +745,11 @@ c.explicitProperty = function(m) { return this.n + m }; >m : number c.explicitThis = function(m) { return this.n + m }; ->c.explicitThis = function(m) { return this.n + m } : (this: C, m: number) => number +>c.explicitThis = function(m) { return this.n + m } : (m: number) => number >c.explicitThis : (this: C, m: number) => number >c : C >explicitThis : (this: C, m: number) => number ->function(m) { return this.n + m } : (this: C, m: number) => number +>function(m) { return this.n + m } : (m: number) => number >m : number >this.n + m : number >this.n : number @@ -758,11 +758,11 @@ c.explicitThis = function(m) { return this.n + m }; >m : number c.implicitThis = function(m) { return this.n + m }; ->c.implicitThis = function(m) { return this.n + m } : (this: C, m: number) => number +>c.implicitThis = function(m) { return this.n + m } : (m: number) => number >c.implicitThis : (this: C, m: number) => number >c : C >implicitThis : (this: C, m: number) => number ->function(m) { return this.n + m } : (this: C, m: number) => number +>function(m) { return this.n + m } : (m: number) => number >m : number >this.n + m : number >this.n : number diff --git a/tests/cases/fourslash/quickInfoOnThis.ts b/tests/cases/fourslash/quickInfoOnThis.ts index cef78efe0cc7f..3213b85174ef9 100644 --- a/tests/cases/fourslash/quickInfoOnThis.ts +++ b/tests/cases/fourslash/quickInfoOnThis.ts @@ -42,6 +42,17 @@ ////function explicitLiteral(th/*14*/is: { n: number }): void { //// console.log(th/*15*/is); ////} +//// +//// interface ContextualInterface { +//// m: number; +//// method(this: this, n: number); +//// } +//// let o: ContextualInterface = { +//// m: 12, +//// method(n) { +//// let x = this/*16*/.m; +//// } +//// } goTo.marker('1'); verify.quickInfoIs('void'); @@ -73,4 +84,7 @@ goTo.marker('14'); verify.quickInfoIs('(parameter) this: {\n n: number;\n}'); goTo.marker('15'); -verify.quickInfoIs('this: {\n n: number;\n}'); \ No newline at end of file +verify.quickInfoIs('this: {\n n: number;\n}'); + +goTo.marker('16'); +verify.quickInfoIs('this: ContextualInterface'); \ No newline at end of file From fa598758b12d9b06c2b21579e8512a32bffd5065 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Mon, 8 Feb 2016 09:41:57 -0800 Subject: [PATCH 19/41] Improve display and contextual typing of `this` 1. Always display `this` type if annotated. 2. Contextually type un-annotated `this` parameters in addition to `this` expressions. --- src/compiler/checker.ts | 9 +- .../reference/contextualTyping24.errors.txt | 4 +- .../looseThisTypeInFunctions.errors.txt | 4 +- .../reference/thisTypeInFunctions.types | 128 +++++++++--------- .../thisTypeInFunctionsNegative.errors.txt | 16 +-- tests/cases/fourslash/quickInfoOnThis.ts | 16 ++- 6 files changed, 92 insertions(+), 85 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index be98dc985b56e..06986107fbb52 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2203,15 +2203,14 @@ namespace ts { function buildDisplayForParametersAndDelimiters(thisType: Type, parameters: Symbol[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) { writePunctuation(writer, SyntaxKind.OpenParenToken); - const useThisType = thisType && thisType.symbol; - if (useThisType) { + if (thisType) { writeKeyword(writer, SyntaxKind.ThisKeyword); writePunctuation(writer, SyntaxKind.ColonToken); writeSpace(writer); buildTypeDisplay(thisType, writer, enclosingDeclaration, flags, symbolStack); } for (let i = 0; i < parameters.length; i++) { - if (i > 0 || useThisType) { + if (i > 0 || thisType) { writePunctuation(writer, SyntaxKind.CommaToken); writeSpace(writer); } @@ -2690,7 +2689,9 @@ namespace ts { } } // Use contextual parameter type if one is available - const type = getContextuallyTypedParameterType(declaration); + const type = declaration.symbol.name === "this" + ? getContextuallyTypedThisType(func) + : getContextuallyTypedParameterType(declaration); if (type) { return type; } diff --git a/tests/baselines/reference/contextualTyping24.errors.txt b/tests/baselines/reference/contextualTyping24.errors.txt index b4d0d5344562e..d5cb13e4e3e40 100644 --- a/tests/baselines/reference/contextualTyping24.errors.txt +++ b/tests/baselines/reference/contextualTyping24.errors.txt @@ -1,4 +1,4 @@ -tests/cases/compiler/contextualTyping24.ts(1,55): error TS2322: Type '(a: string) => number' is not assignable to type '(a: { (): number; (i: number): number; }) => number'. +tests/cases/compiler/contextualTyping24.ts(1,55): error TS2322: Type '(this: void, a: string) => number' is not assignable to type '(a: { (): number; (i: number): number; }) => number'. Types of parameters 'a' and 'a' are incompatible. Type 'string' is not assignable to type '{ (): number; (i: number): number; }'. @@ -6,6 +6,6 @@ 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(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: Type '(this: void, a: string) => number' is not assignable to type '(a: { (): number; (i: number): number; }) => number'. !!! error TS2322: Types of parameters 'a' and 'a' are incompatible. !!! error TS2322: Type 'string' is not assignable to type '{ (): number; (i: number): number; }'. \ No newline at end of file diff --git a/tests/baselines/reference/looseThisTypeInFunctions.errors.txt b/tests/baselines/reference/looseThisTypeInFunctions.errors.txt index 317446050a8e3..4eef7d83f787a 100644 --- a/tests/baselines/reference/looseThisTypeInFunctions.errors.txt +++ b/tests/baselines/reference/looseThisTypeInFunctions.errors.txt @@ -1,4 +1,4 @@ -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'. +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. Type 'void' is not assignable to type 'C'. tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(32,5): error TS1005: ',' expected. @@ -30,7 +30,7 @@ tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(46,19): error let c = new C(); c.explicitVoid = c.explicitThis; // error, 'void' is missing everything ~~~~~~~~~~~~~~ -!!! error TS2322: Type '(this: C, m: number) => number' is not assignable to type '(m: number) => number'. +!!! 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: Type 'void' is not assignable to type 'C'. let o = { diff --git a/tests/baselines/reference/thisTypeInFunctions.types b/tests/baselines/reference/thisTypeInFunctions.types index e1044bb3d90f5..2c334b2caed3b 100644 --- a/tests/baselines/reference/thisTypeInFunctions.types +++ b/tests/baselines/reference/thisTypeInFunctions.types @@ -56,7 +56,7 @@ class C { >m : number } explicitVoid(this: void, m: number): number { ->explicitVoid : (m: number) => number +>explicitVoid : (this: void, m: number) => number >this : void >m : number @@ -83,11 +83,11 @@ interface I { >a : number explicitVoid1(this: void): number; ->explicitVoid1 : () => number +>explicitVoid1 : (this: void) => number >this : void explicitVoid2(this: void): number; ->explicitVoid2 : () => number +>explicitVoid2 : (this: void) => number >this : void explicitStructural(this: {a: number}): number; @@ -108,7 +108,7 @@ interface I { >implicitMethod : (this: this) => number implicitFunction: () => number; ->implicitFunction : () => number +>implicitFunction : (this: void) => number } function explicitStructural(this: { y: number }, x: number): number { >explicitStructural : (this: { y: number; }, x: number) => number @@ -134,7 +134,7 @@ function justThis(this: { y: number }): number { >y : number } function implicitThis(n: number): number { ->implicitThis : (n: number) => number +>implicitThis : (this: void, n: number) => number >n : number return 12; @@ -204,37 +204,37 @@ let impl: I = { >a : any } impl.explicitVoid1 = function () { return 12; }; ->impl.explicitVoid1 = function () { return 12; } : () => number ->impl.explicitVoid1 : () => number +>impl.explicitVoid1 = function () { return 12; } : (this: void) => number +>impl.explicitVoid1 : (this: void) => number >impl : I ->explicitVoid1 : () => number ->function () { return 12; } : () => number +>explicitVoid1 : (this: void) => number +>function () { return 12; } : (this: void) => number >12 : number impl.explicitVoid2 = () => 12; >impl.explicitVoid2 = () => 12 : () => number ->impl.explicitVoid2 : () => number +>impl.explicitVoid2 : (this: void) => number >impl : I ->explicitVoid2 : () => number +>explicitVoid2 : (this: void) => number >() => 12 : () => number >12 : number impl.explicitStructural = function() { return this.a; }; ->impl.explicitStructural = function() { return this.a; } : () => number +>impl.explicitStructural = function() { return this.a; } : (this: void) => number >impl.explicitStructural : (this: { a: number; }) => number >impl : I >explicitStructural : (this: { a: number; }) => number ->function() { return this.a; } : () => number +>function() { return this.a; } : (this: void) => number >this.a : number >this : { a: number; } >a : number impl.explicitInterface = function() { return this.a; }; ->impl.explicitInterface = function() { return this.a; } : () => number +>impl.explicitInterface = function() { return this.a; } : (this: void) => number >impl.explicitInterface : (this: I) => number >impl : I >explicitInterface : (this: I) => number ->function() { return this.a; } : () => number +>function() { return this.a; } : (this: void) => number >this.a : number >this : I >a : number @@ -256,21 +256,21 @@ impl.explicitInterface = () => 12; >12 : number impl.explicitThis = function () { return this.a; }; ->impl.explicitThis = function () { return this.a; } : () => number +>impl.explicitThis = function () { return this.a; } : (this: void) => number >impl.explicitThis : (this: I) => number >impl : I >explicitThis : (this: I) => number ->function () { return this.a; } : () => number +>function () { return this.a; } : (this: void) => number >this.a : number >this : I >a : number impl.implicitMethod = function () { return this.a; }; ->impl.implicitMethod = function () { return this.a; } : () => number +>impl.implicitMethod = function () { return this.a; } : (this: void) => number >impl.implicitMethod : (this: I) => number >impl : I >implicitMethod : (this: I) => number ->function () { return this.a; } : () => number +>function () { return this.a; } : (this: void) => number >this.a : number >this : I >a : number @@ -285,9 +285,9 @@ impl.implicitMethod = () => 12; impl.implicitFunction = () => this.a; // ok, this: any because it refers to some outer object (window?) >impl.implicitFunction = () => this.a : () => any ->impl.implicitFunction : () => number +>impl.implicitFunction : (this: void) => number >impl : I ->implicitFunction : () => number +>implicitFunction : (this: void) => number >() => this.a : () => any >this.a : any >this : any @@ -308,15 +308,15 @@ let ok: {y: number, f: (this: { y: number }, x: number) => number} = { y: 12, f: >explicitStructural : (this: { y: number; }, x: number) => number let implicitAnyOk: {notSpecified: number, f: (x: number) => number} = { notSpecified: 12, f: implicitThis }; ->implicitAnyOk : { notSpecified: number; f: (x: number) => number; } +>implicitAnyOk : { notSpecified: number; f: (this: void, x: number) => number; } >notSpecified : number ->f : (x: number) => number +>f : (this: void, x: number) => number >x : number ->{ notSpecified: 12, f: implicitThis } : { notSpecified: number; f: (n: number) => number; } +>{ notSpecified: 12, f: implicitThis } : { notSpecified: number; f: (this: void, n: number) => number; } >notSpecified : number >12 : number ->f : (n: number) => number ->implicitThis : (n: number) => number +>f : (this: void, n: number) => number +>implicitThis : (this: void, n: number) => number ok.f(13); >ok.f(13) : number @@ -327,14 +327,14 @@ ok.f(13); implicitThis(12); >implicitThis(12) : number ->implicitThis : (n: number) => number +>implicitThis : (this: void, n: number) => number >12 : number implicitAnyOk.f(12); >implicitAnyOk.f(12) : number ->implicitAnyOk.f : (x: number) => number ->implicitAnyOk : { notSpecified: number; f: (x: number) => number; } ->f : (x: number) => number +>implicitAnyOk.f : (this: void, x: number) => number +>implicitAnyOk : { notSpecified: number; f: (this: void, x: number) => number; } +>f : (this: void, x: number) => number >12 : number let c = new C(); @@ -410,7 +410,7 @@ d.implicitThis(12); >12 : number let reconstructed: { ->reconstructed : { n: number; explicitThis(this: C, m: number): number; implicitThis(m: number): number; explicitC(this: C, m: number): number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid(m: number): number; } +>reconstructed : { n: number; explicitThis(this: C, m: number): number; implicitThis(m: number): number; explicitC(this: C, m: number): number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid(this: void, m: number): number; } n: number, >n : number @@ -438,12 +438,12 @@ let reconstructed: { >m : number explicitVoid(this: void, m: number): number, ->explicitVoid : (m: number) => number +>explicitVoid : (this: void, m: number) => number >this : void >m : number } = { ->{ n: 12, explicitThis: c.explicitThis, implicitThis: c.implicitThis, explicitC: c.explicitC, explicitProperty: c.explicitProperty, explicitVoid: c.explicitVoid} : { n: number; explicitThis: (this: C, m: number) => number; implicitThis: (this: C, m: number) => number; explicitC: (this: C, m: number) => number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid: (m: number) => number; } +>{ n: 12, explicitThis: c.explicitThis, implicitThis: c.implicitThis, explicitC: c.explicitC, explicitProperty: c.explicitProperty, explicitVoid: c.explicitVoid} : { n: number; explicitThis: (this: C, m: number) => number; implicitThis: (this: C, m: number) => number; explicitC: (this: C, m: number) => number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid: (this: void, m: number) => number; } n: 12, >n : number @@ -474,23 +474,23 @@ let reconstructed: { >explicitProperty : (this: { n: number; }, m: number) => number explicitVoid: c.explicitVoid ->explicitVoid : (m: number) => number ->c.explicitVoid : (m: number) => number +>explicitVoid : (this: void, m: number) => number +>c.explicitVoid : (this: void, m: number) => number >c : C ->explicitVoid : (m: number) => number +>explicitVoid : (this: void, m: number) => number }; reconstructed.explicitProperty(11); >reconstructed.explicitProperty(11) : number >reconstructed.explicitProperty : (this: { n: number; }, m: number) => number ->reconstructed : { n: number; explicitThis(this: C, m: number): number; implicitThis(m: number): number; explicitC(this: C, m: number): number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid(m: number): number; } +>reconstructed : { n: number; explicitThis(this: C, m: number): number; implicitThis(m: number): number; explicitC(this: C, m: number): number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid(this: void, m: number): number; } >explicitProperty : (this: { n: number; }, m: number) => number >11 : number reconstructed.implicitThis(11); >reconstructed.implicitThis(11) : number >reconstructed.implicitThis : (m: number) => number ->reconstructed : { n: number; explicitThis(this: C, m: number): number; implicitThis(m: number): number; explicitC(this: C, m: number): number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid(m: number): number; } +>reconstructed : { n: number; explicitThis(this: C, m: number): number; implicitThis(m: number): number; explicitC(this: C, m: number): number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid(this: void, m: number): number; } >implicitThis : (m: number) => number >11 : number @@ -520,14 +520,14 @@ 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; } : (x: number) => number +>function(x: number): number { return x + 12; } : (this: void, x: number) => number >x : number >x + 12 : number >x : number >12 : number let unspecifiedLambda: (x: number) => number = x => x + 12; ->unspecifiedLambda : (x: number) => number +>unspecifiedLambda : (this: void, x: number) => number >x : number >x => x + 12 : (x: number) => number >x : number @@ -536,7 +536,7 @@ let unspecifiedLambda: (x: number) => number = x => x + 12; >12 : number let specifiedLambda: (this: void, x: number) => number = x => x + 12; ->specifiedLambda : (x: number) => number +>specifiedLambda : (this: void, x: number) => number >this : void >x : number >x => x + 12 : (x: number) => number @@ -550,14 +550,14 @@ let unspecifiedLambdaToSpecified: (this: {y: number}, x: number) => number = uns >this : { y: number; } >y : number >x : number ->unspecifiedLambda : (x: number) => number +>unspecifiedLambda : (this: void, x: number) => number let specifiedLambdaToSpecified: (this: {y: number}, x: number) => number = specifiedLambda; >specifiedLambdaToSpecified : (this: { y: number; }, x: number) => number >this : { y: number; } >y : number >x : number ->specifiedLambda : (x: number) => number +>specifiedLambda : (this: void, x: number) => number let explicitCFunction: (this: C, m: number) => number; @@ -622,7 +622,7 @@ c.explicitProperty = reconstructed.explicitProperty; >c : C >explicitProperty : (this: { n: number; }, m: number) => number >reconstructed.explicitProperty : (this: { n: number; }, m: number) => number ->reconstructed : { n: number; explicitThis(this: C, m: number): number; implicitThis(m: number): number; explicitC(this: C, m: number): number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid(m: number): number; } +>reconstructed : { n: number; explicitThis(this: C, m: number): number; implicitThis(m: number): number; explicitC(this: C, m: number): number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid(this: void, m: number): number; } >explicitProperty : (this: { n: number; }, m: number) => number // lambdas are assignable to anything @@ -719,11 +719,11 @@ c.explicitThis = function(this: C, m: number) { return this.n + m }; // this:any compatibility c.explicitC = function(m) { return this.n + m }; ->c.explicitC = function(m) { return this.n + m } : (m: number) => number +>c.explicitC = function(m) { return this.n + m } : (this: void, m: number) => number >c.explicitC : (this: C, m: number) => number >c : C >explicitC : (this: C, m: number) => number ->function(m) { return this.n + m } : (m: number) => number +>function(m) { return this.n + m } : (this: void, m: number) => number >m : number >this.n + m : number >this.n : number @@ -732,11 +732,11 @@ c.explicitC = function(m) { return this.n + m }; >m : number c.explicitProperty = function(m) { return this.n + m }; ->c.explicitProperty = function(m) { return this.n + m } : (m: number) => number +>c.explicitProperty = function(m) { return this.n + m } : (this: void, m: number) => number >c.explicitProperty : (this: { n: number; }, m: number) => number >c : C >explicitProperty : (this: { n: number; }, m: number) => number ->function(m) { return this.n + m } : (m: number) => number +>function(m) { return this.n + m } : (this: void, m: number) => number >m : number >this.n + m : number >this.n : number @@ -745,11 +745,11 @@ c.explicitProperty = function(m) { return this.n + m }; >m : number c.explicitThis = function(m) { return this.n + m }; ->c.explicitThis = function(m) { return this.n + m } : (m: number) => number +>c.explicitThis = function(m) { return this.n + m } : (this: void, m: number) => number >c.explicitThis : (this: C, m: number) => number >c : C >explicitThis : (this: C, m: number) => number ->function(m) { return this.n + m } : (m: number) => number +>function(m) { return this.n + m } : (this: void, m: number) => number >m : number >this.n + m : number >this.n : number @@ -758,11 +758,11 @@ c.explicitThis = function(m) { return this.n + m }; >m : number c.implicitThis = function(m) { return this.n + m }; ->c.implicitThis = function(m) { return this.n + m } : (m: number) => number +>c.implicitThis = function(m) { return this.n + m } : (this: void, m: number) => number >c.implicitThis : (this: C, m: number) => number >c : C >implicitThis : (this: C, m: number) => number ->function(m) { return this.n + m } : (m: number) => number +>function(m) { return this.n + m } : (this: void, m: number) => number >m : number >this.n + m : number >this.n : number @@ -776,7 +776,7 @@ c.implicitThis = reconstructed.implicitThis; >c : C >implicitThis : (this: C, m: number) => number >reconstructed.implicitThis : (m: number) => number ->reconstructed : { n: number; explicitThis(this: C, m: number): number; implicitThis(m: number): number; explicitC(this: C, m: number): number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid(m: number): number; } +>reconstructed : { n: number; explicitThis(this: C, m: number): number; implicitThis(m: number): number; explicitC(this: C, m: number): number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid(this: void, m: number): number; } >implicitThis : (m: number) => number c.explicitC = function(this: B, m: number) { return this.n + m }; @@ -797,9 +797,9 @@ c.explicitC = function(this: B, m: number) { return this.n + m }; // this:void compatibility c.explicitVoid = n => n; >c.explicitVoid = n => n : (n: number) => number ->c.explicitVoid : (m: number) => number +>c.explicitVoid : (this: void, m: number) => number >c : C ->explicitVoid : (m: number) => number +>explicitVoid : (this: void, m: number) => number >n => n : (n: number) => number >n : number >n : number @@ -978,7 +978,7 @@ function LiteralTypeThis(this: {x: string}) { >"ok" : string } function AnyThis(this: any) { ->AnyThis : () => void +>AnyThis : (this: any) => void >this : any this.x = "ok"; @@ -1001,20 +1001,20 @@ let literalTypeThis = new LiteralTypeThis(); let anyThis = new AnyThis(); >anyThis : any >new AnyThis() : any ->AnyThis : () => void +>AnyThis : (this: any) => void //// type parameter inference //// declare var f: { ->f : { (x: number): number; call(this: (...argArray: any[]) => U, ...argArray: any[]): U; } +>f : { (this: void, x: number): number; call(this: (this: void, ...argArray: any[]) => U, ...argArray: any[]): U; } (this: void, x: number): number, >this : void >x : number call(this: (...argArray: any[]) => U, ...argArray: any[]): U; ->call : (this: (...argArray: any[]) => U, ...argArray: any[]) => U +>call : (this: (this: void, ...argArray: any[]) => U, ...argArray: any[]) => U >U : U ->this : (...argArray: any[]) => U +>this : (this: void, ...argArray: any[]) => U >argArray : any[] >U : U >argArray : any[] @@ -1024,13 +1024,13 @@ declare var f: { let n: number = f.call(12); >n : number >f.call(12) : number ->f.call : (this: (...argArray: any[]) => U, ...argArray: any[]) => U ->f : { (x: number): number; call(this: (...argArray: any[]) => U, ...argArray: any[]): U; } ->call : (this: (...argArray: any[]) => U, ...argArray: any[]) => U +>f.call : (this: (this: void, ...argArray: any[]) => U, ...argArray: any[]) => U +>f : { (this: void, x: number): number; call(this: (this: void, ...argArray: any[]) => U, ...argArray: any[]): U; } +>call : (this: (this: void, ...argArray: any[]) => U, ...argArray: any[]) => U >12 : number function missingTypeIsImplicitAny(this, a: number) { return a; } ->missingTypeIsImplicitAny : (a: number) => number +>missingTypeIsImplicitAny : (this: any, a: number) => number >this : any >a : number >a : number diff --git a/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt b/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt index 0b755b9e0bde3..fdb9489f639d4 100644 --- a/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt +++ b/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt @@ -33,7 +33,7 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(95,1): err tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(96,1): error TS2346: Supplied parameters do not match any signature of call target. tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(97,20): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(98,1): error TS2346: Supplied parameters do not match any signature of call target. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(101,5): error TS2322: Type '(this: { y: number; }, x: number) => number' is not assignable to type '(x: number) => number'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(101,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. Type 'void' is not assignable to type '{ y: number; }'. tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(124,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'. @@ -70,13 +70,13 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(134,1): er Types of parameters 'this' and 'this' are incompatible. Type '{ n: number; }' is not assignable to type 'D'. tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(135,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(136,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(m: number) => number'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(136,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. Type 'void' is not assignable to type 'D'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(137,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(m: number) => number'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(137,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. Type 'void' is not assignable to type 'D'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(138,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(m: number) => number'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(138,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. Type 'void' is not assignable to type 'D'. tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(146,51): error TS2339: Property 'x' does not exist on type 'typeof Base1'. @@ -287,7 +287,7 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(197,35): e // oops, this triggers contextual typing, which needs to be updated to understand that =>'s `this` is void. let specifiedToImplicitVoid: (x: number) => number = explicitStructural; ~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2322: Type '(this: { y: number; }, x: number) => number' is not assignable to type '(x: number) => number'. +!!! 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: Type 'void' is not assignable to type '{ y: number; }'. @@ -371,17 +371,17 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(197,35): e !!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'. c.explicitVoid = d.implicitD; ~~~~~~~~~~~~~~ -!!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(m: number) => number'. +!!! 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: Type 'void' is not assignable to type 'D'. c.explicitVoid = d.explicitD; ~~~~~~~~~~~~~~ -!!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(m: number) => number'. +!!! 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: 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 '(m: number) => number'. +!!! 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: Type 'void' is not assignable to type 'D'. diff --git a/tests/cases/fourslash/quickInfoOnThis.ts b/tests/cases/fourslash/quickInfoOnThis.ts index 3213b85174ef9..57bbb6c5a3ef4 100644 --- a/tests/cases/fourslash/quickInfoOnThis.ts +++ b/tests/cases/fourslash/quickInfoOnThis.ts @@ -43,16 +43,20 @@ //// console.log(th/*15*/is); ////} //// -//// interface ContextualInterface { +////interface ContextualInterface { //// m: number; //// method(this: this, n: number); -//// } -//// let o: ContextualInterface = { +////} +////let o: ContextualInterface = { //// m: 12, //// method(n) { //// let x = this/*16*/.m; //// } -//// } +////} +////interface ContextualInterface2 { +//// (this: void, n: number): void; +////} +////let contextualInterface2: ContextualInterface2 = function (th/*17*/is, n) { } goTo.marker('1'); verify.quickInfoIs('void'); @@ -87,4 +91,6 @@ goTo.marker('15'); verify.quickInfoIs('this: {\n n: number;\n}'); goTo.marker('16'); -verify.quickInfoIs('this: ContextualInterface'); \ No newline at end of file +verify.quickInfoIs('this: ContextualInterface'); +goTo.marker('17'); +verify.quickInfoIs('(parameter) this: void'); \ No newline at end of file From 738713b146d055194254640d8b079cc54ca6cd7f Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Mon, 8 Feb 2016 14:01:51 -0800 Subject: [PATCH 20/41] Improve error reporting 1. Fix bug in error reporting in compareSignaturesRelated. 2. When the this-argument is a union type, allow assignability when the method's signature is assignable to *any* member of the union. --- src/compiler/checker.ts | 12 +- src/compiler/core.ts | 17 + .../reference/thisTypeInFunctions.js | 24 +- .../reference/thisTypeInFunctions.symbols | 382 +++++++++--------- .../reference/thisTypeInFunctions.types | 25 +- .../types/thisType/thisTypeInFunctions.ts | 11 +- 6 files changed, 267 insertions(+), 204 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 06986107fbb52..0acb3a127d509 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5305,7 +5305,9 @@ namespace ts { if (!related) { related = compareTypes(source.thisType, target.thisType, /*reportErrors*/ false); if (!related) { - errorReporter(Diagnostics.Types_of_parameters_0_and_1_are_incompatible, "this", "this"); + if (reportErrors) { + errorReporter(Diagnostics.Types_of_parameters_0_and_1_are_incompatible, "this", "this"); + } return Ternary.False; } } @@ -9511,7 +9513,13 @@ namespace ts { const thisArgumentNode = getThisArgumentOfCall(node); const thisArgumentType = thisArgumentNode ? checkExpression(thisArgumentNode) : voidType; const errorNode = reportErrors ? (thisArgumentNode || node) : undefined; - if (!checkTypeRelatedTo(thisArgumentType, signature.thisType, relation, errorNode, headMessage)) { + if (thisArgumentType.flags & TypeFlags.UnionOrIntersection) { + const u = thisArgumentType; + if (!forEach(u.types, t => checkTypeRelatedTo(t, signature.thisType, relation, errorNode, headMessage))) { + return false; + } + } + else if (!checkTypeRelatedTo(thisArgumentType, signature.thisType, relation, errorNode, headMessage)) { return false; } } diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 21536da36ff26..f1f9d93c5d265 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -91,6 +91,23 @@ namespace ts { return undefined; } + /** + * Iterates through `array` by index and performs the callback on each element of array until the callback + * returns a falsey value, then returns false. + * If no such value is found, the callback is applied to each element of array and `true` is returned. + */ + export function trueForAll(array: T[], callback: (element: T, index: number) => boolean): boolean { + if (array) { + for (let i = 0, len = array.length; i < len; i++) { + if (!callback(array[i], i)) { + return false; + } + } + } + + return true; + } + export function contains(array: T[], value: T): boolean { if (array) { for (const v of array) { diff --git a/tests/baselines/reference/thisTypeInFunctions.js b/tests/baselines/reference/thisTypeInFunctions.js index f3ad84acb55aa..af55603a4b72a 100644 --- a/tests/baselines/reference/thisTypeInFunctions.js +++ b/tests/baselines/reference/thisTypeInFunctions.js @@ -1,5 +1,8 @@ //// [thisTypeInFunctions.ts] // body checking +class B { + n: number; +} class C { n: number; explicitThis(this: this, m: number): number { @@ -19,9 +22,6 @@ class C { } } class D extends C { } -class B { - n: number; -} interface I { a: number; explicitVoid1(this: void): number; @@ -185,6 +185,11 @@ d2.implicit = d1.explicit // ok, 'y' in { x, y } (c assignable to f) b1.implicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) b1.explicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) +// union assignability + +let b1b2: Base1 | Base2; +b1b2.implicit(); + ////// use this-type for construction with new //// function InterfaceThis(this: I) { this.a = 12; @@ -216,6 +221,11 @@ var __extends = (this && this.__extends) || function (d, b) { }; var _this = this; // body checking +var B = (function () { + function B() { + } + return B; +}()); var C = (function () { function C() { } @@ -243,11 +253,6 @@ var D = (function (_super) { } return D; }(C)); -var B = (function () { - function B() { - } - return B; -}()); function explicitStructural(x) { return x + this.y; } @@ -390,6 +395,9 @@ d1.implicit = b2.implicit; // ok, 'y' in D: { x, y } (d assignable e) d2.implicit = d1.explicit; // ok, 'y' in { x, y } (c assignable to f) b1.implicit = d2.implicit; // ok, 'x' and 'y' not in C: { x } (c assignable to f) b1.explicit = d2.implicit; // ok, 'x' and 'y' not in C: { x } (c assignable to f) +// union assignability +var b1b2; +b1b2.implicit(); ////// use this-type for construction with new //// function InterfaceThis() { this.a = 12; diff --git a/tests/baselines/reference/thisTypeInFunctions.symbols b/tests/baselines/reference/thisTypeInFunctions.symbols index bb6a9acfdd06d..120494c206fb8 100644 --- a/tests/baselines/reference/thisTypeInFunctions.symbols +++ b/tests/baselines/reference/thisTypeInFunctions.symbols @@ -1,77 +1,77 @@ === tests/cases/conformance/types/thisType/thisTypeInFunctions.ts === // body checking -class C { ->C : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +class B { +>B : Symbol(B, Decl(thisTypeInFunctions.ts, 0, 0)) n: number; >n : Symbol(n, Decl(thisTypeInFunctions.ts, 1, 9)) +} +class C { +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) + + n: number; +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 4, 9)) explicitThis(this: this, m: number): number { ->explicitThis : Symbol(explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 3, 17)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 3, 28)) +>explicitThis : Symbol(explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 6, 17)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 6, 28)) return this.n + m; ->this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 1, 9)) ->this : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) ->n : Symbol(n, Decl(thisTypeInFunctions.ts, 1, 9)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 3, 28)) +>this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 4, 9)) +>this : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 4, 9)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 6, 28)) } implicitThis(m: number): number { ->implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 6, 17)) +>implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 8, 5)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 9, 17)) return this.n + m; ->this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 1, 9)) ->this : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) ->n : Symbol(n, Decl(thisTypeInFunctions.ts, 1, 9)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 6, 17)) +>this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 4, 9)) +>this : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 4, 9)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 9, 17)) } explicitC(this: C, m: number): number { ->explicitC : Symbol(explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 9, 14)) ->C : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 9, 22)) +>explicitC : Symbol(explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 12, 14)) +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 12, 22)) return this.n + m; ->this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 1, 9)) ->this : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) ->n : Symbol(n, Decl(thisTypeInFunctions.ts, 1, 9)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 9, 22)) +>this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 4, 9)) +>this : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 4, 9)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 12, 22)) } explicitProperty(this: {n: number}, m: number): number { ->explicitProperty : Symbol(explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 12, 21)) ->n : Symbol(n, Decl(thisTypeInFunctions.ts, 12, 28)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 12, 39)) +>explicitProperty : Symbol(explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 15, 21)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 15, 28)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 15, 39)) return this.n + m; ->this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 12, 28)) ->this : Symbol(, Decl(thisTypeInFunctions.ts, 12, 26)) ->n : Symbol(n, Decl(thisTypeInFunctions.ts, 12, 28)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 12, 39)) +>this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 15, 28)) +>this : Symbol(, Decl(thisTypeInFunctions.ts, 15, 26)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 15, 28)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 15, 39)) } explicitVoid(this: void, m: number): number { ->explicitVoid : Symbol(explicitVoid, Decl(thisTypeInFunctions.ts, 14, 5)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 15, 17)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 15, 28)) +>explicitVoid : Symbol(explicitVoid, Decl(thisTypeInFunctions.ts, 17, 5)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 18, 17)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 18, 28)) return m + 1; ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 15, 28)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 18, 28)) } } class D extends C { } ->D : Symbol(D, Decl(thisTypeInFunctions.ts, 18, 1)) ->C : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>D : Symbol(D, Decl(thisTypeInFunctions.ts, 21, 1)) +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) -class B { ->B : Symbol(B, Decl(thisTypeInFunctions.ts, 19, 21)) - - n: number; ->n : Symbol(n, Decl(thisTypeInFunctions.ts, 20, 9)) -} interface I { ->I : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) +>I : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 21)) a: number; >a : Symbol(a, Decl(thisTypeInFunctions.ts, 23, 13)) @@ -92,7 +92,7 @@ interface I { explicitInterface(this: I): number; >explicitInterface : Symbol(explicitInterface, Decl(thisTypeInFunctions.ts, 27, 50)) >this : Symbol(this, Decl(thisTypeInFunctions.ts, 28, 22)) ->I : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) +>I : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 21)) explicitThis(this: this): number; >explicitThis : Symbol(explicitThis, Decl(thisTypeInFunctions.ts, 28, 39)) @@ -134,7 +134,7 @@ function implicitThis(n: number): number { } let impl: I = { >impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) ->I : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) +>I : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 21)) a: 12, >a : Symbol(a, Decl(thisTypeInFunctions.ts, 42, 15)) @@ -159,7 +159,7 @@ let impl: I = { return this.a; >this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) ->this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) +>this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 21)) >a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) }, @@ -168,7 +168,7 @@ let impl: I = { return this.a; >this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) ->this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) +>this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 21)) >a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) }, @@ -177,7 +177,7 @@ let impl: I = { return this.a; >this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) ->this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) +>this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 21)) >a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) }, @@ -207,7 +207,7 @@ impl.explicitInterface = function() { return this.a; }; >impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) >explicitInterface : Symbol(I.explicitInterface, Decl(thisTypeInFunctions.ts, 27, 50)) >this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) ->this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) +>this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 21)) >a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) impl.explicitStructural = () => 12; @@ -225,7 +225,7 @@ impl.explicitThis = function () { return this.a; }; >impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) >explicitThis : Symbol(I.explicitThis, Decl(thisTypeInFunctions.ts, 28, 39)) >this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) ->this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) +>this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 21)) >a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) impl.implicitMethod = function () { return this.a; }; @@ -233,7 +233,7 @@ impl.implicitMethod = function () { return this.a; }; >impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) >implicitMethod : Symbol(I.implicitMethod, Decl(thisTypeInFunctions.ts, 29, 37)) >this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) ->this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) +>this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 21)) >a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) impl.implicitMethod = () => 12; @@ -282,57 +282,57 @@ implicitAnyOk.f(12); let c = new C(); >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->C : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) let d = new D(); >d : Symbol(d, Decl(thisTypeInFunctions.ts, 78, 3)) ->D : Symbol(D, Decl(thisTypeInFunctions.ts, 18, 1)) +>D : Symbol(D, Decl(thisTypeInFunctions.ts, 21, 1)) let ripped = c.explicitC; >ripped : Symbol(ripped, Decl(thisTypeInFunctions.ts, 79, 3)) ->c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) c.explicitC(12); ->c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) c.explicitProperty(12); ->c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) c.explicitThis(12); ->c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) c.implicitThis(12); ->c.implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) +>c.implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 8, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) +>implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 8, 5)) d.explicitC(12); ->d.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>d.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) >d : Symbol(d, Decl(thisTypeInFunctions.ts, 78, 3)) ->explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) d.explicitProperty(12); ->d.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>d.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) >d : Symbol(d, Decl(thisTypeInFunctions.ts, 78, 3)) ->explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) d.explicitThis(12); ->d.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>d.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) >d : Symbol(d, Decl(thisTypeInFunctions.ts, 78, 3)) ->explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) d.implicitThis(12); ->d.implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) +>d.implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 8, 5)) >d : Symbol(d, Decl(thisTypeInFunctions.ts, 78, 3)) ->implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) +>implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 8, 5)) let reconstructed: { >reconstructed : Symbol(reconstructed, Decl(thisTypeInFunctions.ts, 88, 3)) @@ -343,7 +343,7 @@ let reconstructed: { explicitThis(this: C, m: number): number, // note: this: this is not allowed in an object literal type. >explicitThis : Symbol(explicitThis, Decl(thisTypeInFunctions.ts, 89, 14)) >this : Symbol(this, Decl(thisTypeInFunctions.ts, 90, 17)) ->C : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 90, 25)) implicitThis(m: number): number, @@ -353,7 +353,7 @@ let reconstructed: { explicitC(this: C, m: number): number, >explicitC : Symbol(explicitC, Decl(thisTypeInFunctions.ts, 91, 36)) >this : Symbol(this, Decl(thisTypeInFunctions.ts, 92, 14)) ->C : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 92, 22)) explicitProperty: (this: {n : number}, m: number) => number, @@ -373,33 +373,33 @@ let reconstructed: { explicitThis: c.explicitThis, >explicitThis : Symbol(explicitThis, Decl(thisTypeInFunctions.ts, 96, 10)) ->c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) implicitThis: c.implicitThis, >implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 97, 33)) ->c.implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) +>c.implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 8, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) +>implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 8, 5)) explicitC: c.explicitC, >explicitC : Symbol(explicitC, Decl(thisTypeInFunctions.ts, 98, 33)) ->c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) explicitProperty: c.explicitProperty, >explicitProperty : Symbol(explicitProperty, Decl(thisTypeInFunctions.ts, 99, 27)) ->c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) explicitVoid: c.explicitVoid >explicitVoid : Symbol(explicitVoid, Decl(thisTypeInFunctions.ts, 100, 41)) ->c.explicitVoid : Symbol(C.explicitVoid, Decl(thisTypeInFunctions.ts, 14, 5)) +>c.explicitVoid : Symbol(C.explicitVoid, Decl(thisTypeInFunctions.ts, 17, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitVoid : Symbol(C.explicitVoid, Decl(thisTypeInFunctions.ts, 14, 5)) +>explicitVoid : Symbol(C.explicitVoid, Decl(thisTypeInFunctions.ts, 17, 5)) }; reconstructed.explicitProperty(11); @@ -467,7 +467,7 @@ let specifiedLambdaToSpecified: (this: {y: number}, x: number) => number = speci let explicitCFunction: (this: C, m: number) => number; >explicitCFunction : Symbol(explicitCFunction, Decl(thisTypeInFunctions.ts, 117, 3)) >this : Symbol(this, Decl(thisTypeInFunctions.ts, 117, 24)) ->C : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 117, 32)) let explicitPropertyFunction: (this: {n: number}, m: number) => number; @@ -477,33 +477,33 @@ let explicitPropertyFunction: (this: {n: number}, m: number) => number; >m : Symbol(m, Decl(thisTypeInFunctions.ts, 118, 49)) c.explicitC = explicitCFunction; ->c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) >explicitCFunction : Symbol(explicitCFunction, Decl(thisTypeInFunctions.ts, 117, 3)) c.explicitC = function(this: C, m: number) { return this.n + m }; ->c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) >this : Symbol(this, Decl(thisTypeInFunctions.ts, 120, 23)) ->C : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 120, 31)) ->this.n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) ->this : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) ->n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) +>this.n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 4, 9)) +>this : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) +>n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 4, 9)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 120, 31)) c.explicitProperty = explicitPropertyFunction; ->c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) >explicitPropertyFunction : Symbol(explicitPropertyFunction, Decl(thisTypeInFunctions.ts, 118, 3)) c.explicitProperty = function(this: {n: number}, m: number) { return this.n + m }; ->c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) >this : Symbol(this, Decl(thisTypeInFunctions.ts, 122, 30)) >n : Symbol(n, Decl(thisTypeInFunctions.ts, 122, 37)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 122, 48)) @@ -513,143 +513,143 @@ c.explicitProperty = function(this: {n: number}, m: number) { return this.n + m >m : Symbol(m, Decl(thisTypeInFunctions.ts, 122, 48)) c.explicitProperty = reconstructed.explicitProperty; ->c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) >reconstructed.explicitProperty : Symbol(explicitProperty, Decl(thisTypeInFunctions.ts, 92, 42)) >reconstructed : Symbol(reconstructed, Decl(thisTypeInFunctions.ts, 88, 3)) >explicitProperty : Symbol(explicitProperty, Decl(thisTypeInFunctions.ts, 92, 42)) // lambdas are assignable to anything c.explicitC = m => m; ->c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 126, 13)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 126, 13)) c.explicitThis = m => m; ->c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 127, 16)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 127, 16)) c.explicitProperty = m => m; ->c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 128, 20)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 128, 20)) // this inside lambdas refer to outer scope // the outer-scoped lambda at top-level is still just `any` c.explicitC = m => m + this.n; ->c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 132, 13)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 132, 13)) c.explicitThis = m => m + this.n; ->c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 133, 16)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 133, 16)) c.explicitProperty = m => m + this.n; ->c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 134, 20)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 134, 20)) //NOTE: this=C here, I guess? c.explicitThis = explicitCFunction; ->c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) >explicitCFunction : Symbol(explicitCFunction, Decl(thisTypeInFunctions.ts, 117, 3)) c.explicitThis = function(this: C, m: number) { return this.n + m }; ->c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) >this : Symbol(this, Decl(thisTypeInFunctions.ts, 138, 26)) ->C : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 138, 34)) ->this.n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) ->this : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) ->n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) +>this.n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 4, 9)) +>this : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) +>n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 4, 9)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 138, 34)) // this:any compatibility c.explicitC = function(m) { return this.n + m }; ->c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 141, 23)) ->this.n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) ->this : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) ->n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) +>this.n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 4, 9)) +>this : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) +>n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 4, 9)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 141, 23)) c.explicitProperty = function(m) { return this.n + m }; ->c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 142, 30)) ->this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 12, 28)) ->this : Symbol(, Decl(thisTypeInFunctions.ts, 12, 26)) ->n : Symbol(n, Decl(thisTypeInFunctions.ts, 12, 28)) +>this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 15, 28)) +>this : Symbol(, Decl(thisTypeInFunctions.ts, 15, 26)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 15, 28)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 142, 30)) c.explicitThis = function(m) { return this.n + m }; ->c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 143, 26)) ->this.n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) ->this : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) ->n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) +>this.n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 4, 9)) +>this : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) +>n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 4, 9)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 143, 26)) c.implicitThis = function(m) { return this.n + m }; ->c.implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) +>c.implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 8, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) +>implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 8, 5)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 144, 26)) ->this.n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) ->this : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) ->n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) +>this.n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 4, 9)) +>this : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) +>n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 4, 9)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 144, 26)) c.implicitThis = reconstructed.implicitThis; ->c.implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) +>c.implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 8, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) +>implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 8, 5)) >reconstructed.implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 90, 45)) >reconstructed : Symbol(reconstructed, Decl(thisTypeInFunctions.ts, 88, 3)) >implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 90, 45)) c.explicitC = function(this: B, m: number) { return this.n + m }; ->c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) >this : Symbol(this, Decl(thisTypeInFunctions.ts, 147, 23)) ->B : Symbol(B, Decl(thisTypeInFunctions.ts, 19, 21)) +>B : Symbol(B, Decl(thisTypeInFunctions.ts, 0, 0)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 147, 31)) ->this.n : Symbol(B.n, Decl(thisTypeInFunctions.ts, 20, 9)) ->this : Symbol(B, Decl(thisTypeInFunctions.ts, 19, 21)) ->n : Symbol(B.n, Decl(thisTypeInFunctions.ts, 20, 9)) +>this.n : Symbol(B.n, Decl(thisTypeInFunctions.ts, 1, 9)) +>this : Symbol(B, Decl(thisTypeInFunctions.ts, 0, 0)) +>n : Symbol(B.n, Decl(thisTypeInFunctions.ts, 1, 9)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 147, 31)) // this:void compatibility c.explicitVoid = n => n; ->c.explicitVoid : Symbol(C.explicitVoid, Decl(thisTypeInFunctions.ts, 14, 5)) +>c.explicitVoid : Symbol(C.explicitVoid, Decl(thisTypeInFunctions.ts, 17, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitVoid : Symbol(C.explicitVoid, Decl(thisTypeInFunctions.ts, 14, 5)) +>explicitVoid : Symbol(C.explicitVoid, Decl(thisTypeInFunctions.ts, 17, 5)) >n : Symbol(n, Decl(thisTypeInFunctions.ts, 150, 16)) >n : Symbol(n, Decl(thisTypeInFunctions.ts, 150, 16)) @@ -791,72 +791,84 @@ b1.explicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) >d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 176, 3)) >implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) +// union assignability + +let b1b2: Base1 | Base2; +>b1b2 : Symbol(b1b2, Decl(thisTypeInFunctions.ts, 188, 3)) +>Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) +>Base2 : Symbol(Base2, Decl(thisTypeInFunctions.ts, 164, 1)) + +b1b2.implicit(); +>b1b2.implicit : Symbol(implicit, Decl(thisTypeInFunctions.ts, 154, 14), Decl(thisTypeInFunctions.ts, 166, 13)) +>b1b2 : Symbol(b1b2, Decl(thisTypeInFunctions.ts, 188, 3)) +>implicit : Symbol(implicit, Decl(thisTypeInFunctions.ts, 154, 14), Decl(thisTypeInFunctions.ts, 166, 13)) + ////// use this-type for construction with new //// function InterfaceThis(this: I) { ->InterfaceThis : Symbol(InterfaceThis, Decl(thisTypeInFunctions.ts, 184, 25)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 187, 23)) ->I : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) +>InterfaceThis : Symbol(InterfaceThis, Decl(thisTypeInFunctions.ts, 189, 16)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 192, 23)) +>I : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 21)) this.a = 12; >this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) ->this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) +>this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 21)) >a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) } function LiteralTypeThis(this: {x: string}) { ->LiteralTypeThis : Symbol(LiteralTypeThis, Decl(thisTypeInFunctions.ts, 189, 1)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 190, 25)) ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 190, 32)) +>LiteralTypeThis : Symbol(LiteralTypeThis, Decl(thisTypeInFunctions.ts, 194, 1)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 195, 25)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 195, 32)) this.x = "ok"; ->this.x : Symbol(x, Decl(thisTypeInFunctions.ts, 190, 32)) ->this : Symbol(, Decl(thisTypeInFunctions.ts, 190, 30)) ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 190, 32)) +>this.x : Symbol(x, Decl(thisTypeInFunctions.ts, 195, 32)) +>this : Symbol(, Decl(thisTypeInFunctions.ts, 195, 30)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 195, 32)) } function AnyThis(this: any) { ->AnyThis : Symbol(AnyThis, Decl(thisTypeInFunctions.ts, 192, 1)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 193, 17)) +>AnyThis : Symbol(AnyThis, Decl(thisTypeInFunctions.ts, 197, 1)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 198, 17)) this.x = "ok"; } let interfaceThis = new InterfaceThis(); ->interfaceThis : Symbol(interfaceThis, Decl(thisTypeInFunctions.ts, 196, 3)) ->InterfaceThis : Symbol(InterfaceThis, Decl(thisTypeInFunctions.ts, 184, 25)) +>interfaceThis : Symbol(interfaceThis, Decl(thisTypeInFunctions.ts, 201, 3)) +>InterfaceThis : Symbol(InterfaceThis, Decl(thisTypeInFunctions.ts, 189, 16)) let literalTypeThis = new LiteralTypeThis(); ->literalTypeThis : Symbol(literalTypeThis, Decl(thisTypeInFunctions.ts, 197, 3)) ->LiteralTypeThis : Symbol(LiteralTypeThis, Decl(thisTypeInFunctions.ts, 189, 1)) +>literalTypeThis : Symbol(literalTypeThis, Decl(thisTypeInFunctions.ts, 202, 3)) +>LiteralTypeThis : Symbol(LiteralTypeThis, Decl(thisTypeInFunctions.ts, 194, 1)) let anyThis = new AnyThis(); ->anyThis : Symbol(anyThis, Decl(thisTypeInFunctions.ts, 198, 3)) ->AnyThis : Symbol(AnyThis, Decl(thisTypeInFunctions.ts, 192, 1)) +>anyThis : Symbol(anyThis, Decl(thisTypeInFunctions.ts, 203, 3)) +>AnyThis : Symbol(AnyThis, Decl(thisTypeInFunctions.ts, 197, 1)) //// type parameter inference //// declare var f: { ->f : Symbol(f, Decl(thisTypeInFunctions.ts, 201, 11)) +>f : Symbol(f, Decl(thisTypeInFunctions.ts, 206, 11)) (this: void, x: number): number, ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 202, 5)) ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 202, 16)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 207, 5)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 207, 16)) call(this: (...argArray: any[]) => U, ...argArray: any[]): U; ->call : Symbol(call, Decl(thisTypeInFunctions.ts, 202, 36)) ->U : Symbol(U, Decl(thisTypeInFunctions.ts, 203, 9)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 203, 12)) ->argArray : Symbol(argArray, Decl(thisTypeInFunctions.ts, 203, 19)) ->U : Symbol(U, Decl(thisTypeInFunctions.ts, 203, 9)) ->argArray : Symbol(argArray, Decl(thisTypeInFunctions.ts, 203, 44)) ->U : Symbol(U, Decl(thisTypeInFunctions.ts, 203, 9)) +>call : Symbol(call, Decl(thisTypeInFunctions.ts, 207, 36)) +>U : Symbol(U, Decl(thisTypeInFunctions.ts, 208, 9)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 208, 12)) +>argArray : Symbol(argArray, Decl(thisTypeInFunctions.ts, 208, 19)) +>U : Symbol(U, Decl(thisTypeInFunctions.ts, 208, 9)) +>argArray : Symbol(argArray, Decl(thisTypeInFunctions.ts, 208, 44)) +>U : Symbol(U, Decl(thisTypeInFunctions.ts, 208, 9)) }; let n: number = f.call(12); ->n : Symbol(n, Decl(thisTypeInFunctions.ts, 205, 3)) ->f.call : Symbol(call, Decl(thisTypeInFunctions.ts, 202, 36)) ->f : Symbol(f, Decl(thisTypeInFunctions.ts, 201, 11)) ->call : Symbol(call, Decl(thisTypeInFunctions.ts, 202, 36)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 210, 3)) +>f.call : Symbol(call, Decl(thisTypeInFunctions.ts, 207, 36)) +>f : Symbol(f, Decl(thisTypeInFunctions.ts, 206, 11)) +>call : Symbol(call, Decl(thisTypeInFunctions.ts, 207, 36)) function missingTypeIsImplicitAny(this, a: number) { return a; } ->missingTypeIsImplicitAny : Symbol(missingTypeIsImplicitAny, Decl(thisTypeInFunctions.ts, 205, 27)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 207, 34)) ->a : Symbol(a, Decl(thisTypeInFunctions.ts, 207, 39)) ->a : Symbol(a, Decl(thisTypeInFunctions.ts, 207, 39)) +>missingTypeIsImplicitAny : Symbol(missingTypeIsImplicitAny, Decl(thisTypeInFunctions.ts, 210, 27)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 212, 34)) +>a : Symbol(a, Decl(thisTypeInFunctions.ts, 212, 39)) +>a : Symbol(a, Decl(thisTypeInFunctions.ts, 212, 39)) diff --git a/tests/baselines/reference/thisTypeInFunctions.types b/tests/baselines/reference/thisTypeInFunctions.types index 2c334b2caed3b..e5f6a561d59bc 100644 --- a/tests/baselines/reference/thisTypeInFunctions.types +++ b/tests/baselines/reference/thisTypeInFunctions.types @@ -1,5 +1,11 @@ === tests/cases/conformance/types/thisType/thisTypeInFunctions.ts === // body checking +class B { +>B : B + + n: number; +>n : number +} class C { >C : C @@ -70,12 +76,6 @@ class D extends C { } >D : D >C : C -class B { ->B : B - - n: number; ->n : number -} interface I { >I : I @@ -952,6 +952,19 @@ b1.explicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) >d2 : Derived2 >implicit : (this: Derived2) => number +// union assignability + +let b1b2: Base1 | Base2; +>b1b2 : Base1 | Base2 +>Base1 : Base1 +>Base2 : Base2 + +b1b2.implicit(); +>b1b2.implicit() : number +>b1b2.implicit : ((this: Base1) => number) | ((this: Base2) => number) +>b1b2 : Base1 | Base2 +>implicit : ((this: Base1) => number) | ((this: Base2) => number) + ////// use this-type for construction with new //// function InterfaceThis(this: I) { >InterfaceThis : (this: I) => void diff --git a/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts b/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts index f92b8ab4e15f6..e5cc9e45ba25c 100644 --- a/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts +++ b/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts @@ -1,5 +1,8 @@ // @strictThis: true // body checking +class B { + n: number; +} class C { n: number; explicitThis(this: this, m: number): number { @@ -19,9 +22,6 @@ class C { } } class D extends C { } -class B { - n: number; -} interface I { a: number; explicitVoid1(this: void): number; @@ -185,6 +185,11 @@ d2.implicit = d1.explicit // ok, 'y' in { x, y } (c assignable to f) b1.implicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) b1.explicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) +// union assignability + +let b1b2: Base1 | Base2; +b1b2.implicit(); + ////// use this-type for construction with new //// function InterfaceThis(this: I) { this.a = 12; From 41bb4468652243e2df9f1bd563f7544469bb3021 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Mon, 8 Feb 2016 16:39:19 -0800 Subject: [PATCH 21/41] Revert unioning of this argument types The right solution is to not instantiate this-types of unions, which is a separate problem more to do with this-class types. --- src/compiler/checker.ts | 8 +- src/compiler/core.ts | 17 ---- .../looseThisTypeInFunctions.errors.txt | 22 +++-- .../reference/looseThisTypeInFunctions.js | 9 +-- .../reference/thisTypeInFunctions.js | 8 -- .../reference/thisTypeInFunctions.symbols | 80 ++++++++----------- .../reference/thisTypeInFunctions.types | 13 --- .../thisType/looseThisTypeInFunctions.ts | 8 +- .../types/thisType/thisTypeInFuncTemp.ts | 36 +++------ .../types/thisType/thisTypeInFunctions.ts | 5 -- 10 files changed, 61 insertions(+), 145 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0acb3a127d509..b9343a2cdbe08 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -9513,13 +9513,7 @@ namespace ts { const thisArgumentNode = getThisArgumentOfCall(node); const thisArgumentType = thisArgumentNode ? checkExpression(thisArgumentNode) : voidType; const errorNode = reportErrors ? (thisArgumentNode || node) : undefined; - if (thisArgumentType.flags & TypeFlags.UnionOrIntersection) { - const u = thisArgumentType; - if (!forEach(u.types, t => checkTypeRelatedTo(t, signature.thisType, relation, errorNode, headMessage))) { - return false; - } - } - else if (!checkTypeRelatedTo(thisArgumentType, signature.thisType, relation, errorNode, headMessage)) { + if (!checkTypeRelatedTo(thisArgumentType, signature.thisType, relation, errorNode, headMessage)) { return false; } } diff --git a/src/compiler/core.ts b/src/compiler/core.ts index f1f9d93c5d265..21536da36ff26 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -91,23 +91,6 @@ namespace ts { return undefined; } - /** - * Iterates through `array` by index and performs the callback on each element of array until the callback - * returns a falsey value, then returns false. - * If no such value is found, the callback is applied to each element of array and `true` is returned. - */ - export function trueForAll(array: T[], callback: (element: T, index: number) => boolean): boolean { - if (array) { - for (let i = 0, len = array.length; i < len; i++) { - if (!callback(array[i], i)) { - return false; - } - } - } - - return true; - } - export function contains(array: T[], value: T): boolean { if (array) { for (const v of array) { diff --git a/tests/baselines/reference/looseThisTypeInFunctions.errors.txt b/tests/baselines/reference/looseThisTypeInFunctions.errors.txt index 4eef7d83f787a..caaf7afb09cab 100644 --- a/tests/baselines/reference/looseThisTypeInFunctions.errors.txt +++ b/tests/baselines/reference/looseThisTypeInFunctions.errors.txt @@ -1,13 +1,12 @@ 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. Type 'void' is not assignable to type 'C'. -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(33,28): 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(46,20): error TS2339: Property 'length' does not exist on type 'number'. -==== tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts (5 errors) ==== +==== tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts (4 errors) ==== interface I { n: number; explicitThis(this: this, m: number): number; @@ -42,12 +41,10 @@ tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(46,19): error }; let i: I = o; let o2: I = { - n: 1001 + n: 1001, explicitThis: function (m) { - ~~~~~~~~~~~~ -!!! error TS1005: ',' expected. - return m + this.n.length; // error, this.n: number, no member 'length' - ~~~~~~ + return m + this.n.length; // error, this.n: number, no member 'length' + ~~~~~~ !!! error TS2339: Property 'length' does not exist on type 'number'. }, } @@ -63,8 +60,7 @@ tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(46,19): error 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 - ~~~~~~ + return this.n.length; // error, this.n: number + ~~~~~~ !!! error TS2339: Property 'length' does not exist on type 'number'. - } - \ No newline at end of file + } \ No newline at end of file diff --git a/tests/baselines/reference/looseThisTypeInFunctions.js b/tests/baselines/reference/looseThisTypeInFunctions.js index ecb9f650716de..3b172877e0e8f 100644 --- a/tests/baselines/reference/looseThisTypeInFunctions.js +++ b/tests/baselines/reference/looseThisTypeInFunctions.js @@ -29,9 +29,9 @@ let o = { }; let i: I = o; let o2: I = { - n: 1001 + n: 1001, explicitThis: function (m) { - return m + this.n.length; // error, this.n: number, no member 'length' + return m + this.n.length; // error, this.n: number, no member 'length' }, } let x = i.explicitThis; @@ -44,9 +44,8 @@ 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 -} - + return this.n.length; // error, this.n: number +} //// [looseThisTypeInFunctions.js] var C = (function () { diff --git a/tests/baselines/reference/thisTypeInFunctions.js b/tests/baselines/reference/thisTypeInFunctions.js index af55603a4b72a..8d34f9bc2cfca 100644 --- a/tests/baselines/reference/thisTypeInFunctions.js +++ b/tests/baselines/reference/thisTypeInFunctions.js @@ -185,11 +185,6 @@ d2.implicit = d1.explicit // ok, 'y' in { x, y } (c assignable to f) b1.implicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) b1.explicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) -// union assignability - -let b1b2: Base1 | Base2; -b1b2.implicit(); - ////// use this-type for construction with new //// function InterfaceThis(this: I) { this.a = 12; @@ -395,9 +390,6 @@ d1.implicit = b2.implicit; // ok, 'y' in D: { x, y } (d assignable e) d2.implicit = d1.explicit; // ok, 'y' in { x, y } (c assignable to f) b1.implicit = d2.implicit; // ok, 'x' and 'y' not in C: { x } (c assignable to f) b1.explicit = d2.implicit; // ok, 'x' and 'y' not in C: { x } (c assignable to f) -// union assignability -var b1b2; -b1b2.implicit(); ////// use this-type for construction with new //// function InterfaceThis() { this.a = 12; diff --git a/tests/baselines/reference/thisTypeInFunctions.symbols b/tests/baselines/reference/thisTypeInFunctions.symbols index 120494c206fb8..9cd1915fc941b 100644 --- a/tests/baselines/reference/thisTypeInFunctions.symbols +++ b/tests/baselines/reference/thisTypeInFunctions.symbols @@ -791,22 +791,10 @@ b1.explicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) >d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 176, 3)) >implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) -// union assignability - -let b1b2: Base1 | Base2; ->b1b2 : Symbol(b1b2, Decl(thisTypeInFunctions.ts, 188, 3)) ->Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) ->Base2 : Symbol(Base2, Decl(thisTypeInFunctions.ts, 164, 1)) - -b1b2.implicit(); ->b1b2.implicit : Symbol(implicit, Decl(thisTypeInFunctions.ts, 154, 14), Decl(thisTypeInFunctions.ts, 166, 13)) ->b1b2 : Symbol(b1b2, Decl(thisTypeInFunctions.ts, 188, 3)) ->implicit : Symbol(implicit, Decl(thisTypeInFunctions.ts, 154, 14), Decl(thisTypeInFunctions.ts, 166, 13)) - ////// use this-type for construction with new //// function InterfaceThis(this: I) { ->InterfaceThis : Symbol(InterfaceThis, Decl(thisTypeInFunctions.ts, 189, 16)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 192, 23)) +>InterfaceThis : Symbol(InterfaceThis, Decl(thisTypeInFunctions.ts, 184, 25)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 187, 23)) >I : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 21)) this.a = 12; @@ -815,60 +803,60 @@ function InterfaceThis(this: I) { >a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) } function LiteralTypeThis(this: {x: string}) { ->LiteralTypeThis : Symbol(LiteralTypeThis, Decl(thisTypeInFunctions.ts, 194, 1)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 195, 25)) ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 195, 32)) +>LiteralTypeThis : Symbol(LiteralTypeThis, Decl(thisTypeInFunctions.ts, 189, 1)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 190, 25)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 190, 32)) this.x = "ok"; ->this.x : Symbol(x, Decl(thisTypeInFunctions.ts, 195, 32)) ->this : Symbol(, Decl(thisTypeInFunctions.ts, 195, 30)) ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 195, 32)) +>this.x : Symbol(x, Decl(thisTypeInFunctions.ts, 190, 32)) +>this : Symbol(, Decl(thisTypeInFunctions.ts, 190, 30)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 190, 32)) } function AnyThis(this: any) { ->AnyThis : Symbol(AnyThis, Decl(thisTypeInFunctions.ts, 197, 1)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 198, 17)) +>AnyThis : Symbol(AnyThis, Decl(thisTypeInFunctions.ts, 192, 1)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 193, 17)) this.x = "ok"; } let interfaceThis = new InterfaceThis(); ->interfaceThis : Symbol(interfaceThis, Decl(thisTypeInFunctions.ts, 201, 3)) ->InterfaceThis : Symbol(InterfaceThis, Decl(thisTypeInFunctions.ts, 189, 16)) +>interfaceThis : Symbol(interfaceThis, Decl(thisTypeInFunctions.ts, 196, 3)) +>InterfaceThis : Symbol(InterfaceThis, Decl(thisTypeInFunctions.ts, 184, 25)) let literalTypeThis = new LiteralTypeThis(); ->literalTypeThis : Symbol(literalTypeThis, Decl(thisTypeInFunctions.ts, 202, 3)) ->LiteralTypeThis : Symbol(LiteralTypeThis, Decl(thisTypeInFunctions.ts, 194, 1)) +>literalTypeThis : Symbol(literalTypeThis, Decl(thisTypeInFunctions.ts, 197, 3)) +>LiteralTypeThis : Symbol(LiteralTypeThis, Decl(thisTypeInFunctions.ts, 189, 1)) let anyThis = new AnyThis(); ->anyThis : Symbol(anyThis, Decl(thisTypeInFunctions.ts, 203, 3)) ->AnyThis : Symbol(AnyThis, Decl(thisTypeInFunctions.ts, 197, 1)) +>anyThis : Symbol(anyThis, Decl(thisTypeInFunctions.ts, 198, 3)) +>AnyThis : Symbol(AnyThis, Decl(thisTypeInFunctions.ts, 192, 1)) //// type parameter inference //// declare var f: { ->f : Symbol(f, Decl(thisTypeInFunctions.ts, 206, 11)) +>f : Symbol(f, Decl(thisTypeInFunctions.ts, 201, 11)) (this: void, x: number): number, ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 207, 5)) ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 207, 16)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 202, 5)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 202, 16)) call(this: (...argArray: any[]) => U, ...argArray: any[]): U; ->call : Symbol(call, Decl(thisTypeInFunctions.ts, 207, 36)) ->U : Symbol(U, Decl(thisTypeInFunctions.ts, 208, 9)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 208, 12)) ->argArray : Symbol(argArray, Decl(thisTypeInFunctions.ts, 208, 19)) ->U : Symbol(U, Decl(thisTypeInFunctions.ts, 208, 9)) ->argArray : Symbol(argArray, Decl(thisTypeInFunctions.ts, 208, 44)) ->U : Symbol(U, Decl(thisTypeInFunctions.ts, 208, 9)) +>call : Symbol(call, Decl(thisTypeInFunctions.ts, 202, 36)) +>U : Symbol(U, Decl(thisTypeInFunctions.ts, 203, 9)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 203, 12)) +>argArray : Symbol(argArray, Decl(thisTypeInFunctions.ts, 203, 19)) +>U : Symbol(U, Decl(thisTypeInFunctions.ts, 203, 9)) +>argArray : Symbol(argArray, Decl(thisTypeInFunctions.ts, 203, 44)) +>U : Symbol(U, Decl(thisTypeInFunctions.ts, 203, 9)) }; let n: number = f.call(12); ->n : Symbol(n, Decl(thisTypeInFunctions.ts, 210, 3)) ->f.call : Symbol(call, Decl(thisTypeInFunctions.ts, 207, 36)) ->f : Symbol(f, Decl(thisTypeInFunctions.ts, 206, 11)) ->call : Symbol(call, Decl(thisTypeInFunctions.ts, 207, 36)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 205, 3)) +>f.call : Symbol(call, Decl(thisTypeInFunctions.ts, 202, 36)) +>f : Symbol(f, Decl(thisTypeInFunctions.ts, 201, 11)) +>call : Symbol(call, Decl(thisTypeInFunctions.ts, 202, 36)) function missingTypeIsImplicitAny(this, a: number) { return a; } ->missingTypeIsImplicitAny : Symbol(missingTypeIsImplicitAny, Decl(thisTypeInFunctions.ts, 210, 27)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 212, 34)) ->a : Symbol(a, Decl(thisTypeInFunctions.ts, 212, 39)) ->a : Symbol(a, Decl(thisTypeInFunctions.ts, 212, 39)) +>missingTypeIsImplicitAny : Symbol(missingTypeIsImplicitAny, Decl(thisTypeInFunctions.ts, 205, 27)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 207, 34)) +>a : Symbol(a, Decl(thisTypeInFunctions.ts, 207, 39)) +>a : Symbol(a, Decl(thisTypeInFunctions.ts, 207, 39)) diff --git a/tests/baselines/reference/thisTypeInFunctions.types b/tests/baselines/reference/thisTypeInFunctions.types index e5f6a561d59bc..3922e454c3ff1 100644 --- a/tests/baselines/reference/thisTypeInFunctions.types +++ b/tests/baselines/reference/thisTypeInFunctions.types @@ -952,19 +952,6 @@ b1.explicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) >d2 : Derived2 >implicit : (this: Derived2) => number -// union assignability - -let b1b2: Base1 | Base2; ->b1b2 : Base1 | Base2 ->Base1 : Base1 ->Base2 : Base2 - -b1b2.implicit(); ->b1b2.implicit() : number ->b1b2.implicit : ((this: Base1) => number) | ((this: Base2) => number) ->b1b2 : Base1 | Base2 ->implicit : ((this: Base1) => number) | ((this: Base2) => number) - ////// use this-type for construction with new //// function InterfaceThis(this: I) { >InterfaceThis : (this: I) => void diff --git a/tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts b/tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts index 3e8bdb1117085..b151961e324e1 100644 --- a/tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts +++ b/tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts @@ -28,9 +28,9 @@ let o = { }; let i: I = o; let o2: I = { - n: 1001 + n: 1001, explicitThis: function (m) { - return m + this.n.length; // error, this.n: number, no member 'length' + return m + this.n.length; // error, this.n: number, no member 'length' }, } let x = i.explicitThis; @@ -43,5 +43,5 @@ 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 -} + return this.n.length; // error, this.n: number +} \ No newline at end of file diff --git a/tests/cases/conformance/types/thisType/thisTypeInFuncTemp.ts b/tests/cases/conformance/types/thisType/thisTypeInFuncTemp.ts index 2f4873031fb6f..e4ae3deb171cd 100644 --- a/tests/cases/conformance/types/thisType/thisTypeInFuncTemp.ts +++ b/tests/cases/conformance/types/thisType/thisTypeInFuncTemp.ts @@ -1,27 +1,9 @@ -// @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!!) \ No newline at end of file +//@strictThis: true +interface A { a: number; m(this: this): number } +interface B { b: number, m(this: this): number } +interface C { c: number; m(): number } +let a: A; +let ab: A | B; +let abc: A | B | C; +// ab.m().length; +abc.m().length; // should be OK? this: any, right? \ No newline at end of file diff --git a/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts b/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts index e5cc9e45ba25c..8676d12c5abed 100644 --- a/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts +++ b/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts @@ -185,11 +185,6 @@ d2.implicit = d1.explicit // ok, 'y' in { x, y } (c assignable to f) b1.implicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) b1.explicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) -// union assignability - -let b1b2: Base1 | Base2; -b1b2.implicit(); - ////// use this-type for construction with new //// function InterfaceThis(this: I) { this.a = 12; From a014edf55a61376839682b537463b01d03929c66 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Tue, 16 Feb 2016 13:00:21 -0800 Subject: [PATCH 22/41] Address more comments and remove temp test. I added the temp test by mistake. --- src/lib/core.d.ts | 4 ++-- .../conformance/types/thisType/thisTypeInFuncTemp.ts | 9 --------- 2 files changed, 2 insertions(+), 11 deletions(-) delete mode 100644 tests/cases/conformance/types/thisType/thisTypeInFuncTemp.ts diff --git a/src/lib/core.d.ts b/src/lib/core.d.ts index 5a94b21b0fb04..efc6e12fc6db7 100644 --- a/src/lib/core.d.ts +++ b/src/lib/core.d.ts @@ -215,7 +215,7 @@ interface Function { * @param thisArg The object to be used as the this object. * @param argArray A set of arguments to be passed to the function. */ - apply(this: (this: T, ...argArray: any[]) => U, thisArg: T, argArray?: any): U; + apply(this: (this: T, ...argArray: any[]) => U, thisArg: T, argArray?: any): U; apply(this: Function, thisArg: any, argArray?: any): any; /** @@ -223,7 +223,7 @@ interface Function { * @param thisArg The object to be used as the current object. * @param argArray A list of arguments to be passed to the method. */ - call(this: (this: T, ...argArray: any[]) => U, thisArg: T, ...argArray: any[]): U; + call(this: (this: T, ...argArray: any[]) => U, thisArg: T, ...argArray: any[]): U; call(this: Function, thisArg: any, ...argArray: any[]): any; /** diff --git a/tests/cases/conformance/types/thisType/thisTypeInFuncTemp.ts b/tests/cases/conformance/types/thisType/thisTypeInFuncTemp.ts deleted file mode 100644 index e4ae3deb171cd..0000000000000 --- a/tests/cases/conformance/types/thisType/thisTypeInFuncTemp.ts +++ /dev/null @@ -1,9 +0,0 @@ -//@strictThis: true -interface A { a: number; m(this: this): number } -interface B { b: number, m(this: this): number } -interface C { c: number; m(): number } -let a: A; -let ab: A | B; -let abc: A | B | C; -// ab.m().length; -abc.m().length; // should be OK? this: any, right? \ No newline at end of file From 482acccadaa754c96e09059dff68c50619e5f8aa Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Tue, 8 Mar 2016 13:05:00 -0800 Subject: [PATCH 23/41] Union this-types of unioned call signatures And and tests and baselines --- src/compiler/checker.ts | 26 +++++++++----- .../reference/unionThisTypeInFunctions.js | 18 ++++++++++ .../unionThisTypeInFunctions.symbols | 33 +++++++++++++++++ .../reference/unionThisTypeInFunctions.types | 35 +++++++++++++++++++ .../thisType/unionThisTypeInFunctions.ts | 12 +++++++ 5 files changed, 116 insertions(+), 8 deletions(-) create mode 100644 tests/baselines/reference/unionThisTypeInFunctions.js create mode 100644 tests/baselines/reference/unionThisTypeInFunctions.symbols create mode 100644 tests/baselines/reference/unionThisTypeInFunctions.types create mode 100644 tests/cases/conformance/types/thisType/unionThisTypeInFunctions.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d1b6dc5435ea0..b5337082c0ff4 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3610,9 +3610,9 @@ namespace ts { setObjectTypeMembers(type, members, arrayType.callSignatures, arrayType.constructSignatures, arrayType.stringIndexInfo, arrayType.numberIndexInfo); } - function findMatchingSignature(signatureList: Signature[], signature: Signature, partialMatch: boolean, ignoreReturnTypes: boolean): Signature { + function findMatchingSignature(signatureList: Signature[], signature: Signature, partialMatch: boolean, ignoreThisTypes: boolean, ignoreReturnTypes: boolean): Signature { for (const s of signatureList) { - if (compareSignaturesIdentical(s, signature, partialMatch, ignoreReturnTypes, compareTypesIdentical)) { + if (compareSignaturesIdentical(s, signature, partialMatch, ignoreThisTypes, ignoreReturnTypes, compareTypesIdentical)) { return s; } } @@ -3626,7 +3626,7 @@ namespace ts { return undefined; } for (let i = 1; i < signatureLists.length; i++) { - if (!findMatchingSignature(signatureLists[i], signature, /*partialMatch*/ false, /*ignoreReturnTypes*/ false)) { + if (!findMatchingSignature(signatureLists[i], signature, /*partialMatch*/ false, /*ignoreThisTypes*/ false, /*ignoreReturnTypes*/ false)) { return undefined; } } @@ -3635,7 +3635,7 @@ namespace ts { let result: Signature[] = undefined; for (let i = 0; i < signatureLists.length; i++) { // Allow matching non-generic signatures to have excess parameters and different return types - const match = i === listIndex ? signature : findMatchingSignature(signatureLists[i], signature, /*partialMatch*/ true, /*ignoreReturnTypes*/ true); + const match = i === listIndex ? signature : findMatchingSignature(signatureLists[i], signature, /*partialMatch*/ true, /*ignoreThisTypes*/ true, /*ignoreReturnTypes*/ true); if (!match) { return undefined; } @@ -3656,13 +3656,16 @@ namespace ts { for (let i = 0; i < signatureLists.length; i++) { for (const signature of signatureLists[i]) { // Only process signatures with parameter lists that aren't already in the result list - if (!result || !findMatchingSignature(result, signature, /*partialMatch*/ false, /*ignoreReturnTypes*/ true)) { + if (!result || !findMatchingSignature(result, signature, /*partialMatch*/ false, /*ignoreThisTypes*/ true, /*ignoreReturnTypes*/ true)) { const unionSignatures = findMatchingSignatures(signatureLists, signature, i); if (unionSignatures) { let s = signature; // Union the result types when more than one signature matches if (unionSignatures.length > 1) { s = cloneSignature(signature); + if (forEach(unionSignatures, sig => sig.thisType)) { + s.thisType = getUnionType(map(unionSignatures, sig => sig.thisType || anyType)); + } // Clear resolved return type we possibly got from cloneSignature s.resolvedReturnType = undefined; s.unionSignatures = unionSignatures; @@ -6002,7 +6005,7 @@ namespace ts { } let result = Ternary.True; for (let i = 0, len = sourceSignatures.length; i < len; i++) { - const related = compareSignaturesIdentical(sourceSignatures[i], targetSignatures[i], /*partialMatch*/ false, /*ignoreReturnTypes*/ false, isRelatedTo); + const related = compareSignaturesIdentical(sourceSignatures[i], targetSignatures[i], /*partialMatch*/ false, /*ignoreThisTypes*/ false, /*ignoreReturnTypes*/ false, isRelatedTo); if (!related) { return Ternary.False; } @@ -6203,7 +6206,7 @@ namespace ts { /** * See signatureRelatedTo, compareSignaturesIdentical */ - function compareSignaturesIdentical(source: Signature, target: Signature, partialMatch: boolean, ignoreReturnTypes: boolean, compareTypes: (s: Type, t: Type) => Ternary): Ternary { + function compareSignaturesIdentical(source: Signature, target: Signature, partialMatch: boolean, ignoreThisTypes: boolean, ignoreReturnTypes: boolean, compareTypes: (s: Type, t: Type) => Ternary): Ternary { // TODO (drosen): De-duplicate code between related functions. if (source === target) { return Ternary.True; @@ -6224,6 +6227,13 @@ namespace ts { source = getErasedSignature(source); target = getErasedSignature(target); let result = Ternary.True; + if (!ignoreThisTypes && source.thisType && target.thisType) { + const related = compareTypes(source.thisType, target.thisType); + if (!related) { + return Ternary.False; + } + result &= related; + } const targetLen = target.parameters.length; for (let i = 0; i < targetLen; i++) { const s = isRestParameterIndex(source, i) ? getRestTypeOfSignature(source) : getTypeOfSymbol(source.parameters[i]); @@ -8137,7 +8147,7 @@ namespace ts { // This signature will contribute to contextual union signature signatureList = [signature]; } - else if (!compareSignaturesIdentical(signatureList[0], signature, /*partialMatch*/ false, /*ignoreReturnTypes*/ true, compareTypesIdentical)) { + else if (!compareSignaturesIdentical(signatureList[0], signature, /*partialMatch*/ false, /*ignoreThisTypes*/ true, /*ignoreReturnTypes*/ true, compareTypesIdentical)) { // Signatures aren't identical, do not use return undefined; } diff --git a/tests/baselines/reference/unionThisTypeInFunctions.js b/tests/baselines/reference/unionThisTypeInFunctions.js new file mode 100644 index 0000000000000..31ff266087b70 --- /dev/null +++ b/tests/baselines/reference/unionThisTypeInFunctions.js @@ -0,0 +1,18 @@ +//// [unionThisTypeInFunctions.ts] +interface Real { + method(n: number): void; + data: string; +} +interface Fake { + method(n: number): void; + data: number; +} +function test(r: Real | Fake) { + r.method(12); +} + + +//// [unionThisTypeInFunctions.js] +function test(r) { + r.method(12); +} diff --git a/tests/baselines/reference/unionThisTypeInFunctions.symbols b/tests/baselines/reference/unionThisTypeInFunctions.symbols new file mode 100644 index 0000000000000..8b5f2af01e0ba --- /dev/null +++ b/tests/baselines/reference/unionThisTypeInFunctions.symbols @@ -0,0 +1,33 @@ +=== tests/cases/conformance/types/thisType/unionThisTypeInFunctions.ts === +interface Real { +>Real : Symbol(Real, Decl(unionThisTypeInFunctions.ts, 0, 0)) + + method(n: number): void; +>method : Symbol(method, Decl(unionThisTypeInFunctions.ts, 0, 16)) +>n : Symbol(n, Decl(unionThisTypeInFunctions.ts, 1, 11)) + + data: string; +>data : Symbol(data, Decl(unionThisTypeInFunctions.ts, 1, 28)) +} +interface Fake { +>Fake : Symbol(Fake, Decl(unionThisTypeInFunctions.ts, 3, 1)) + + method(n: number): void; +>method : Symbol(method, Decl(unionThisTypeInFunctions.ts, 4, 16)) +>n : Symbol(n, Decl(unionThisTypeInFunctions.ts, 5, 11)) + + data: number; +>data : Symbol(data, Decl(unionThisTypeInFunctions.ts, 5, 28)) +} +function test(r: Real | Fake) { +>test : Symbol(test, Decl(unionThisTypeInFunctions.ts, 7, 1)) +>r : Symbol(r, Decl(unionThisTypeInFunctions.ts, 8, 14)) +>Real : Symbol(Real, Decl(unionThisTypeInFunctions.ts, 0, 0)) +>Fake : Symbol(Fake, Decl(unionThisTypeInFunctions.ts, 3, 1)) + + r.method(12); +>r.method : Symbol(method, Decl(unionThisTypeInFunctions.ts, 0, 16), Decl(unionThisTypeInFunctions.ts, 4, 16)) +>r : Symbol(r, Decl(unionThisTypeInFunctions.ts, 8, 14)) +>method : Symbol(method, Decl(unionThisTypeInFunctions.ts, 0, 16), Decl(unionThisTypeInFunctions.ts, 4, 16)) +} + diff --git a/tests/baselines/reference/unionThisTypeInFunctions.types b/tests/baselines/reference/unionThisTypeInFunctions.types new file mode 100644 index 0000000000000..f2c4f7ee4ec42 --- /dev/null +++ b/tests/baselines/reference/unionThisTypeInFunctions.types @@ -0,0 +1,35 @@ +=== tests/cases/conformance/types/thisType/unionThisTypeInFunctions.ts === +interface Real { +>Real : Real + + method(n: number): void; +>method : (this: this, n: number) => void +>n : number + + data: string; +>data : string +} +interface Fake { +>Fake : Fake + + method(n: number): void; +>method : (this: this, n: number) => void +>n : number + + data: number; +>data : number +} +function test(r: Real | Fake) { +>test : (this: void, r: Real | Fake) => void +>r : Real | Fake +>Real : Real +>Fake : Fake + + r.method(12); +>r.method(12) : void +>r.method : ((this: Real, n: number) => void) | ((this: Fake, n: number) => void) +>r : Real | Fake +>method : ((this: Real, n: number) => void) | ((this: Fake, n: number) => void) +>12 : number +} + diff --git a/tests/cases/conformance/types/thisType/unionThisTypeInFunctions.ts b/tests/cases/conformance/types/thisType/unionThisTypeInFunctions.ts new file mode 100644 index 0000000000000..a140c3fba958d --- /dev/null +++ b/tests/cases/conformance/types/thisType/unionThisTypeInFunctions.ts @@ -0,0 +1,12 @@ +// @strictThis: true +interface Real { + method(n: number): void; + data: string; +} +interface Fake { + method(n: number): void; + data: number; +} +function test(r: Real | Fake) { + r.method(12); +} From 7b531fcd05334c059a1eaa27c67807046a8bfeec Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 9 Mar 2016 13:06:06 -0800 Subject: [PATCH 24/41] Check this expressions in object literal methods Add a test and baseline --- src/compiler/checker.ts | 8 +++++++ .../reference/thisTypeInObjectLiterals.js | 16 ++++++++++++++ .../thisTypeInObjectLiterals.symbols | 19 +++++++++++++++++ .../reference/thisTypeInObjectLiterals.types | 21 +++++++++++++++++++ .../thisType/thisTypeInObjectLiterals.ts | 6 ++++++ 5 files changed, 70 insertions(+) create mode 100644 tests/baselines/reference/thisTypeInObjectLiterals.js create mode 100644 tests/baselines/reference/thisTypeInObjectLiterals.symbols create mode 100644 tests/baselines/reference/thisTypeInObjectLiterals.types create mode 100644 tests/cases/conformance/types/thisType/thisTypeInObjectLiterals.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b5337082c0ff4..7073af85fcfd3 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7494,6 +7494,14 @@ namespace ts { const symbol = getSymbolOfNode(container.parent); return container.flags & NodeFlags.Static ? getTypeOfSymbol(symbol) : (getDeclaredTypeOfSymbol(symbol)).thisType; } + if (container.parent && container.parent.kind === SyntaxKind.ObjectLiteralExpression) { + // Note: this works because object literal methods are deferred, + // which means that the type of the containing object literal is already known. + const type = checkExpressionCached(container.parent); + if (type) { + return type; + } + } if (isInJavaScriptFile(node)) { const type = getTypeForThisExpressionFromJSDoc(container); diff --git a/tests/baselines/reference/thisTypeInObjectLiterals.js b/tests/baselines/reference/thisTypeInObjectLiterals.js new file mode 100644 index 0000000000000..78854bf2388b3 --- /dev/null +++ b/tests/baselines/reference/thisTypeInObjectLiterals.js @@ -0,0 +1,16 @@ +//// [thisTypeInObjectLiterals.ts] +let o = { + d: "bar", + m() { + return this.d.length; + } +} + + +//// [thisTypeInObjectLiterals.js] +var o = { + d: "bar", + m: function () { + return this.d.length; + } +}; diff --git a/tests/baselines/reference/thisTypeInObjectLiterals.symbols b/tests/baselines/reference/thisTypeInObjectLiterals.symbols new file mode 100644 index 0000000000000..6bea6d88c5830 --- /dev/null +++ b/tests/baselines/reference/thisTypeInObjectLiterals.symbols @@ -0,0 +1,19 @@ +=== tests/cases/conformance/types/thisType/thisTypeInObjectLiterals.ts === +let o = { +>o : Symbol(o, Decl(thisTypeInObjectLiterals.ts, 0, 3)) + + d: "bar", +>d : Symbol(d, Decl(thisTypeInObjectLiterals.ts, 0, 9)) + + m() { +>m : Symbol(m, Decl(thisTypeInObjectLiterals.ts, 1, 13)) + + return this.d.length; +>this.d.length : Symbol(String.length, Decl(lib.d.ts, --, --)) +>this.d : Symbol(d, Decl(thisTypeInObjectLiterals.ts, 0, 9)) +>this : Symbol(, Decl(thisTypeInObjectLiterals.ts, 0, 7)) +>d : Symbol(d, Decl(thisTypeInObjectLiterals.ts, 0, 9)) +>length : Symbol(String.length, Decl(lib.d.ts, --, --)) + } +} + diff --git a/tests/baselines/reference/thisTypeInObjectLiterals.types b/tests/baselines/reference/thisTypeInObjectLiterals.types new file mode 100644 index 0000000000000..824b0b00f4ca1 --- /dev/null +++ b/tests/baselines/reference/thisTypeInObjectLiterals.types @@ -0,0 +1,21 @@ +=== tests/cases/conformance/types/thisType/thisTypeInObjectLiterals.ts === +let o = { +>o : { d: string; m(): number; } +>{ d: "bar", m() { return this.d.length; }} : { d: string; m(): number; } + + d: "bar", +>d : string +>"bar" : string + + m() { +>m : () => number + + return this.d.length; +>this.d.length : number +>this.d : string +>this : { d: string; m(): number; } +>d : string +>length : number + } +} + diff --git a/tests/cases/conformance/types/thisType/thisTypeInObjectLiterals.ts b/tests/cases/conformance/types/thisType/thisTypeInObjectLiterals.ts new file mode 100644 index 0000000000000..11c6b58d7104d --- /dev/null +++ b/tests/cases/conformance/types/thisType/thisTypeInObjectLiterals.ts @@ -0,0 +1,6 @@ +let o = { + d: "bar", + m() { + return this.d.length; + } +} From 4012587808d3027c88360c2f16e90075c2a32b90 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 9 Mar 2016 13:08:09 -0800 Subject: [PATCH 25/41] Update baselines: 'this' in object literal methods --- .../reference/commentsOnObjectLiteral3.symbols | 7 +++++++ .../reference/commentsOnObjectLiteral3.types | 12 ++++++------ .../baselines/reference/commentsOnObjectLiteral4.js | 7 ++++--- .../reference/commentsOnObjectLiteral4.symbols | 3 ++- .../reference/commentsOnObjectLiteral4.types | 9 ++++----- .../declFileObjectLiteralWithAccessors.symbols | 3 +++ .../declFileObjectLiteralWithAccessors.types | 6 +++--- .../declFileObjectLiteralWithOnlySetter.symbols | 3 +++ .../declFileObjectLiteralWithOnlySetter.types | 6 +++--- .../declarationEmitThisPredicates02.errors.txt | 7 ++++++- ...ionEmitThisPredicatesWithPrivateName02.errors.txt | 7 ++++++- ...xponentiationAssignmentWithIndexingOnLHS3.symbols | 7 +++++++ ...dExponentiationAssignmentWithIndexingOnLHS3.types | 12 ++++++------ .../reference/thisInObjectLiterals.errors.txt | 5 ++++- .../reference/throwInEnclosingStatements.symbols | 1 + .../reference/throwInEnclosingStatements.types | 2 +- tests/cases/compiler/commentsOnObjectLiteral4.ts | 4 ++-- .../expressions/thisKeyword/thisInObjectLiterals.ts | 2 +- 18 files changed, 69 insertions(+), 34 deletions(-) diff --git a/tests/baselines/reference/commentsOnObjectLiteral3.symbols b/tests/baselines/reference/commentsOnObjectLiteral3.symbols index 3d58fe2d6d7eb..81fa15b6a11de 100644 --- a/tests/baselines/reference/commentsOnObjectLiteral3.symbols +++ b/tests/baselines/reference/commentsOnObjectLiteral3.symbols @@ -21,6 +21,10 @@ var v = { >a : Symbol(a, Decl(commentsOnObjectLiteral3.ts, 8, 13), Decl(commentsOnObjectLiteral3.ts, 12, 18)) return this.prop; +>this.prop : Symbol(prop, Decl(commentsOnObjectLiteral3.ts, 1, 9)) +>this : Symbol(, Decl(commentsOnObjectLiteral3.ts, 1, 7)) +>prop : Symbol(prop, Decl(commentsOnObjectLiteral3.ts, 1, 9)) + } /*trailing 1*/, //setter set a(value) { @@ -28,6 +32,9 @@ var v = { >value : Symbol(value, Decl(commentsOnObjectLiteral3.ts, 14, 7)) this.prop = value; +>this.prop : Symbol(prop, Decl(commentsOnObjectLiteral3.ts, 1, 9)) +>this : Symbol(, Decl(commentsOnObjectLiteral3.ts, 1, 7)) +>prop : Symbol(prop, Decl(commentsOnObjectLiteral3.ts, 1, 9)) >value : Symbol(value, Decl(commentsOnObjectLiteral3.ts, 14, 7)) } // trailing 2 diff --git a/tests/baselines/reference/commentsOnObjectLiteral3.types b/tests/baselines/reference/commentsOnObjectLiteral3.types index a63920fce0f3a..26a1e2e4250e5 100644 --- a/tests/baselines/reference/commentsOnObjectLiteral3.types +++ b/tests/baselines/reference/commentsOnObjectLiteral3.types @@ -24,9 +24,9 @@ var v = { >a : any return this.prop; ->this.prop : any ->this : any ->prop : any +>this.prop : number +>this : { prop: number; func: () => void; func1(): void; a: any; } +>prop : number } /*trailing 1*/, //setter @@ -36,9 +36,9 @@ var v = { this.prop = value; >this.prop = value : any ->this.prop : any ->this : any ->prop : any +>this.prop : number +>this : { prop: number; func: () => void; func1(): void; a: any; } +>prop : number >value : any } // trailing 2 diff --git a/tests/baselines/reference/commentsOnObjectLiteral4.js b/tests/baselines/reference/commentsOnObjectLiteral4.js index 3b7efefdff49c..23e238b8307dc 100644 --- a/tests/baselines/reference/commentsOnObjectLiteral4.js +++ b/tests/baselines/reference/commentsOnObjectLiteral4.js @@ -5,9 +5,10 @@ var v = { * @type {number} */ get bar(): number { - return this._bar; + return 12; } -} +} + //// [commentsOnObjectLiteral4.js] var v = { @@ -15,6 +16,6 @@ var v = { * @type {number} */ get bar() { - return this._bar; + return 12; } }; diff --git a/tests/baselines/reference/commentsOnObjectLiteral4.symbols b/tests/baselines/reference/commentsOnObjectLiteral4.symbols index c1762cb75c8e8..568d633212625 100644 --- a/tests/baselines/reference/commentsOnObjectLiteral4.symbols +++ b/tests/baselines/reference/commentsOnObjectLiteral4.symbols @@ -9,6 +9,7 @@ var v = { get bar(): number { >bar : Symbol(bar, Decl(commentsOnObjectLiteral4.ts, 1, 9)) - return this._bar; + return 12; } } + diff --git a/tests/baselines/reference/commentsOnObjectLiteral4.types b/tests/baselines/reference/commentsOnObjectLiteral4.types index f458d73ae3652..5d20d4f79cc87 100644 --- a/tests/baselines/reference/commentsOnObjectLiteral4.types +++ b/tests/baselines/reference/commentsOnObjectLiteral4.types @@ -2,7 +2,7 @@ var v = { >v : { readonly bar: number; } ->{ /** * @type {number} */ get bar(): number { return this._bar; }} : { readonly bar: number; } +>{ /** * @type {number} */ get bar(): number { return 12; }} : { readonly bar: number; } /** * @type {number} @@ -10,9 +10,8 @@ var v = { get bar(): number { >bar : number - return this._bar; ->this._bar : any ->this : any ->_bar : any + return 12; +>12 : number } } + diff --git a/tests/baselines/reference/declFileObjectLiteralWithAccessors.symbols b/tests/baselines/reference/declFileObjectLiteralWithAccessors.symbols index 862b0b3781eff..9b3599da67425 100644 --- a/tests/baselines/reference/declFileObjectLiteralWithAccessors.symbols +++ b/tests/baselines/reference/declFileObjectLiteralWithAccessors.symbols @@ -15,6 +15,9 @@ function /*1*/makePoint(x: number) { set x(a: number) { this.b = a; } >x : Symbol(x, Decl(declFileObjectLiteralWithAccessors.ts, 3, 14), Decl(declFileObjectLiteralWithAccessors.ts, 4, 30)) >a : Symbol(a, Decl(declFileObjectLiteralWithAccessors.ts, 5, 14)) +>this.b : Symbol(b, Decl(declFileObjectLiteralWithAccessors.ts, 2, 12)) +>this : Symbol(, Decl(declFileObjectLiteralWithAccessors.ts, 2, 10)) +>b : Symbol(b, Decl(declFileObjectLiteralWithAccessors.ts, 2, 12)) >a : Symbol(a, Decl(declFileObjectLiteralWithAccessors.ts, 5, 14)) }; diff --git a/tests/baselines/reference/declFileObjectLiteralWithAccessors.types b/tests/baselines/reference/declFileObjectLiteralWithAccessors.types index f7bb57b0e1e7d..1bf012605c1e7 100644 --- a/tests/baselines/reference/declFileObjectLiteralWithAccessors.types +++ b/tests/baselines/reference/declFileObjectLiteralWithAccessors.types @@ -19,9 +19,9 @@ function /*1*/makePoint(x: number) { >x : number >a : number >this.b = a : number ->this.b : any ->this : any ->b : any +>this.b : number +>this : { b: number; x: number; } +>b : number >a : number }; diff --git a/tests/baselines/reference/declFileObjectLiteralWithOnlySetter.symbols b/tests/baselines/reference/declFileObjectLiteralWithOnlySetter.symbols index f747446614018..89b7b9dd74794 100644 --- a/tests/baselines/reference/declFileObjectLiteralWithOnlySetter.symbols +++ b/tests/baselines/reference/declFileObjectLiteralWithOnlySetter.symbols @@ -11,6 +11,9 @@ function /*1*/makePoint(x: number) { set x(a: number) { this.b = a; } >x : Symbol(x, Decl(declFileObjectLiteralWithOnlySetter.ts, 3, 14)) >a : Symbol(a, Decl(declFileObjectLiteralWithOnlySetter.ts, 4, 14)) +>this.b : Symbol(b, Decl(declFileObjectLiteralWithOnlySetter.ts, 2, 12)) +>this : Symbol(, Decl(declFileObjectLiteralWithOnlySetter.ts, 2, 10)) +>b : Symbol(b, Decl(declFileObjectLiteralWithOnlySetter.ts, 2, 12)) >a : Symbol(a, Decl(declFileObjectLiteralWithOnlySetter.ts, 4, 14)) }; diff --git a/tests/baselines/reference/declFileObjectLiteralWithOnlySetter.types b/tests/baselines/reference/declFileObjectLiteralWithOnlySetter.types index 2b9b98a896398..1bce86915ade7 100644 --- a/tests/baselines/reference/declFileObjectLiteralWithOnlySetter.types +++ b/tests/baselines/reference/declFileObjectLiteralWithOnlySetter.types @@ -15,9 +15,9 @@ function /*1*/makePoint(x: number) { >x : number >a : number >this.b = a : number ->this.b : any ->this : any ->b : any +>this.b : number +>this : { b: number; x: number; } +>b : number >a : number }; diff --git a/tests/baselines/reference/declarationEmitThisPredicates02.errors.txt b/tests/baselines/reference/declarationEmitThisPredicates02.errors.txt index 4d95cf01136fd..8cf85d4f7647d 100644 --- a/tests/baselines/reference/declarationEmitThisPredicates02.errors.txt +++ b/tests/baselines/reference/declarationEmitThisPredicates02.errors.txt @@ -1,7 +1,9 @@ tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicates02.ts(9,10): error TS2526: A 'this' type is available only in a non-static member of a class or interface. +tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicates02.ts(10,19): error TS2352: Neither type '{ m(): this is Foo; }' nor type 'Foo' is assignable to the other. + Property 'a' is missing in type '{ m(): this is Foo; }'. -==== tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicates02.ts (1 errors) ==== +==== tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicates02.ts (2 errors) ==== export interface Foo { a: string; @@ -14,6 +16,9 @@ tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredic ~~~~ !!! error TS2526: A 'this' type is available only in a non-static member of a class or interface. let dis = this as Foo; + ~~~~~~~~~~~ +!!! error TS2352: Neither type '{ m(): this is Foo; }' nor type 'Foo' is assignable to the other. +!!! error TS2352: Property 'a' is missing in type '{ m(): this is Foo; }'. return dis.a != null && dis.b != null && dis.c != null; } } \ No newline at end of file diff --git a/tests/baselines/reference/declarationEmitThisPredicatesWithPrivateName02.errors.txt b/tests/baselines/reference/declarationEmitThisPredicatesWithPrivateName02.errors.txt index 86c0f478133c3..0c0661023f5df 100644 --- a/tests/baselines/reference/declarationEmitThisPredicatesWithPrivateName02.errors.txt +++ b/tests/baselines/reference/declarationEmitThisPredicatesWithPrivateName02.errors.txt @@ -1,8 +1,10 @@ tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicatesWithPrivateName02.ts(8,14): error TS4025: Exported variable 'obj' has or is using private name 'Foo'. tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicatesWithPrivateName02.ts(9,10): error TS2526: A 'this' type is available only in a non-static member of a class or interface. +tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicatesWithPrivateName02.ts(10,19): error TS2352: Neither type '{ m(): this is Foo; }' nor type 'Foo' is assignable to the other. + Property 'a' is missing in type '{ m(): this is Foo; }'. -==== tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicatesWithPrivateName02.ts (2 errors) ==== +==== tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicatesWithPrivateName02.ts (3 errors) ==== interface Foo { a: string; @@ -17,6 +19,9 @@ tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredic ~~~~ !!! error TS2526: A 'this' type is available only in a non-static member of a class or interface. let dis = this as Foo; + ~~~~~~~~~~~ +!!! error TS2352: Neither type '{ m(): this is Foo; }' nor type 'Foo' is assignable to the other. +!!! error TS2352: Property 'a' is missing in type '{ m(): this is Foo; }'. return dis.a != null && dis.b != null && dis.c != null; } } \ No newline at end of file diff --git a/tests/baselines/reference/emitCompoundExponentiationAssignmentWithIndexingOnLHS3.symbols b/tests/baselines/reference/emitCompoundExponentiationAssignmentWithIndexingOnLHS3.symbols index dbd5aa150dc5e..4da659c4a1a74 100644 --- a/tests/baselines/reference/emitCompoundExponentiationAssignmentWithIndexingOnLHS3.symbols +++ b/tests/baselines/reference/emitCompoundExponentiationAssignmentWithIndexingOnLHS3.symbols @@ -8,11 +8,18 @@ var object = { get 0() { return this._0; +>this._0 : Symbol(_0, Decl(emitCompoundExponentiationAssignmentWithIndexingOnLHS3.ts, 1, 14)) +>this : Symbol(, Decl(emitCompoundExponentiationAssignmentWithIndexingOnLHS3.ts, 1, 12)) +>_0 : Symbol(_0, Decl(emitCompoundExponentiationAssignmentWithIndexingOnLHS3.ts, 1, 14)) + }, set 0(x: number) { >x : Symbol(x, Decl(emitCompoundExponentiationAssignmentWithIndexingOnLHS3.ts, 6, 10)) this._0 = x; +>this._0 : Symbol(_0, Decl(emitCompoundExponentiationAssignmentWithIndexingOnLHS3.ts, 1, 14)) +>this : Symbol(, Decl(emitCompoundExponentiationAssignmentWithIndexingOnLHS3.ts, 1, 12)) +>_0 : Symbol(_0, Decl(emitCompoundExponentiationAssignmentWithIndexingOnLHS3.ts, 1, 14)) >x : Symbol(x, Decl(emitCompoundExponentiationAssignmentWithIndexingOnLHS3.ts, 6, 10)) }, diff --git a/tests/baselines/reference/emitCompoundExponentiationAssignmentWithIndexingOnLHS3.types b/tests/baselines/reference/emitCompoundExponentiationAssignmentWithIndexingOnLHS3.types index 1877f3912070c..b47c88f3de3f0 100644 --- a/tests/baselines/reference/emitCompoundExponentiationAssignmentWithIndexingOnLHS3.types +++ b/tests/baselines/reference/emitCompoundExponentiationAssignmentWithIndexingOnLHS3.types @@ -10,9 +10,9 @@ var object = { get 0() { return this._0; ->this._0 : any ->this : any ->_0 : any +>this._0 : number +>this : { 0: number; _0: number; } +>_0 : number }, set 0(x: number) { @@ -20,9 +20,9 @@ var object = { this._0 = x; >this._0 = x : number ->this._0 : any ->this : any ->_0 : any +>this._0 : number +>this : { 0: number; _0: number; } +>_0 : number >x : number }, diff --git a/tests/baselines/reference/thisInObjectLiterals.errors.txt b/tests/baselines/reference/thisInObjectLiterals.errors.txt index 73300d86d74f1..f956ce42e345f 100644 --- a/tests/baselines/reference/thisInObjectLiterals.errors.txt +++ b/tests/baselines/reference/thisInObjectLiterals.errors.txt @@ -1,7 +1,8 @@ tests/cases/conformance/expressions/thisKeyword/thisInObjectLiterals.ts(7,13): error TS2403: Subsequent variable declarations must have the same type. Variable 't' must be of type '{ x: this; y: number; }', but here has type '{ x: MyClass; y: number; }'. +tests/cases/conformance/expressions/thisKeyword/thisInObjectLiterals.ts(14,21): error TS2339: Property 'spaaace' does not exist on type '{ f(): any; }'. -==== tests/cases/conformance/expressions/thisKeyword/thisInObjectLiterals.ts (1 errors) ==== +==== tests/cases/conformance/expressions/thisKeyword/thisInObjectLiterals.ts (2 errors) ==== class MyClass { t: number; @@ -18,6 +19,8 @@ tests/cases/conformance/expressions/thisKeyword/thisInObjectLiterals.ts(7,13): e var obj = { f() { return this.spaaace; + ~~~~~~~ +!!! error TS2339: Property 'spaaace' does not exist on type '{ f(): any; }'. } }; var obj: { f: () => any; }; diff --git a/tests/baselines/reference/throwInEnclosingStatements.symbols b/tests/baselines/reference/throwInEnclosingStatements.symbols index 42053c60efa06..06fd9d53ff8a7 100644 --- a/tests/baselines/reference/throwInEnclosingStatements.symbols +++ b/tests/baselines/reference/throwInEnclosingStatements.symbols @@ -89,6 +89,7 @@ var aa = { >biz : Symbol(biz, Decl(throwInEnclosingStatements.ts, 41, 10)) throw this; +>this : Symbol(, Decl(throwInEnclosingStatements.ts, 40, 8)) } } diff --git a/tests/baselines/reference/throwInEnclosingStatements.types b/tests/baselines/reference/throwInEnclosingStatements.types index 32f0fb093bcd9..8add6e8b1a835 100644 --- a/tests/baselines/reference/throwInEnclosingStatements.types +++ b/tests/baselines/reference/throwInEnclosingStatements.types @@ -104,7 +104,7 @@ var aa = { >biz : () => void throw this; ->this : any +>this : { id: number; biz(): void; } } } diff --git a/tests/cases/compiler/commentsOnObjectLiteral4.ts b/tests/cases/compiler/commentsOnObjectLiteral4.ts index d685304f31ef1..dfb9e42b3cb26 100644 --- a/tests/cases/compiler/commentsOnObjectLiteral4.ts +++ b/tests/cases/compiler/commentsOnObjectLiteral4.ts @@ -6,6 +6,6 @@ var v = { * @type {number} */ get bar(): number { - return this._bar; + return 12; } -} \ No newline at end of file +} diff --git a/tests/cases/conformance/expressions/thisKeyword/thisInObjectLiterals.ts b/tests/cases/conformance/expressions/thisKeyword/thisInObjectLiterals.ts index da38484bc07c3..ddfbb790980e4 100644 --- a/tests/cases/conformance/expressions/thisKeyword/thisInObjectLiterals.ts +++ b/tests/cases/conformance/expressions/thisKeyword/thisInObjectLiterals.ts @@ -8,7 +8,7 @@ class MyClass { } } -//type of 'this' in an object literal property of a function type is Any +//type of 'this' in an object literal method is the type of the object literal var obj = { f() { return this.spaaace; From 32978247bd1778136a2d83a87a2d6cf7fb729e09 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 9 Mar 2016 13:20:49 -0800 Subject: [PATCH 26/41] Add missed update of thisInObjectLiterals baseline --- tests/baselines/reference/thisInObjectLiterals.errors.txt | 2 +- tests/baselines/reference/thisInObjectLiterals.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/baselines/reference/thisInObjectLiterals.errors.txt b/tests/baselines/reference/thisInObjectLiterals.errors.txt index f956ce42e345f..b0b1c63a34a91 100644 --- a/tests/baselines/reference/thisInObjectLiterals.errors.txt +++ b/tests/baselines/reference/thisInObjectLiterals.errors.txt @@ -15,7 +15,7 @@ tests/cases/conformance/expressions/thisKeyword/thisInObjectLiterals.ts(14,21): } } - //type of 'this' in an object literal property of a function type is Any + //type of 'this' in an object literal method is the type of the object literal var obj = { f() { return this.spaaace; diff --git a/tests/baselines/reference/thisInObjectLiterals.js b/tests/baselines/reference/thisInObjectLiterals.js index 4e71347a366e1..6c8380060a721 100644 --- a/tests/baselines/reference/thisInObjectLiterals.js +++ b/tests/baselines/reference/thisInObjectLiterals.js @@ -9,7 +9,7 @@ class MyClass { } } -//type of 'this' in an object literal property of a function type is Any +//type of 'this' in an object literal method is the type of the object literal var obj = { f() { return this.spaaace; @@ -29,7 +29,7 @@ var MyClass = (function () { }; return MyClass; }()); -//type of 'this' in an object literal property of a function type is Any +//type of 'this' in an object literal method is the type of the object literal var obj = { f: function () { return this.spaaace; From 3a46e72bde6f3fd8f9801022575f9024e95a9339 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 9 Mar 2016 13:40:17 -0800 Subject: [PATCH 27/41] After merge, update error numbers in baselines --- .../thisTypeInFunctionsNegative.errors.txt | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt b/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt index fdb9489f639d4..c48ea11b3b001 100644 --- a/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt +++ b/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt @@ -91,10 +91,10 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(168,1): er tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(170,1): error TS2322: Type '(this: Base2) => number' is not assignable to type '(this: Base1) => number'. Types of parameters 'this' and 'this' are incompatible. Type 'Base1' is not assignable to type 'Base2'. -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,17): error TS2674: A constructor cannot have a 'this' parameter. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(187,30): error TS2673: 'this' parameter must be the first parameter. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(179,16): error TS2678: 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 TS2678: 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,17): error TS2680: A constructor cannot have a 'this' parameter. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(187,30): error TS2679: 'this' parameter must be the first parameter. tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(187,61): error TS2339: Property 'n' does not exist on type 'void'. tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(190,26): error TS1003: Identifier expected. tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(190,30): error TS1005: ',' expected. @@ -443,21 +443,21 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(197,35): e } let voidThis = new VoidThis(); ~~~~~~~~~~~~~~ -!!! error TS2672: A function that is called with the 'new' keyword cannot have a 'this' type that is void. +!!! error TS2678: A function that is called with the 'new' keyword cannot have a 'this' type that is void. let implicitVoidThis = new ImplicitVoidThis(); ~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2672: A function that is called with the 'new' keyword cannot have a 'this' type that is void. +!!! error TS2678: A function that is called with the 'new' keyword cannot have a 'this' type that is void. ///// syntax-ish errors ///// class ThisConstructor { constructor(this: ThisConstructor, private n: number) { ~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2674: A constructor cannot have a 'this' parameter. +!!! error TS2680: A constructor cannot have a 'this' parameter. } } function notFirst(a: number, this: C): number { return this.n; } ~~~~~~~ -!!! error TS2673: 'this' parameter must be the first parameter. +!!! error TS2679: 'this' parameter must be the first parameter. ~ !!! error TS2339: Property 'n' does not exist on type 'void'. From 1032cc54089c48025e361f91303942b9b7a54122 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 11 Mar 2016 13:24:31 -0800 Subject: [PATCH 28/41] Rename --strictThis to --strictThisChecks Use the upcoming naming scheme for --strict.*Checks and --strictChecks flags. --- src/compiler/binder.ts | 2 +- src/compiler/checker.ts | 4 ++-- src/compiler/commandLineParser.ts | 2 +- src/compiler/types.ts | 2 +- tests/baselines/reference/thisTypeInFunctions.js | 3 ++- tests/cases/conformance/types/thisType/thisTypeInFunctions.ts | 4 ++-- .../conformance/types/thisType/thisTypeInFunctionsNegative.ts | 2 +- .../conformance/types/thisType/unionThisTypeInFunctions.ts | 2 +- tests/cases/fourslash/memberListOnExplicitThis.ts | 2 +- tests/cases/fourslash/quickInfoOnThis.ts | 4 ++-- 10 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 10183f9a63fc3..7ae21a6338e47 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -1307,7 +1307,7 @@ namespace ts { // as other properties in the object literal. So we use SymbolFlags.PropertyExcludes // so that it will conflict with any other object literal members with the same // name. - if (options.strictThis) { + if (options.strictThisChecks) { seenThisKeyword = true; } return bindPropertyOrMethodOrAccessor(node, SymbolFlags.Method | ((node).questionToken ? SymbolFlags.Optional : SymbolFlags.None), diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4a1299196f16b..5017f0dcd2c7d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3520,7 +3520,7 @@ namespace ts { return isIndependentVariableLikeDeclaration(declaration); case SyntaxKind.MethodDeclaration: case SyntaxKind.MethodSignature: - return compilerOptions.strictThis ? false : isIndependentFunctionLikeDeclaration(declaration); + return compilerOptions.strictThisChecks ? false : isIndependentFunctionLikeDeclaration(declaration); case SyntaxKind.Constructor: return isIndependentFunctionLikeDeclaration(declaration); } @@ -4234,7 +4234,7 @@ namespace ts { if (minArgumentCount < 0) { minArgumentCount = declaration.parameters.length - (hasThisParameter ? 1 : 0); } - if (!hasThisParameter && compilerOptions.strictThis) { + if (!hasThisParameter && compilerOptions.strictThisChecks) { if (declaration.kind === SyntaxKind.FunctionDeclaration || declaration.kind === SyntaxKind.CallSignature || declaration.kind == SyntaxKind.FunctionExpression || diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 01d18d3a7552b..f6e1d9b48d70c 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -138,7 +138,7 @@ namespace ts { type: "boolean", }, { - name: "strictThis", + name: "strictThisChecks", type: "boolean", }, { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 4d12e0bce9902..dfa1b54e42812 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2407,7 +2407,7 @@ namespace ts { rootDir?: string; sourceMap?: boolean; sourceRoot?: string; - strictThis?: boolean; + strictThisChecks?: boolean; suppressExcessPropertyErrors?: boolean; suppressImplicitAnyIndexErrors?: boolean; target?: ScriptTarget; diff --git a/tests/baselines/reference/thisTypeInFunctions.js b/tests/baselines/reference/thisTypeInFunctions.js index 8d34f9bc2cfca..e963dad60f76e 100644 --- a/tests/baselines/reference/thisTypeInFunctions.js +++ b/tests/baselines/reference/thisTypeInFunctions.js @@ -206,7 +206,8 @@ declare var f: { }; let n: number = f.call(12); -function missingTypeIsImplicitAny(this, a: number) { return a; } +function missingTypeIsImplicitAny(this, a: number) { return a; } + //// [thisTypeInFunctions.js] var __extends = (this && this.__extends) || function (d, b) { diff --git a/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts b/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts index 8676d12c5abed..3a1de178eea09 100644 --- a/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts +++ b/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts @@ -1,4 +1,4 @@ -// @strictThis: true +// @strictThisChecks: true // body checking class B { n: number; @@ -206,4 +206,4 @@ declare var f: { }; let n: number = f.call(12); -function missingTypeIsImplicitAny(this, a: number) { return a; } \ No newline at end of file +function missingTypeIsImplicitAny(this, a: number) { return a; } diff --git a/tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts b/tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts index 3afc5a5c69b4a..bec0b9ab43454 100644 --- a/tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts +++ b/tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts @@ -1,4 +1,4 @@ -// @strictThis: true +// @strictThisChecks: true class C { n: number; explicitThis(this: this, m: number): number { diff --git a/tests/cases/conformance/types/thisType/unionThisTypeInFunctions.ts b/tests/cases/conformance/types/thisType/unionThisTypeInFunctions.ts index a140c3fba958d..c0a55f138ce0f 100644 --- a/tests/cases/conformance/types/thisType/unionThisTypeInFunctions.ts +++ b/tests/cases/conformance/types/thisType/unionThisTypeInFunctions.ts @@ -1,4 +1,4 @@ -// @strictThis: true +// @strictThisChecks: true interface Real { method(n: number): void; data: string; diff --git a/tests/cases/fourslash/memberListOnExplicitThis.ts b/tests/cases/fourslash/memberListOnExplicitThis.ts index cf57717183c1b..207ec8796fab6 100644 --- a/tests/cases/fourslash/memberListOnExplicitThis.ts +++ b/tests/cases/fourslash/memberListOnExplicitThis.ts @@ -1,4 +1,4 @@ -// @strictThis: true +// @strictThisChecks: true /// ////interface Restricted { diff --git a/tests/cases/fourslash/quickInfoOnThis.ts b/tests/cases/fourslash/quickInfoOnThis.ts index 57bbb6c5a3ef4..bfed13ea89c9f 100644 --- a/tests/cases/fourslash/quickInfoOnThis.ts +++ b/tests/cases/fourslash/quickInfoOnThis.ts @@ -1,4 +1,4 @@ -// @strictThis: true +// @strictThisChecks: true /// ////interface Restricted { //// n: number; @@ -93,4 +93,4 @@ verify.quickInfoIs('this: {\n n: number;\n}'); goTo.marker('16'); verify.quickInfoIs('this: ContextualInterface'); goTo.marker('17'); -verify.quickInfoIs('(parameter) this: void'); \ No newline at end of file +verify.quickInfoIs('(parameter) this: void'); From c9f5f3d67e3783a4a0f4099ecfbd2d213de18548 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 25 Mar 2016 15:41:37 -0700 Subject: [PATCH 29/41] Remove --strictThisChecks --- src/compiler/binder.ts | 3 - src/compiler/checker.ts | 16 - src/compiler/commandLineParser.ts | 4 - src/compiler/types.ts | 1 - .../reference/thisTypeInFunctions.js | 87 +- .../reference/thisTypeInFunctions.symbols | 986 ++++++++---------- .../reference/thisTypeInFunctions.types | 302 ++---- .../thisTypeInFunctionsNegative.errors.txt | 229 ++-- .../reference/thisTypeInFunctionsNegative.js | 78 +- .../reference/unionThisTypeInFunctions.js | 4 +- .../unionThisTypeInFunctions.symbols | 14 +- .../reference/unionThisTypeInFunctions.types | 8 +- .../types/thisType/thisTypeInFunctions.ts | 46 +- .../thisType/thisTypeInFunctionsNegative.ts | 41 +- .../thisType/unionThisTypeInFunctions.ts | 5 +- .../fourslash/memberListOnExplicitThis.ts | 5 +- tests/cases/fourslash/quickInfoOnThis.ts | 13 +- 17 files changed, 719 insertions(+), 1123 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 7ae21a6338e47..9363a8796ee6b 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -1307,9 +1307,6 @@ namespace ts { // as other properties in the object literal. So we use SymbolFlags.PropertyExcludes // so that it will conflict with any other object literal members with the same // name. - if (options.strictThisChecks) { - seenThisKeyword = true; - } return bindPropertyOrMethodOrAccessor(node, SymbolFlags.Method | ((node).questionToken ? SymbolFlags.Optional : SymbolFlags.None), isObjectLiteralMethod(node) ? SymbolFlags.PropertyExcludes : SymbolFlags.MethodExcludes); case SyntaxKind.FunctionDeclaration: diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5017f0dcd2c7d..51fad3e7f3310 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3520,7 +3520,6 @@ namespace ts { return isIndependentVariableLikeDeclaration(declaration); case SyntaxKind.MethodDeclaration: case SyntaxKind.MethodSignature: - return compilerOptions.strictThisChecks ? false : isIndependentFunctionLikeDeclaration(declaration); case SyntaxKind.Constructor: return isIndependentFunctionLikeDeclaration(declaration); } @@ -4234,21 +4233,6 @@ namespace ts { if (minArgumentCount < 0) { minArgumentCount = declaration.parameters.length - (hasThisParameter ? 1 : 0); } - if (!hasThisParameter && compilerOptions.strictThisChecks) { - 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 ? - getTypeOfSymbol(getSymbolOfNode(declaration.parent)) : - getThisType(declaration.name); - Debug.assert(!!thisType, "couldn't find implicit this type"); - } - } if (isJSConstructSignature) { minArgumentCount--; diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index f6e1d9b48d70c..cf55f030c3382 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -137,10 +137,6 @@ namespace ts { name: "skipDefaultLibCheck", type: "boolean", }, - { - name: "strictThisChecks", - type: "boolean", - }, { name: "out", type: "string", diff --git a/src/compiler/types.ts b/src/compiler/types.ts index dfa1b54e42812..5965a39a79ef7 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2407,7 +2407,6 @@ namespace ts { rootDir?: string; sourceMap?: boolean; sourceRoot?: string; - strictThisChecks?: boolean; suppressExcessPropertyErrors?: boolean; suppressImplicitAnyIndexErrors?: boolean; target?: ScriptTarget; diff --git a/tests/baselines/reference/thisTypeInFunctions.js b/tests/baselines/reference/thisTypeInFunctions.js index e963dad60f76e..74eba32082b72 100644 --- a/tests/baselines/reference/thisTypeInFunctions.js +++ b/tests/baselines/reference/thisTypeInFunctions.js @@ -8,9 +8,6 @@ class C { explicitThis(this: this, m: number): number { return this.n + m; } - implicitThis(m: number): number { - return this.n + m; - } explicitC(this: C, m: number): number { return this.n + m; } @@ -29,8 +26,6 @@ interface I { explicitStructural(this: {a: number}): number; explicitInterface(this: I): number; explicitThis(this: this): number; - implicitMethod(): number; - implicitFunction: () => number; } function explicitStructural(this: { y: number }, x: number): number { return x + this.y; @@ -39,7 +34,7 @@ function justThis(this: { y: number }): number { return this.y; } function implicitThis(n: number): number { - return 12; + return this.m + n + 12; } let impl: I = { a: 12, @@ -54,10 +49,6 @@ let impl: I = { explicitThis() { return this.a; }, - implicitMethod() { - return this.a; - }, - implicitFunction: () => this.a, // ok, this: any because it refers to some outer object (window?) } impl.explicitVoid1 = function () { return 12; }; impl.explicitVoid2 = () => 12; @@ -66,9 +57,6 @@ impl.explicitInterface = function() { return this.a; }; impl.explicitStructural = () => 12; impl.explicitInterface = () => 12; impl.explicitThis = function () { return this.a; }; -impl.implicitMethod = function () { return this.a; }; -impl.implicitMethod = () => 12; -impl.implicitFunction = () => this.a; // ok, this: any because it refers to some outer object (window?) // parameter checking let ok: {y: number, f: (this: { y: number }, x: number) => number} = { y: 12, f: explicitStructural }; let implicitAnyOk: {notSpecified: number, f: (x: number) => number} = { notSpecified: 12, f: implicitThis }; @@ -82,29 +70,26 @@ let ripped = c.explicitC; c.explicitC(12); c.explicitProperty(12); c.explicitThis(12); -c.implicitThis(12); d.explicitC(12); d.explicitProperty(12); d.explicitThis(12); -d.implicitThis(12); let reconstructed: { n: number, explicitThis(this: C, m: number): number, // note: this: this is not allowed in an object literal type. - implicitThis(m: number): number, explicitC(this: C, m: number): number, explicitProperty: (this: {n : number}, m: number) => number, explicitVoid(this: void, m: number): number, } = { n: 12, explicitThis: c.explicitThis, - implicitThis: c.implicitThis, explicitC: c.explicitC, explicitProperty: c.explicitProperty, explicitVoid: c.explicitVoid }; +reconstructed.explicitThis(10); reconstructed.explicitProperty(11); -reconstructed.implicitThis(11); - +let explicitVoid = reconstructed.explicitVoid; +explicitVoid(12); // assignment checking let unboundToSpecified: (this: { y: number }, x: number) => number = x => x + this.y; // ok, this:any let specifiedToSpecified: (this: {y: number}, x: number) => number = explicitStructural; @@ -143,8 +128,6 @@ c.explicitThis = function(this: C, 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 }; @@ -154,19 +137,17 @@ c.explicitVoid = n => n; // class-based assignability class Base1 { x: number; - public implicit(): number { return this.x; } + public polymorphic(this: this): number { return this.x; } explicit(this: Base1): number { return this.x; } - static implicitStatic(): number { return this.y; } static explicitStatic(this: typeof Base1): number { return this.y; } static y: number; - } class Derived1 extends Base1 { y: number } class Base2 { y: number - implicit(): number { return this.y; } + polymorphic(this: this): number { return this.y; } explicit(this: Base1): number { return this.x; } } class Derived2 extends Base2 { @@ -176,14 +157,14 @@ let b1 = new Base1(); let b2 = new Base2(); let d1 = new Derived1(); let d2 = new Derived2(); -d2.implicit = d1.implicit // ok, 'x' and 'y' in { x, y } (d assignable to f and vice versa) -d1.implicit = d2.implicit // ok, 'x' and 'y' in { x, y } (f assignable to d and vice versa) +d2.polymorphic = d1.polymorphic // ok, 'x' and 'y' in { x, y } +d1.polymorphic = d2.polymorphic // ok, 'x' and 'y' in { x, y } // bivariance-allowed cases -d1.implicit = b2.implicit // ok, 'y' in D: { x, y } (d assignable e) -d2.implicit = d1.explicit // ok, 'y' in { x, y } (c assignable to f) -b1.implicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) -b1.explicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) +d1.polymorphic = b2.polymorphic // ok, 'y' in D: { x, y } +d2.polymorphic = d1.explicit // ok, 'y' in { x, y } +b1.polymorphic = d2.polymorphic // ok, 'x' and 'y' not in Base1: { x } +b1.explicit = d2.polymorphic // ok, 'x' and 'y' not in Base1: { x } ////// use this-type for construction with new //// function InterfaceThis(this: I) { @@ -206,7 +187,7 @@ declare var f: { }; let n: number = f.call(12); -function missingTypeIsImplicitAny(this, a: number) { return a; } +function missingTypeIsImplicitAny(this, a: number) { return this.anything + a; } //// [thisTypeInFunctions.js] @@ -228,9 +209,6 @@ var C = (function () { C.prototype.explicitThis = function (m) { return this.n + m; }; - C.prototype.implicitThis = function (m) { - return this.n + m; - }; C.prototype.explicitC = function (m) { return this.n + m; }; @@ -256,7 +234,7 @@ function justThis() { return this.y; } function implicitThis(n) { - return 12; + return this.m + n + 12; } var impl = { a: 12, @@ -270,11 +248,7 @@ var impl = { }, explicitThis: function () { return this.a; - }, - implicitMethod: function () { - return this.a; - }, - implicitFunction: function () { return _this.a; } + } }; impl.explicitVoid1 = function () { return 12; }; impl.explicitVoid2 = function () { return 12; }; @@ -283,9 +257,6 @@ impl.explicitInterface = function () { return this.a; }; impl.explicitStructural = function () { return 12; }; impl.explicitInterface = function () { return 12; }; impl.explicitThis = function () { return this.a; }; -impl.implicitMethod = function () { return this.a; }; -impl.implicitMethod = function () { return 12; }; -impl.implicitFunction = function () { return _this.a; }; // ok, this: any because it refers to some outer object (window?) // parameter checking var ok = { y: 12, f: explicitStructural }; var implicitAnyOk = { notSpecified: 12, f: implicitThis }; @@ -298,21 +269,20 @@ var ripped = c.explicitC; c.explicitC(12); c.explicitProperty(12); c.explicitThis(12); -c.implicitThis(12); d.explicitC(12); d.explicitProperty(12); d.explicitThis(12); -d.implicitThis(12); var reconstructed = { n: 12, explicitThis: c.explicitThis, - implicitThis: c.implicitThis, explicitC: c.explicitC, explicitProperty: c.explicitProperty, explicitVoid: c.explicitVoid }; +reconstructed.explicitThis(10); reconstructed.explicitProperty(11); -reconstructed.implicitThis(11); +var explicitVoid = reconstructed.explicitVoid; +explicitVoid(12); // assignment checking var unboundToSpecified = function (x) { return x + _this.y; }; // ok, this:any var specifiedToSpecified = explicitStructural; @@ -344,8 +314,6 @@ c.explicitThis = function (m) { 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 (m) { return this.n + m; }; // this:void compatibility c.explicitVoid = function (n) { return n; }; @@ -353,9 +321,8 @@ c.explicitVoid = function (n) { return n; }; var Base1 = (function () { function Base1() { } - Base1.prototype.implicit = function () { return this.x; }; + Base1.prototype.polymorphic = function () { return this.x; }; Base1.prototype.explicit = function () { return this.x; }; - Base1.implicitStatic = function () { return this.y; }; Base1.explicitStatic = function () { return this.y; }; return Base1; }()); @@ -369,7 +336,7 @@ var Derived1 = (function (_super) { var Base2 = (function () { function Base2() { } - Base2.prototype.implicit = function () { return this.y; }; + Base2.prototype.polymorphic = function () { return this.y; }; Base2.prototype.explicit = function () { return this.x; }; return Base2; }()); @@ -384,13 +351,13 @@ var b1 = new Base1(); var b2 = new Base2(); var d1 = new Derived1(); var d2 = new Derived2(); -d2.implicit = d1.implicit; // ok, 'x' and 'y' in { x, y } (d assignable to f and vice versa) -d1.implicit = d2.implicit; // ok, 'x' and 'y' in { x, y } (f assignable to d and vice versa) +d2.polymorphic = d1.polymorphic; // ok, 'x' and 'y' in { x, y } +d1.polymorphic = d2.polymorphic; // ok, 'x' and 'y' in { x, y } // bivariance-allowed cases -d1.implicit = b2.implicit; // ok, 'y' in D: { x, y } (d assignable e) -d2.implicit = d1.explicit; // ok, 'y' in { x, y } (c assignable to f) -b1.implicit = d2.implicit; // ok, 'x' and 'y' not in C: { x } (c assignable to f) -b1.explicit = d2.implicit; // ok, 'x' and 'y' not in C: { x } (c assignable to f) +d1.polymorphic = b2.polymorphic; // ok, 'y' in D: { x, y } +d2.polymorphic = d1.explicit; // ok, 'y' in { x, y } +b1.polymorphic = d2.polymorphic; // ok, 'x' and 'y' not in Base1: { x } +b1.explicit = d2.polymorphic; // ok, 'x' and 'y' not in Base1: { x } ////// use this-type for construction with new //// function InterfaceThis() { this.a = 12; @@ -405,4 +372,4 @@ var interfaceThis = new InterfaceThis(); var literalTypeThis = new LiteralTypeThis(); var anyThis = new AnyThis(); var n = f.call(12); -function missingTypeIsImplicitAny(a) { return a; } +function missingTypeIsImplicitAny(a) { return this.anything + a; } diff --git a/tests/baselines/reference/thisTypeInFunctions.symbols b/tests/baselines/reference/thisTypeInFunctions.symbols index 9cd1915fc941b..1d51f4aaca07a 100644 --- a/tests/baselines/reference/thisTypeInFunctions.symbols +++ b/tests/baselines/reference/thisTypeInFunctions.symbols @@ -22,841 +22,763 @@ class C { >this : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) >n : Symbol(n, Decl(thisTypeInFunctions.ts, 4, 9)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 6, 28)) - } - implicitThis(m: number): number { ->implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 8, 5)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 9, 17)) - - return this.n + m; ->this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 4, 9)) ->this : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) ->n : Symbol(n, Decl(thisTypeInFunctions.ts, 4, 9)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 9, 17)) } explicitC(this: C, m: number): number { ->explicitC : Symbol(explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 12, 14)) +>explicitC : Symbol(explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 9, 14)) >C : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 12, 22)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 9, 22)) return this.n + m; >this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 4, 9)) >this : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) >n : Symbol(n, Decl(thisTypeInFunctions.ts, 4, 9)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 12, 22)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 9, 22)) } explicitProperty(this: {n: number}, m: number): number { ->explicitProperty : Symbol(explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 15, 21)) ->n : Symbol(n, Decl(thisTypeInFunctions.ts, 15, 28)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 15, 39)) +>explicitProperty : Symbol(explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 12, 21)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 12, 28)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 12, 39)) return this.n + m; ->this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 15, 28)) ->this : Symbol(, Decl(thisTypeInFunctions.ts, 15, 26)) ->n : Symbol(n, Decl(thisTypeInFunctions.ts, 15, 28)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 15, 39)) +>this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 12, 28)) +>this : Symbol(, Decl(thisTypeInFunctions.ts, 12, 26)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 12, 28)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 12, 39)) } explicitVoid(this: void, m: number): number { ->explicitVoid : Symbol(explicitVoid, Decl(thisTypeInFunctions.ts, 17, 5)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 18, 17)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 18, 28)) +>explicitVoid : Symbol(explicitVoid, Decl(thisTypeInFunctions.ts, 14, 5)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 15, 17)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 15, 28)) return m + 1; ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 18, 28)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 15, 28)) } } class D extends C { } ->D : Symbol(D, Decl(thisTypeInFunctions.ts, 21, 1)) +>D : Symbol(D, Decl(thisTypeInFunctions.ts, 18, 1)) >C : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) interface I { ->I : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 21)) +>I : Symbol(I, Decl(thisTypeInFunctions.ts, 19, 21)) a: number; ->a : Symbol(a, Decl(thisTypeInFunctions.ts, 23, 13)) +>a : Symbol(a, Decl(thisTypeInFunctions.ts, 20, 13)) explicitVoid1(this: void): number; ->explicitVoid1 : Symbol(explicitVoid1, Decl(thisTypeInFunctions.ts, 24, 14)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 25, 18)) +>explicitVoid1 : Symbol(explicitVoid1, Decl(thisTypeInFunctions.ts, 21, 14)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 22, 18)) explicitVoid2(this: void): number; ->explicitVoid2 : Symbol(explicitVoid2, Decl(thisTypeInFunctions.ts, 25, 38)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 26, 18)) +>explicitVoid2 : Symbol(explicitVoid2, Decl(thisTypeInFunctions.ts, 22, 38)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 23, 18)) explicitStructural(this: {a: number}): number; ->explicitStructural : Symbol(explicitStructural, Decl(thisTypeInFunctions.ts, 26, 38)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 27, 23)) ->a : Symbol(a, Decl(thisTypeInFunctions.ts, 27, 30)) +>explicitStructural : Symbol(explicitStructural, Decl(thisTypeInFunctions.ts, 23, 38)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 24, 23)) +>a : Symbol(a, Decl(thisTypeInFunctions.ts, 24, 30)) explicitInterface(this: I): number; ->explicitInterface : Symbol(explicitInterface, Decl(thisTypeInFunctions.ts, 27, 50)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 28, 22)) ->I : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 21)) +>explicitInterface : Symbol(explicitInterface, Decl(thisTypeInFunctions.ts, 24, 50)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 25, 22)) +>I : Symbol(I, Decl(thisTypeInFunctions.ts, 19, 21)) explicitThis(this: this): number; ->explicitThis : Symbol(explicitThis, Decl(thisTypeInFunctions.ts, 28, 39)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 29, 17)) - - implicitMethod(): number; ->implicitMethod : Symbol(implicitMethod, Decl(thisTypeInFunctions.ts, 29, 37)) - - implicitFunction: () => number; ->implicitFunction : Symbol(implicitFunction, Decl(thisTypeInFunctions.ts, 30, 29)) +>explicitThis : Symbol(explicitThis, Decl(thisTypeInFunctions.ts, 25, 39)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 26, 17)) } function explicitStructural(this: { y: number }, x: number): number { ->explicitStructural : Symbol(explicitStructural, Decl(thisTypeInFunctions.ts, 32, 1)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 33, 28)) ->y : Symbol(y, Decl(thisTypeInFunctions.ts, 33, 35)) ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 33, 48)) +>explicitStructural : Symbol(explicitStructural, Decl(thisTypeInFunctions.ts, 27, 1)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 28, 28)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 28, 35)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 28, 48)) return x + this.y; ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 33, 48)) ->this.y : Symbol(y, Decl(thisTypeInFunctions.ts, 33, 35)) ->this : Symbol(, Decl(thisTypeInFunctions.ts, 33, 33)) ->y : Symbol(y, Decl(thisTypeInFunctions.ts, 33, 35)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 28, 48)) +>this.y : Symbol(y, Decl(thisTypeInFunctions.ts, 28, 35)) +>this : Symbol(, Decl(thisTypeInFunctions.ts, 28, 33)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 28, 35)) } function justThis(this: { y: number }): number { ->justThis : Symbol(justThis, Decl(thisTypeInFunctions.ts, 35, 1)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 36, 18)) ->y : Symbol(y, Decl(thisTypeInFunctions.ts, 36, 25)) +>justThis : Symbol(justThis, Decl(thisTypeInFunctions.ts, 30, 1)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 31, 18)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 31, 25)) return this.y; ->this.y : Symbol(y, Decl(thisTypeInFunctions.ts, 36, 25)) ->this : Symbol(, Decl(thisTypeInFunctions.ts, 36, 23)) ->y : Symbol(y, Decl(thisTypeInFunctions.ts, 36, 25)) +>this.y : Symbol(y, Decl(thisTypeInFunctions.ts, 31, 25)) +>this : Symbol(, Decl(thisTypeInFunctions.ts, 31, 23)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 31, 25)) } function implicitThis(n: number): number { ->implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 38, 1)) ->n : Symbol(n, Decl(thisTypeInFunctions.ts, 39, 22)) +>implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 33, 1)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 34, 22)) - return 12; + return this.m + n + 12; +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 34, 22)) } let impl: I = { ->impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) ->I : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 21)) +>impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 37, 3)) +>I : Symbol(I, Decl(thisTypeInFunctions.ts, 19, 21)) a: 12, ->a : Symbol(a, Decl(thisTypeInFunctions.ts, 42, 15)) +>a : Symbol(a, Decl(thisTypeInFunctions.ts, 37, 15)) explicitVoid2: () => this.a, // ok, this: any because it refers to some outer object (window?) ->explicitVoid2 : Symbol(explicitVoid2, Decl(thisTypeInFunctions.ts, 43, 10)) +>explicitVoid2 : Symbol(explicitVoid2, Decl(thisTypeInFunctions.ts, 38, 10)) explicitVoid1() { return 12; }, ->explicitVoid1 : Symbol(explicitVoid1, Decl(thisTypeInFunctions.ts, 44, 32)) +>explicitVoid1 : Symbol(explicitVoid1, Decl(thisTypeInFunctions.ts, 39, 32)) explicitStructural() { ->explicitStructural : Symbol(explicitStructural, Decl(thisTypeInFunctions.ts, 45, 35)) +>explicitStructural : Symbol(explicitStructural, Decl(thisTypeInFunctions.ts, 40, 35)) return this.a; ->this.a : Symbol(a, Decl(thisTypeInFunctions.ts, 27, 30)) ->this : Symbol(, Decl(thisTypeInFunctions.ts, 27, 28)) ->a : Symbol(a, Decl(thisTypeInFunctions.ts, 27, 30)) +>this.a : Symbol(a, Decl(thisTypeInFunctions.ts, 24, 30)) +>this : Symbol(, Decl(thisTypeInFunctions.ts, 24, 28)) +>a : Symbol(a, Decl(thisTypeInFunctions.ts, 24, 30)) }, explicitInterface() { ->explicitInterface : Symbol(explicitInterface, Decl(thisTypeInFunctions.ts, 48, 6)) +>explicitInterface : Symbol(explicitInterface, Decl(thisTypeInFunctions.ts, 43, 6)) return this.a; ->this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) ->this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 21)) ->a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) +>this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 20, 13)) +>this : Symbol(I, Decl(thisTypeInFunctions.ts, 19, 21)) +>a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 20, 13)) }, explicitThis() { ->explicitThis : Symbol(explicitThis, Decl(thisTypeInFunctions.ts, 51, 6)) - - return this.a; ->this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) ->this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 21)) ->a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) - - }, - implicitMethod() { ->implicitMethod : Symbol(implicitMethod, Decl(thisTypeInFunctions.ts, 54, 6)) +>explicitThis : Symbol(explicitThis, Decl(thisTypeInFunctions.ts, 46, 6)) return this.a; ->this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) ->this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 21)) ->a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) +>this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 20, 13)) +>this : Symbol(I, Decl(thisTypeInFunctions.ts, 19, 21)) +>a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 20, 13)) }, - implicitFunction: () => this.a, // ok, this: any because it refers to some outer object (window?) ->implicitFunction : Symbol(implicitFunction, Decl(thisTypeInFunctions.ts, 57, 6)) } impl.explicitVoid1 = function () { return 12; }; ->impl.explicitVoid1 : Symbol(I.explicitVoid1, Decl(thisTypeInFunctions.ts, 24, 14)) ->impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) ->explicitVoid1 : Symbol(I.explicitVoid1, Decl(thisTypeInFunctions.ts, 24, 14)) +>impl.explicitVoid1 : Symbol(I.explicitVoid1, Decl(thisTypeInFunctions.ts, 21, 14)) +>impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 37, 3)) +>explicitVoid1 : Symbol(I.explicitVoid1, Decl(thisTypeInFunctions.ts, 21, 14)) impl.explicitVoid2 = () => 12; ->impl.explicitVoid2 : Symbol(I.explicitVoid2, Decl(thisTypeInFunctions.ts, 25, 38)) ->impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) ->explicitVoid2 : Symbol(I.explicitVoid2, Decl(thisTypeInFunctions.ts, 25, 38)) +>impl.explicitVoid2 : Symbol(I.explicitVoid2, Decl(thisTypeInFunctions.ts, 22, 38)) +>impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 37, 3)) +>explicitVoid2 : Symbol(I.explicitVoid2, Decl(thisTypeInFunctions.ts, 22, 38)) impl.explicitStructural = function() { return this.a; }; ->impl.explicitStructural : Symbol(I.explicitStructural, Decl(thisTypeInFunctions.ts, 26, 38)) ->impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) ->explicitStructural : Symbol(I.explicitStructural, Decl(thisTypeInFunctions.ts, 26, 38)) ->this.a : Symbol(a, Decl(thisTypeInFunctions.ts, 27, 30)) ->this : Symbol(, Decl(thisTypeInFunctions.ts, 27, 28)) ->a : Symbol(a, Decl(thisTypeInFunctions.ts, 27, 30)) +>impl.explicitStructural : Symbol(I.explicitStructural, Decl(thisTypeInFunctions.ts, 23, 38)) +>impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 37, 3)) +>explicitStructural : Symbol(I.explicitStructural, Decl(thisTypeInFunctions.ts, 23, 38)) +>this.a : Symbol(a, Decl(thisTypeInFunctions.ts, 24, 30)) +>this : Symbol(, Decl(thisTypeInFunctions.ts, 24, 28)) +>a : Symbol(a, Decl(thisTypeInFunctions.ts, 24, 30)) impl.explicitInterface = function() { return this.a; }; ->impl.explicitInterface : Symbol(I.explicitInterface, Decl(thisTypeInFunctions.ts, 27, 50)) ->impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) ->explicitInterface : Symbol(I.explicitInterface, Decl(thisTypeInFunctions.ts, 27, 50)) ->this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) ->this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 21)) ->a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) +>impl.explicitInterface : Symbol(I.explicitInterface, Decl(thisTypeInFunctions.ts, 24, 50)) +>impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 37, 3)) +>explicitInterface : Symbol(I.explicitInterface, Decl(thisTypeInFunctions.ts, 24, 50)) +>this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 20, 13)) +>this : Symbol(I, Decl(thisTypeInFunctions.ts, 19, 21)) +>a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 20, 13)) impl.explicitStructural = () => 12; ->impl.explicitStructural : Symbol(I.explicitStructural, Decl(thisTypeInFunctions.ts, 26, 38)) ->impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) ->explicitStructural : Symbol(I.explicitStructural, Decl(thisTypeInFunctions.ts, 26, 38)) +>impl.explicitStructural : Symbol(I.explicitStructural, Decl(thisTypeInFunctions.ts, 23, 38)) +>impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 37, 3)) +>explicitStructural : Symbol(I.explicitStructural, Decl(thisTypeInFunctions.ts, 23, 38)) impl.explicitInterface = () => 12; ->impl.explicitInterface : Symbol(I.explicitInterface, Decl(thisTypeInFunctions.ts, 27, 50)) ->impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) ->explicitInterface : Symbol(I.explicitInterface, Decl(thisTypeInFunctions.ts, 27, 50)) +>impl.explicitInterface : Symbol(I.explicitInterface, Decl(thisTypeInFunctions.ts, 24, 50)) +>impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 37, 3)) +>explicitInterface : Symbol(I.explicitInterface, Decl(thisTypeInFunctions.ts, 24, 50)) impl.explicitThis = function () { return this.a; }; ->impl.explicitThis : Symbol(I.explicitThis, Decl(thisTypeInFunctions.ts, 28, 39)) ->impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) ->explicitThis : Symbol(I.explicitThis, Decl(thisTypeInFunctions.ts, 28, 39)) ->this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) ->this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 21)) ->a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) - -impl.implicitMethod = function () { return this.a; }; ->impl.implicitMethod : Symbol(I.implicitMethod, Decl(thisTypeInFunctions.ts, 29, 37)) ->impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) ->implicitMethod : Symbol(I.implicitMethod, Decl(thisTypeInFunctions.ts, 29, 37)) ->this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) ->this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 21)) ->a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) - -impl.implicitMethod = () => 12; ->impl.implicitMethod : Symbol(I.implicitMethod, Decl(thisTypeInFunctions.ts, 29, 37)) ->impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) ->implicitMethod : Symbol(I.implicitMethod, Decl(thisTypeInFunctions.ts, 29, 37)) - -impl.implicitFunction = () => this.a; // ok, this: any because it refers to some outer object (window?) ->impl.implicitFunction : Symbol(I.implicitFunction, Decl(thisTypeInFunctions.ts, 30, 29)) ->impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) ->implicitFunction : Symbol(I.implicitFunction, Decl(thisTypeInFunctions.ts, 30, 29)) +>impl.explicitThis : Symbol(I.explicitThis, Decl(thisTypeInFunctions.ts, 25, 39)) +>impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 37, 3)) +>explicitThis : Symbol(I.explicitThis, Decl(thisTypeInFunctions.ts, 25, 39)) +>this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 20, 13)) +>this : Symbol(I, Decl(thisTypeInFunctions.ts, 19, 21)) +>a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 20, 13)) // parameter checking let ok: {y: number, f: (this: { y: number }, x: number) => number} = { y: 12, f: explicitStructural }; ->ok : Symbol(ok, Decl(thisTypeInFunctions.ts, 71, 3)) ->y : Symbol(y, Decl(thisTypeInFunctions.ts, 71, 9)) ->f : Symbol(f, Decl(thisTypeInFunctions.ts, 71, 19)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 71, 24)) ->y : Symbol(y, Decl(thisTypeInFunctions.ts, 71, 31)) ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 71, 44)) ->y : Symbol(y, Decl(thisTypeInFunctions.ts, 71, 70)) ->f : Symbol(f, Decl(thisTypeInFunctions.ts, 71, 77)) ->explicitStructural : Symbol(explicitStructural, Decl(thisTypeInFunctions.ts, 32, 1)) +>ok : Symbol(ok, Decl(thisTypeInFunctions.ts, 59, 3)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 59, 9)) +>f : Symbol(f, Decl(thisTypeInFunctions.ts, 59, 19)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 59, 24)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 59, 31)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 59, 44)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 59, 70)) +>f : Symbol(f, Decl(thisTypeInFunctions.ts, 59, 77)) +>explicitStructural : Symbol(explicitStructural, Decl(thisTypeInFunctions.ts, 27, 1)) let implicitAnyOk: {notSpecified: number, f: (x: number) => number} = { notSpecified: 12, f: implicitThis }; ->implicitAnyOk : Symbol(implicitAnyOk, Decl(thisTypeInFunctions.ts, 72, 3)) ->notSpecified : Symbol(notSpecified, Decl(thisTypeInFunctions.ts, 72, 20)) ->f : Symbol(f, Decl(thisTypeInFunctions.ts, 72, 41)) ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 72, 46)) ->notSpecified : Symbol(notSpecified, Decl(thisTypeInFunctions.ts, 72, 71)) ->f : Symbol(f, Decl(thisTypeInFunctions.ts, 72, 89)) ->implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 38, 1)) +>implicitAnyOk : Symbol(implicitAnyOk, Decl(thisTypeInFunctions.ts, 60, 3)) +>notSpecified : Symbol(notSpecified, Decl(thisTypeInFunctions.ts, 60, 20)) +>f : Symbol(f, Decl(thisTypeInFunctions.ts, 60, 41)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 60, 46)) +>notSpecified : Symbol(notSpecified, Decl(thisTypeInFunctions.ts, 60, 71)) +>f : Symbol(f, Decl(thisTypeInFunctions.ts, 60, 89)) +>implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 33, 1)) ok.f(13); ->ok.f : Symbol(f, Decl(thisTypeInFunctions.ts, 71, 19)) ->ok : Symbol(ok, Decl(thisTypeInFunctions.ts, 71, 3)) ->f : Symbol(f, Decl(thisTypeInFunctions.ts, 71, 19)) +>ok.f : Symbol(f, Decl(thisTypeInFunctions.ts, 59, 19)) +>ok : Symbol(ok, Decl(thisTypeInFunctions.ts, 59, 3)) +>f : Symbol(f, Decl(thisTypeInFunctions.ts, 59, 19)) implicitThis(12); ->implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 38, 1)) +>implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 33, 1)) implicitAnyOk.f(12); ->implicitAnyOk.f : Symbol(f, Decl(thisTypeInFunctions.ts, 72, 41)) ->implicitAnyOk : Symbol(implicitAnyOk, Decl(thisTypeInFunctions.ts, 72, 3)) ->f : Symbol(f, Decl(thisTypeInFunctions.ts, 72, 41)) +>implicitAnyOk.f : Symbol(f, Decl(thisTypeInFunctions.ts, 60, 41)) +>implicitAnyOk : Symbol(implicitAnyOk, Decl(thisTypeInFunctions.ts, 60, 3)) +>f : Symbol(f, Decl(thisTypeInFunctions.ts, 60, 41)) let c = new C(); ->c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 65, 3)) >C : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) let d = new D(); ->d : Symbol(d, Decl(thisTypeInFunctions.ts, 78, 3)) ->D : Symbol(D, Decl(thisTypeInFunctions.ts, 21, 1)) +>d : Symbol(d, Decl(thisTypeInFunctions.ts, 66, 3)) +>D : Symbol(D, Decl(thisTypeInFunctions.ts, 18, 1)) let ripped = c.explicitC; ->ripped : Symbol(ripped, Decl(thisTypeInFunctions.ts, 79, 3)) ->c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) ->c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) +>ripped : Symbol(ripped, Decl(thisTypeInFunctions.ts, 67, 3)) +>c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 65, 3)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) c.explicitC(12); ->c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) ->c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) +>c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 65, 3)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) c.explicitProperty(12); ->c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) ->c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) +>c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 65, 3)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) c.explicitThis(12); >c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) ->c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 65, 3)) >explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) -c.implicitThis(12); ->c.implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 8, 5)) ->c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 8, 5)) - d.explicitC(12); ->d.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) ->d : Symbol(d, Decl(thisTypeInFunctions.ts, 78, 3)) ->explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) +>d.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>d : Symbol(d, Decl(thisTypeInFunctions.ts, 66, 3)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) d.explicitProperty(12); ->d.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) ->d : Symbol(d, Decl(thisTypeInFunctions.ts, 78, 3)) ->explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) +>d.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>d : Symbol(d, Decl(thisTypeInFunctions.ts, 66, 3)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) d.explicitThis(12); >d.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) ->d : Symbol(d, Decl(thisTypeInFunctions.ts, 78, 3)) +>d : Symbol(d, Decl(thisTypeInFunctions.ts, 66, 3)) >explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) -d.implicitThis(12); ->d.implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 8, 5)) ->d : Symbol(d, Decl(thisTypeInFunctions.ts, 78, 3)) ->implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 8, 5)) - let reconstructed: { ->reconstructed : Symbol(reconstructed, Decl(thisTypeInFunctions.ts, 88, 3)) +>reconstructed : Symbol(reconstructed, Decl(thisTypeInFunctions.ts, 74, 3)) n: number, ->n : Symbol(n, Decl(thisTypeInFunctions.ts, 88, 20)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 74, 20)) explicitThis(this: C, m: number): number, // note: this: this is not allowed in an object literal type. ->explicitThis : Symbol(explicitThis, Decl(thisTypeInFunctions.ts, 89, 14)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 90, 17)) +>explicitThis : Symbol(explicitThis, Decl(thisTypeInFunctions.ts, 75, 14)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 76, 17)) >C : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 90, 25)) - - implicitThis(m: number): number, ->implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 90, 45)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 91, 17)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 76, 25)) explicitC(this: C, m: number): number, ->explicitC : Symbol(explicitC, Decl(thisTypeInFunctions.ts, 91, 36)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 92, 14)) +>explicitC : Symbol(explicitC, Decl(thisTypeInFunctions.ts, 76, 45)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 77, 14)) >C : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 92, 22)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 77, 22)) explicitProperty: (this: {n : number}, m: number) => number, ->explicitProperty : Symbol(explicitProperty, Decl(thisTypeInFunctions.ts, 92, 42)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 93, 23)) ->n : Symbol(n, Decl(thisTypeInFunctions.ts, 93, 30)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 93, 42)) +>explicitProperty : Symbol(explicitProperty, Decl(thisTypeInFunctions.ts, 77, 42)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 78, 23)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 78, 30)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 78, 42)) explicitVoid(this: void, m: number): number, ->explicitVoid : Symbol(explicitVoid, Decl(thisTypeInFunctions.ts, 93, 64)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 94, 17)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 94, 28)) +>explicitVoid : Symbol(explicitVoid, Decl(thisTypeInFunctions.ts, 78, 64)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 79, 17)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 79, 28)) } = { n: 12, ->n : Symbol(n, Decl(thisTypeInFunctions.ts, 95, 5)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 80, 5)) explicitThis: c.explicitThis, ->explicitThis : Symbol(explicitThis, Decl(thisTypeInFunctions.ts, 96, 10)) +>explicitThis : Symbol(explicitThis, Decl(thisTypeInFunctions.ts, 81, 10)) >c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) ->c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 65, 3)) >explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) - implicitThis: c.implicitThis, ->implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 97, 33)) ->c.implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 8, 5)) ->c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 8, 5)) - explicitC: c.explicitC, ->explicitC : Symbol(explicitC, Decl(thisTypeInFunctions.ts, 98, 33)) ->c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) ->c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) +>explicitC : Symbol(explicitC, Decl(thisTypeInFunctions.ts, 82, 33)) +>c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 65, 3)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) explicitProperty: c.explicitProperty, ->explicitProperty : Symbol(explicitProperty, Decl(thisTypeInFunctions.ts, 99, 27)) ->c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) ->c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) +>explicitProperty : Symbol(explicitProperty, Decl(thisTypeInFunctions.ts, 83, 27)) +>c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 65, 3)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) explicitVoid: c.explicitVoid ->explicitVoid : Symbol(explicitVoid, Decl(thisTypeInFunctions.ts, 100, 41)) ->c.explicitVoid : Symbol(C.explicitVoid, Decl(thisTypeInFunctions.ts, 17, 5)) ->c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitVoid : Symbol(C.explicitVoid, Decl(thisTypeInFunctions.ts, 17, 5)) +>explicitVoid : Symbol(explicitVoid, Decl(thisTypeInFunctions.ts, 84, 41)) +>c.explicitVoid : Symbol(C.explicitVoid, Decl(thisTypeInFunctions.ts, 14, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 65, 3)) +>explicitVoid : Symbol(C.explicitVoid, Decl(thisTypeInFunctions.ts, 14, 5)) }; +reconstructed.explicitThis(10); +>reconstructed.explicitThis : Symbol(explicitThis, Decl(thisTypeInFunctions.ts, 75, 14)) +>reconstructed : Symbol(reconstructed, Decl(thisTypeInFunctions.ts, 74, 3)) +>explicitThis : Symbol(explicitThis, Decl(thisTypeInFunctions.ts, 75, 14)) + reconstructed.explicitProperty(11); ->reconstructed.explicitProperty : Symbol(explicitProperty, Decl(thisTypeInFunctions.ts, 92, 42)) ->reconstructed : Symbol(reconstructed, Decl(thisTypeInFunctions.ts, 88, 3)) ->explicitProperty : Symbol(explicitProperty, Decl(thisTypeInFunctions.ts, 92, 42)) +>reconstructed.explicitProperty : Symbol(explicitProperty, Decl(thisTypeInFunctions.ts, 77, 42)) +>reconstructed : Symbol(reconstructed, Decl(thisTypeInFunctions.ts, 74, 3)) +>explicitProperty : Symbol(explicitProperty, Decl(thisTypeInFunctions.ts, 77, 42)) + +let explicitVoid = reconstructed.explicitVoid; +>explicitVoid : Symbol(explicitVoid, Decl(thisTypeInFunctions.ts, 89, 3)) +>reconstructed.explicitVoid : Symbol(explicitVoid, Decl(thisTypeInFunctions.ts, 78, 64)) +>reconstructed : Symbol(reconstructed, Decl(thisTypeInFunctions.ts, 74, 3)) +>explicitVoid : Symbol(explicitVoid, Decl(thisTypeInFunctions.ts, 78, 64)) -reconstructed.implicitThis(11); ->reconstructed.implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 90, 45)) ->reconstructed : Symbol(reconstructed, Decl(thisTypeInFunctions.ts, 88, 3)) ->implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 90, 45)) +explicitVoid(12); +>explicitVoid : Symbol(explicitVoid, Decl(thisTypeInFunctions.ts, 89, 3)) // assignment checking let unboundToSpecified: (this: { y: number }, x: number) => number = x => x + this.y; // ok, this:any ->unboundToSpecified : Symbol(unboundToSpecified, Decl(thisTypeInFunctions.ts, 107, 3)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 107, 25)) ->y : Symbol(y, Decl(thisTypeInFunctions.ts, 107, 32)) ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 107, 45)) ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 107, 68)) ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 107, 68)) +>unboundToSpecified : Symbol(unboundToSpecified, Decl(thisTypeInFunctions.ts, 92, 3)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 92, 25)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 92, 32)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 92, 45)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 92, 68)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 92, 68)) let specifiedToSpecified: (this: {y: number}, x: number) => number = explicitStructural; ->specifiedToSpecified : Symbol(specifiedToSpecified, Decl(thisTypeInFunctions.ts, 108, 3)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 108, 27)) ->y : Symbol(y, Decl(thisTypeInFunctions.ts, 108, 34)) ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 108, 45)) ->explicitStructural : Symbol(explicitStructural, Decl(thisTypeInFunctions.ts, 32, 1)) +>specifiedToSpecified : Symbol(specifiedToSpecified, Decl(thisTypeInFunctions.ts, 93, 3)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 93, 27)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 93, 34)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 93, 45)) +>explicitStructural : Symbol(explicitStructural, Decl(thisTypeInFunctions.ts, 27, 1)) let anyToSpecified: (this: { y: number }, x: number) => number = function(x: number): number { return x + 12; }; ->anyToSpecified : Symbol(anyToSpecified, Decl(thisTypeInFunctions.ts, 109, 3)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 109, 21)) ->y : Symbol(y, Decl(thisTypeInFunctions.ts, 109, 28)) ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 109, 41)) ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 109, 74)) ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 109, 74)) +>anyToSpecified : Symbol(anyToSpecified, Decl(thisTypeInFunctions.ts, 94, 3)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 94, 21)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 94, 28)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 94, 41)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 94, 74)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 94, 74)) let unspecifiedLambda: (x: number) => number = x => x + 12; ->unspecifiedLambda : Symbol(unspecifiedLambda, Decl(thisTypeInFunctions.ts, 111, 3)) ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 111, 24)) ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 111, 46)) ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 111, 46)) +>unspecifiedLambda : Symbol(unspecifiedLambda, Decl(thisTypeInFunctions.ts, 96, 3)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 96, 24)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 96, 46)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 96, 46)) let specifiedLambda: (this: void, x: number) => number = x => x + 12; ->specifiedLambda : Symbol(specifiedLambda, Decl(thisTypeInFunctions.ts, 112, 3)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 112, 22)) ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 112, 33)) ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 112, 56)) ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 112, 56)) +>specifiedLambda : Symbol(specifiedLambda, Decl(thisTypeInFunctions.ts, 97, 3)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 97, 22)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 97, 33)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 97, 56)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 97, 56)) let unspecifiedLambdaToSpecified: (this: {y: number}, x: number) => number = unspecifiedLambda; ->unspecifiedLambdaToSpecified : Symbol(unspecifiedLambdaToSpecified, Decl(thisTypeInFunctions.ts, 113, 3)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 113, 35)) ->y : Symbol(y, Decl(thisTypeInFunctions.ts, 113, 42)) ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 113, 53)) ->unspecifiedLambda : Symbol(unspecifiedLambda, Decl(thisTypeInFunctions.ts, 111, 3)) +>unspecifiedLambdaToSpecified : Symbol(unspecifiedLambdaToSpecified, Decl(thisTypeInFunctions.ts, 98, 3)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 98, 35)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 98, 42)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 98, 53)) +>unspecifiedLambda : Symbol(unspecifiedLambda, Decl(thisTypeInFunctions.ts, 96, 3)) let specifiedLambdaToSpecified: (this: {y: number}, x: number) => number = specifiedLambda; ->specifiedLambdaToSpecified : Symbol(specifiedLambdaToSpecified, Decl(thisTypeInFunctions.ts, 114, 3)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 114, 33)) ->y : Symbol(y, Decl(thisTypeInFunctions.ts, 114, 40)) ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 114, 51)) ->specifiedLambda : Symbol(specifiedLambda, Decl(thisTypeInFunctions.ts, 112, 3)) +>specifiedLambdaToSpecified : Symbol(specifiedLambdaToSpecified, Decl(thisTypeInFunctions.ts, 99, 3)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 99, 33)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 99, 40)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 99, 51)) +>specifiedLambda : Symbol(specifiedLambda, Decl(thisTypeInFunctions.ts, 97, 3)) let explicitCFunction: (this: C, m: number) => number; ->explicitCFunction : Symbol(explicitCFunction, Decl(thisTypeInFunctions.ts, 117, 3)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 117, 24)) +>explicitCFunction : Symbol(explicitCFunction, Decl(thisTypeInFunctions.ts, 102, 3)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 102, 24)) >C : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 117, 32)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 102, 32)) let explicitPropertyFunction: (this: {n: number}, m: number) => number; ->explicitPropertyFunction : Symbol(explicitPropertyFunction, Decl(thisTypeInFunctions.ts, 118, 3)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 118, 31)) ->n : Symbol(n, Decl(thisTypeInFunctions.ts, 118, 38)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 118, 49)) +>explicitPropertyFunction : Symbol(explicitPropertyFunction, Decl(thisTypeInFunctions.ts, 103, 3)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 103, 31)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 103, 38)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 103, 49)) c.explicitC = explicitCFunction; ->c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) ->c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) ->explicitCFunction : Symbol(explicitCFunction, Decl(thisTypeInFunctions.ts, 117, 3)) +>c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 65, 3)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>explicitCFunction : Symbol(explicitCFunction, Decl(thisTypeInFunctions.ts, 102, 3)) c.explicitC = function(this: C, m: number) { return this.n + m }; ->c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) ->c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 120, 23)) +>c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 65, 3)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 105, 23)) >C : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 120, 31)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 105, 31)) >this.n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 4, 9)) >this : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) >n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 4, 9)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 120, 31)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 105, 31)) c.explicitProperty = explicitPropertyFunction; ->c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) ->c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) ->explicitPropertyFunction : Symbol(explicitPropertyFunction, Decl(thisTypeInFunctions.ts, 118, 3)) +>c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 65, 3)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>explicitPropertyFunction : Symbol(explicitPropertyFunction, Decl(thisTypeInFunctions.ts, 103, 3)) c.explicitProperty = function(this: {n: number}, m: number) { return this.n + m }; ->c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) ->c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 122, 30)) ->n : Symbol(n, Decl(thisTypeInFunctions.ts, 122, 37)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 122, 48)) ->this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 122, 37)) ->this : Symbol(, Decl(thisTypeInFunctions.ts, 122, 35)) ->n : Symbol(n, Decl(thisTypeInFunctions.ts, 122, 37)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 122, 48)) +>c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 65, 3)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 107, 30)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 107, 37)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 107, 48)) +>this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 107, 37)) +>this : Symbol(, Decl(thisTypeInFunctions.ts, 107, 35)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 107, 37)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 107, 48)) c.explicitProperty = reconstructed.explicitProperty; ->c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) ->c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) ->reconstructed.explicitProperty : Symbol(explicitProperty, Decl(thisTypeInFunctions.ts, 92, 42)) ->reconstructed : Symbol(reconstructed, Decl(thisTypeInFunctions.ts, 88, 3)) ->explicitProperty : Symbol(explicitProperty, Decl(thisTypeInFunctions.ts, 92, 42)) +>c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 65, 3)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>reconstructed.explicitProperty : Symbol(explicitProperty, Decl(thisTypeInFunctions.ts, 77, 42)) +>reconstructed : Symbol(reconstructed, Decl(thisTypeInFunctions.ts, 74, 3)) +>explicitProperty : Symbol(explicitProperty, Decl(thisTypeInFunctions.ts, 77, 42)) // lambdas are assignable to anything c.explicitC = m => m; ->c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) ->c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 126, 13)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 126, 13)) +>c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 65, 3)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 111, 13)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 111, 13)) c.explicitThis = m => m; >c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) ->c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 65, 3)) >explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 127, 16)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 127, 16)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 112, 16)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 112, 16)) c.explicitProperty = m => m; ->c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) ->c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 128, 20)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 128, 20)) +>c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 65, 3)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 113, 20)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 113, 20)) // this inside lambdas refer to outer scope // the outer-scoped lambda at top-level is still just `any` c.explicitC = m => m + this.n; ->c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) ->c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 132, 13)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 132, 13)) +>c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 65, 3)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 117, 13)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 117, 13)) c.explicitThis = m => m + this.n; >c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) ->c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 65, 3)) >explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 133, 16)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 133, 16)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 118, 16)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 118, 16)) c.explicitProperty = m => m + this.n; ->c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) ->c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 134, 20)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 134, 20)) +>c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 65, 3)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 119, 20)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 119, 20)) //NOTE: this=C here, I guess? c.explicitThis = explicitCFunction; >c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) ->c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 65, 3)) >explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) ->explicitCFunction : Symbol(explicitCFunction, Decl(thisTypeInFunctions.ts, 117, 3)) +>explicitCFunction : Symbol(explicitCFunction, Decl(thisTypeInFunctions.ts, 102, 3)) c.explicitThis = function(this: C, m: number) { return this.n + m }; >c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) ->c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 65, 3)) >explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 138, 26)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 123, 26)) >C : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 138, 34)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 123, 34)) >this.n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 4, 9)) >this : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) >n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 4, 9)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 138, 34)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 123, 34)) // this:any compatibility c.explicitC = function(m) { return this.n + m }; ->c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) ->c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 141, 23)) +>c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 65, 3)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 126, 23)) >this.n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 4, 9)) >this : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) >n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 4, 9)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 141, 23)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 126, 23)) c.explicitProperty = function(m) { return this.n + m }; ->c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) ->c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 142, 30)) ->this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 15, 28)) ->this : Symbol(, Decl(thisTypeInFunctions.ts, 15, 26)) ->n : Symbol(n, Decl(thisTypeInFunctions.ts, 15, 28)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 142, 30)) +>c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 65, 3)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 127, 30)) +>this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 12, 28)) +>this : Symbol(, Decl(thisTypeInFunctions.ts, 12, 26)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 12, 28)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 127, 30)) c.explicitThis = function(m) { return this.n + m }; >c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) ->c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 65, 3)) >explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 143, 26)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 128, 26)) >this.n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 4, 9)) >this : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) >n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 4, 9)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 143, 26)) - -c.implicitThis = function(m) { return this.n + m }; ->c.implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 8, 5)) ->c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 8, 5)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 144, 26)) ->this.n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 4, 9)) ->this : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) ->n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 4, 9)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 144, 26)) - -c.implicitThis = reconstructed.implicitThis; ->c.implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 8, 5)) ->c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 8, 5)) ->reconstructed.implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 90, 45)) ->reconstructed : Symbol(reconstructed, Decl(thisTypeInFunctions.ts, 88, 3)) ->implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 90, 45)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 128, 26)) c.explicitC = function(this: B, m: number) { return this.n + m }; ->c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) ->c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 147, 23)) +>c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 65, 3)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 130, 23)) >B : Symbol(B, Decl(thisTypeInFunctions.ts, 0, 0)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 147, 31)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 130, 31)) >this.n : Symbol(B.n, Decl(thisTypeInFunctions.ts, 1, 9)) >this : Symbol(B, Decl(thisTypeInFunctions.ts, 0, 0)) >n : Symbol(B.n, Decl(thisTypeInFunctions.ts, 1, 9)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 147, 31)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 130, 31)) // this:void compatibility c.explicitVoid = n => n; ->c.explicitVoid : Symbol(C.explicitVoid, Decl(thisTypeInFunctions.ts, 17, 5)) ->c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitVoid : Symbol(C.explicitVoid, Decl(thisTypeInFunctions.ts, 17, 5)) ->n : Symbol(n, Decl(thisTypeInFunctions.ts, 150, 16)) ->n : Symbol(n, Decl(thisTypeInFunctions.ts, 150, 16)) +>c.explicitVoid : Symbol(C.explicitVoid, Decl(thisTypeInFunctions.ts, 14, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 65, 3)) +>explicitVoid : Symbol(C.explicitVoid, Decl(thisTypeInFunctions.ts, 14, 5)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 133, 16)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 133, 16)) // class-based assignability class Base1 { ->Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) +>Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 133, 24)) x: number; ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 153, 13)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 136, 13)) - public implicit(): number { return this.x; } ->implicit : Symbol(implicit, Decl(thisTypeInFunctions.ts, 154, 14)) ->this.x : Symbol(x, Decl(thisTypeInFunctions.ts, 153, 13)) ->this : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 153, 13)) + public polymorphic(this: this): number { return this.x; } +>polymorphic : Symbol(polymorphic, Decl(thisTypeInFunctions.ts, 137, 14)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 138, 23)) +>this.x : Symbol(x, Decl(thisTypeInFunctions.ts, 136, 13)) +>this : Symbol(Base1, Decl(thisTypeInFunctions.ts, 133, 24)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 136, 13)) explicit(this: Base1): number { return this.x; } ->explicit : Symbol(explicit, Decl(thisTypeInFunctions.ts, 155, 48)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 156, 13)) ->Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) ->this.x : Symbol(x, Decl(thisTypeInFunctions.ts, 153, 13)) ->this : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 153, 13)) - - static implicitStatic(): number { return this.y; } ->implicitStatic : Symbol(Base1.implicitStatic, Decl(thisTypeInFunctions.ts, 156, 52)) ->this.y : Symbol(Base1.y, Decl(thisTypeInFunctions.ts, 158, 72)) ->this : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) ->y : Symbol(Base1.y, Decl(thisTypeInFunctions.ts, 158, 72)) +>explicit : Symbol(explicit, Decl(thisTypeInFunctions.ts, 138, 61)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 139, 13)) +>Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 133, 24)) +>this.x : Symbol(x, Decl(thisTypeInFunctions.ts, 136, 13)) +>this : Symbol(Base1, Decl(thisTypeInFunctions.ts, 133, 24)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 136, 13)) static explicitStatic(this: typeof Base1): number { return this.y; } ->explicitStatic : Symbol(Base1.explicitStatic, Decl(thisTypeInFunctions.ts, 157, 54)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 158, 26)) ->Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) ->this.y : Symbol(Base1.y, Decl(thisTypeInFunctions.ts, 158, 72)) ->this : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) ->y : Symbol(Base1.y, Decl(thisTypeInFunctions.ts, 158, 72)) +>explicitStatic : Symbol(Base1.explicitStatic, Decl(thisTypeInFunctions.ts, 139, 52)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 140, 26)) +>Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 133, 24)) +>this.y : Symbol(Base1.y, Decl(thisTypeInFunctions.ts, 140, 72)) +>this : Symbol(Base1, Decl(thisTypeInFunctions.ts, 133, 24)) +>y : Symbol(Base1.y, Decl(thisTypeInFunctions.ts, 140, 72)) static y: number; ->y : Symbol(Base1.y, Decl(thisTypeInFunctions.ts, 158, 72)) - +>y : Symbol(Base1.y, Decl(thisTypeInFunctions.ts, 140, 72)) } class Derived1 extends Base1 { ->Derived1 : Symbol(Derived1, Decl(thisTypeInFunctions.ts, 161, 1)) ->Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) +>Derived1 : Symbol(Derived1, Decl(thisTypeInFunctions.ts, 142, 1)) +>Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 133, 24)) y: number ->y : Symbol(y, Decl(thisTypeInFunctions.ts, 162, 30)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 143, 30)) } class Base2 { ->Base2 : Symbol(Base2, Decl(thisTypeInFunctions.ts, 164, 1)) +>Base2 : Symbol(Base2, Decl(thisTypeInFunctions.ts, 145, 1)) y: number ->y : Symbol(y, Decl(thisTypeInFunctions.ts, 165, 13)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 146, 13)) - implicit(): number { return this.y; } ->implicit : Symbol(implicit, Decl(thisTypeInFunctions.ts, 166, 13)) ->this.y : Symbol(y, Decl(thisTypeInFunctions.ts, 165, 13)) ->this : Symbol(Base2, Decl(thisTypeInFunctions.ts, 164, 1)) ->y : Symbol(y, Decl(thisTypeInFunctions.ts, 165, 13)) + polymorphic(this: this): number { return this.y; } +>polymorphic : Symbol(polymorphic, Decl(thisTypeInFunctions.ts, 147, 13)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 148, 16)) +>this.y : Symbol(y, Decl(thisTypeInFunctions.ts, 146, 13)) +>this : Symbol(Base2, Decl(thisTypeInFunctions.ts, 145, 1)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 146, 13)) explicit(this: Base1): number { return this.x; } ->explicit : Symbol(explicit, Decl(thisTypeInFunctions.ts, 167, 41)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 168, 13)) ->Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) ->this.x : Symbol(Base1.x, Decl(thisTypeInFunctions.ts, 153, 13)) ->this : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) ->x : Symbol(Base1.x, Decl(thisTypeInFunctions.ts, 153, 13)) +>explicit : Symbol(explicit, Decl(thisTypeInFunctions.ts, 148, 54)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 149, 13)) +>Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 133, 24)) +>this.x : Symbol(Base1.x, Decl(thisTypeInFunctions.ts, 136, 13)) +>this : Symbol(Base1, Decl(thisTypeInFunctions.ts, 133, 24)) +>x : Symbol(Base1.x, Decl(thisTypeInFunctions.ts, 136, 13)) } class Derived2 extends Base2 { ->Derived2 : Symbol(Derived2, Decl(thisTypeInFunctions.ts, 169, 1)) ->Base2 : Symbol(Base2, Decl(thisTypeInFunctions.ts, 164, 1)) +>Derived2 : Symbol(Derived2, Decl(thisTypeInFunctions.ts, 150, 1)) +>Base2 : Symbol(Base2, Decl(thisTypeInFunctions.ts, 145, 1)) x: number ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 170, 30)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 151, 30)) } let b1 = new Base1(); ->b1 : Symbol(b1, Decl(thisTypeInFunctions.ts, 173, 3)) ->Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) +>b1 : Symbol(b1, Decl(thisTypeInFunctions.ts, 154, 3)) +>Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 133, 24)) let b2 = new Base2(); ->b2 : Symbol(b2, Decl(thisTypeInFunctions.ts, 174, 3)) ->Base2 : Symbol(Base2, Decl(thisTypeInFunctions.ts, 164, 1)) +>b2 : Symbol(b2, Decl(thisTypeInFunctions.ts, 155, 3)) +>Base2 : Symbol(Base2, Decl(thisTypeInFunctions.ts, 145, 1)) let d1 = new Derived1(); ->d1 : Symbol(d1, Decl(thisTypeInFunctions.ts, 175, 3)) ->Derived1 : Symbol(Derived1, Decl(thisTypeInFunctions.ts, 161, 1)) +>d1 : Symbol(d1, Decl(thisTypeInFunctions.ts, 156, 3)) +>Derived1 : Symbol(Derived1, Decl(thisTypeInFunctions.ts, 142, 1)) let d2 = new Derived2(); ->d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 176, 3)) ->Derived2 : Symbol(Derived2, Decl(thisTypeInFunctions.ts, 169, 1)) - -d2.implicit = d1.implicit // ok, 'x' and 'y' in { x, y } (d assignable to f and vice versa) ->d2.implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) ->d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 176, 3)) ->implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) ->d1.implicit : Symbol(Base1.implicit, Decl(thisTypeInFunctions.ts, 154, 14)) ->d1 : Symbol(d1, Decl(thisTypeInFunctions.ts, 175, 3)) ->implicit : Symbol(Base1.implicit, Decl(thisTypeInFunctions.ts, 154, 14)) - -d1.implicit = d2.implicit // ok, 'x' and 'y' in { x, y } (f assignable to d and vice versa) ->d1.implicit : Symbol(Base1.implicit, Decl(thisTypeInFunctions.ts, 154, 14)) ->d1 : Symbol(d1, Decl(thisTypeInFunctions.ts, 175, 3)) ->implicit : Symbol(Base1.implicit, Decl(thisTypeInFunctions.ts, 154, 14)) ->d2.implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) ->d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 176, 3)) ->implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) +>d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 157, 3)) +>Derived2 : Symbol(Derived2, Decl(thisTypeInFunctions.ts, 150, 1)) + +d2.polymorphic = d1.polymorphic // ok, 'x' and 'y' in { x, y } +>d2.polymorphic : Symbol(Base2.polymorphic, Decl(thisTypeInFunctions.ts, 147, 13)) +>d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 157, 3)) +>polymorphic : Symbol(Base2.polymorphic, Decl(thisTypeInFunctions.ts, 147, 13)) +>d1.polymorphic : Symbol(Base1.polymorphic, Decl(thisTypeInFunctions.ts, 137, 14)) +>d1 : Symbol(d1, Decl(thisTypeInFunctions.ts, 156, 3)) +>polymorphic : Symbol(Base1.polymorphic, Decl(thisTypeInFunctions.ts, 137, 14)) + +d1.polymorphic = d2.polymorphic // ok, 'x' and 'y' in { x, y } +>d1.polymorphic : Symbol(Base1.polymorphic, Decl(thisTypeInFunctions.ts, 137, 14)) +>d1 : Symbol(d1, Decl(thisTypeInFunctions.ts, 156, 3)) +>polymorphic : Symbol(Base1.polymorphic, Decl(thisTypeInFunctions.ts, 137, 14)) +>d2.polymorphic : Symbol(Base2.polymorphic, Decl(thisTypeInFunctions.ts, 147, 13)) +>d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 157, 3)) +>polymorphic : Symbol(Base2.polymorphic, Decl(thisTypeInFunctions.ts, 147, 13)) // bivariance-allowed cases -d1.implicit = b2.implicit // ok, 'y' in D: { x, y } (d assignable e) ->d1.implicit : Symbol(Base1.implicit, Decl(thisTypeInFunctions.ts, 154, 14)) ->d1 : Symbol(d1, Decl(thisTypeInFunctions.ts, 175, 3)) ->implicit : Symbol(Base1.implicit, Decl(thisTypeInFunctions.ts, 154, 14)) ->b2.implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) ->b2 : Symbol(b2, Decl(thisTypeInFunctions.ts, 174, 3)) ->implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) - -d2.implicit = d1.explicit // ok, 'y' in { x, y } (c assignable to f) ->d2.implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) ->d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 176, 3)) ->implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) ->d1.explicit : Symbol(Base1.explicit, Decl(thisTypeInFunctions.ts, 155, 48)) ->d1 : Symbol(d1, Decl(thisTypeInFunctions.ts, 175, 3)) ->explicit : Symbol(Base1.explicit, Decl(thisTypeInFunctions.ts, 155, 48)) - -b1.implicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) ->b1.implicit : Symbol(Base1.implicit, Decl(thisTypeInFunctions.ts, 154, 14)) ->b1 : Symbol(b1, Decl(thisTypeInFunctions.ts, 173, 3)) ->implicit : Symbol(Base1.implicit, Decl(thisTypeInFunctions.ts, 154, 14)) ->d2.implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) ->d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 176, 3)) ->implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) - -b1.explicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) ->b1.explicit : Symbol(Base1.explicit, Decl(thisTypeInFunctions.ts, 155, 48)) ->b1 : Symbol(b1, Decl(thisTypeInFunctions.ts, 173, 3)) ->explicit : Symbol(Base1.explicit, Decl(thisTypeInFunctions.ts, 155, 48)) ->d2.implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) ->d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 176, 3)) ->implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) +d1.polymorphic = b2.polymorphic // ok, 'y' in D: { x, y } +>d1.polymorphic : Symbol(Base1.polymorphic, Decl(thisTypeInFunctions.ts, 137, 14)) +>d1 : Symbol(d1, Decl(thisTypeInFunctions.ts, 156, 3)) +>polymorphic : Symbol(Base1.polymorphic, Decl(thisTypeInFunctions.ts, 137, 14)) +>b2.polymorphic : Symbol(Base2.polymorphic, Decl(thisTypeInFunctions.ts, 147, 13)) +>b2 : Symbol(b2, Decl(thisTypeInFunctions.ts, 155, 3)) +>polymorphic : Symbol(Base2.polymorphic, Decl(thisTypeInFunctions.ts, 147, 13)) + +d2.polymorphic = d1.explicit // ok, 'y' in { x, y } +>d2.polymorphic : Symbol(Base2.polymorphic, Decl(thisTypeInFunctions.ts, 147, 13)) +>d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 157, 3)) +>polymorphic : Symbol(Base2.polymorphic, Decl(thisTypeInFunctions.ts, 147, 13)) +>d1.explicit : Symbol(Base1.explicit, Decl(thisTypeInFunctions.ts, 138, 61)) +>d1 : Symbol(d1, Decl(thisTypeInFunctions.ts, 156, 3)) +>explicit : Symbol(Base1.explicit, Decl(thisTypeInFunctions.ts, 138, 61)) + +b1.polymorphic = d2.polymorphic // ok, 'x' and 'y' not in Base1: { x } +>b1.polymorphic : Symbol(Base1.polymorphic, Decl(thisTypeInFunctions.ts, 137, 14)) +>b1 : Symbol(b1, Decl(thisTypeInFunctions.ts, 154, 3)) +>polymorphic : Symbol(Base1.polymorphic, Decl(thisTypeInFunctions.ts, 137, 14)) +>d2.polymorphic : Symbol(Base2.polymorphic, Decl(thisTypeInFunctions.ts, 147, 13)) +>d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 157, 3)) +>polymorphic : Symbol(Base2.polymorphic, Decl(thisTypeInFunctions.ts, 147, 13)) + +b1.explicit = d2.polymorphic // ok, 'x' and 'y' not in Base1: { x } +>b1.explicit : Symbol(Base1.explicit, Decl(thisTypeInFunctions.ts, 138, 61)) +>b1 : Symbol(b1, Decl(thisTypeInFunctions.ts, 154, 3)) +>explicit : Symbol(Base1.explicit, Decl(thisTypeInFunctions.ts, 138, 61)) +>d2.polymorphic : Symbol(Base2.polymorphic, Decl(thisTypeInFunctions.ts, 147, 13)) +>d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 157, 3)) +>polymorphic : Symbol(Base2.polymorphic, Decl(thisTypeInFunctions.ts, 147, 13)) ////// use this-type for construction with new //// function InterfaceThis(this: I) { ->InterfaceThis : Symbol(InterfaceThis, Decl(thisTypeInFunctions.ts, 184, 25)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 187, 23)) ->I : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 21)) +>InterfaceThis : Symbol(InterfaceThis, Decl(thisTypeInFunctions.ts, 165, 28)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 168, 23)) +>I : Symbol(I, Decl(thisTypeInFunctions.ts, 19, 21)) this.a = 12; ->this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) ->this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 21)) ->a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) +>this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 20, 13)) +>this : Symbol(I, Decl(thisTypeInFunctions.ts, 19, 21)) +>a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 20, 13)) } function LiteralTypeThis(this: {x: string}) { ->LiteralTypeThis : Symbol(LiteralTypeThis, Decl(thisTypeInFunctions.ts, 189, 1)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 190, 25)) ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 190, 32)) +>LiteralTypeThis : Symbol(LiteralTypeThis, Decl(thisTypeInFunctions.ts, 170, 1)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 171, 25)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 171, 32)) this.x = "ok"; ->this.x : Symbol(x, Decl(thisTypeInFunctions.ts, 190, 32)) ->this : Symbol(, Decl(thisTypeInFunctions.ts, 190, 30)) ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 190, 32)) +>this.x : Symbol(x, Decl(thisTypeInFunctions.ts, 171, 32)) +>this : Symbol(, Decl(thisTypeInFunctions.ts, 171, 30)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 171, 32)) } function AnyThis(this: any) { ->AnyThis : Symbol(AnyThis, Decl(thisTypeInFunctions.ts, 192, 1)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 193, 17)) +>AnyThis : Symbol(AnyThis, Decl(thisTypeInFunctions.ts, 173, 1)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 174, 17)) this.x = "ok"; } let interfaceThis = new InterfaceThis(); ->interfaceThis : Symbol(interfaceThis, Decl(thisTypeInFunctions.ts, 196, 3)) ->InterfaceThis : Symbol(InterfaceThis, Decl(thisTypeInFunctions.ts, 184, 25)) +>interfaceThis : Symbol(interfaceThis, Decl(thisTypeInFunctions.ts, 177, 3)) +>InterfaceThis : Symbol(InterfaceThis, Decl(thisTypeInFunctions.ts, 165, 28)) let literalTypeThis = new LiteralTypeThis(); ->literalTypeThis : Symbol(literalTypeThis, Decl(thisTypeInFunctions.ts, 197, 3)) ->LiteralTypeThis : Symbol(LiteralTypeThis, Decl(thisTypeInFunctions.ts, 189, 1)) +>literalTypeThis : Symbol(literalTypeThis, Decl(thisTypeInFunctions.ts, 178, 3)) +>LiteralTypeThis : Symbol(LiteralTypeThis, Decl(thisTypeInFunctions.ts, 170, 1)) let anyThis = new AnyThis(); ->anyThis : Symbol(anyThis, Decl(thisTypeInFunctions.ts, 198, 3)) ->AnyThis : Symbol(AnyThis, Decl(thisTypeInFunctions.ts, 192, 1)) +>anyThis : Symbol(anyThis, Decl(thisTypeInFunctions.ts, 179, 3)) +>AnyThis : Symbol(AnyThis, Decl(thisTypeInFunctions.ts, 173, 1)) //// type parameter inference //// declare var f: { ->f : Symbol(f, Decl(thisTypeInFunctions.ts, 201, 11)) +>f : Symbol(f, Decl(thisTypeInFunctions.ts, 182, 11)) (this: void, x: number): number, ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 202, 5)) ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 202, 16)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 183, 5)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 183, 16)) call(this: (...argArray: any[]) => U, ...argArray: any[]): U; ->call : Symbol(call, Decl(thisTypeInFunctions.ts, 202, 36)) ->U : Symbol(U, Decl(thisTypeInFunctions.ts, 203, 9)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 203, 12)) ->argArray : Symbol(argArray, Decl(thisTypeInFunctions.ts, 203, 19)) ->U : Symbol(U, Decl(thisTypeInFunctions.ts, 203, 9)) ->argArray : Symbol(argArray, Decl(thisTypeInFunctions.ts, 203, 44)) ->U : Symbol(U, Decl(thisTypeInFunctions.ts, 203, 9)) +>call : Symbol(call, Decl(thisTypeInFunctions.ts, 183, 36)) +>U : Symbol(U, Decl(thisTypeInFunctions.ts, 184, 9)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 184, 12)) +>argArray : Symbol(argArray, Decl(thisTypeInFunctions.ts, 184, 19)) +>U : Symbol(U, Decl(thisTypeInFunctions.ts, 184, 9)) +>argArray : Symbol(argArray, Decl(thisTypeInFunctions.ts, 184, 44)) +>U : Symbol(U, Decl(thisTypeInFunctions.ts, 184, 9)) }; let n: number = f.call(12); ->n : Symbol(n, Decl(thisTypeInFunctions.ts, 205, 3)) ->f.call : Symbol(call, Decl(thisTypeInFunctions.ts, 202, 36)) ->f : Symbol(f, Decl(thisTypeInFunctions.ts, 201, 11)) ->call : Symbol(call, Decl(thisTypeInFunctions.ts, 202, 36)) - -function missingTypeIsImplicitAny(this, a: number) { return a; } ->missingTypeIsImplicitAny : Symbol(missingTypeIsImplicitAny, Decl(thisTypeInFunctions.ts, 205, 27)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 207, 34)) ->a : Symbol(a, Decl(thisTypeInFunctions.ts, 207, 39)) ->a : Symbol(a, Decl(thisTypeInFunctions.ts, 207, 39)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 186, 3)) +>f.call : Symbol(call, Decl(thisTypeInFunctions.ts, 183, 36)) +>f : Symbol(f, Decl(thisTypeInFunctions.ts, 182, 11)) +>call : Symbol(call, Decl(thisTypeInFunctions.ts, 183, 36)) + +function missingTypeIsImplicitAny(this, a: number) { return this.anything + a; } +>missingTypeIsImplicitAny : Symbol(missingTypeIsImplicitAny, Decl(thisTypeInFunctions.ts, 186, 27)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 188, 34)) +>a : Symbol(a, Decl(thisTypeInFunctions.ts, 188, 39)) +>a : Symbol(a, Decl(thisTypeInFunctions.ts, 188, 39)) diff --git a/tests/baselines/reference/thisTypeInFunctions.types b/tests/baselines/reference/thisTypeInFunctions.types index 3922e454c3ff1..48186eee2d067 100644 --- a/tests/baselines/reference/thisTypeInFunctions.types +++ b/tests/baselines/reference/thisTypeInFunctions.types @@ -22,17 +22,6 @@ class C { >this.n : number >this : this >n : number ->m : number - } - implicitThis(m: number): number { ->implicitThis : (this: this, m: number) => number ->m : number - - return this.n + m; ->this.n + m : number ->this.n : number ->this : this ->n : number >m : number } explicitC(this: C, m: number): number { @@ -103,12 +92,6 @@ interface I { explicitThis(this: this): number; >explicitThis : (this: this) => number >this : this - - implicitMethod(): number; ->implicitMethod : (this: this) => number - - implicitFunction: () => number; ->implicitFunction : (this: void) => number } function explicitStructural(this: { y: number }, x: number): number { >explicitStructural : (this: { y: number; }, x: number) => number @@ -134,16 +117,22 @@ function justThis(this: { y: number }): number { >y : number } function implicitThis(n: number): number { ->implicitThis : (this: void, n: number) => number +>implicitThis : (n: number) => number >n : number - return 12; + return this.m + n + 12; +>this.m + n + 12 : any +>this.m + n : any +>this.m : any +>this : any +>m : any +>n : number >12 : number } let impl: I = { >impl : I >I : I ->{ a: 12, explicitVoid2: () => this.a, // ok, this: any because it refers to some outer object (window?) explicitVoid1() { return 12; }, explicitStructural() { return this.a; }, explicitInterface() { return this.a; }, explicitThis() { return this.a; }, implicitMethod() { return this.a; }, implicitFunction: () => this.a, // ok, this: any because it refers to some outer object (window?)} : { a: number; explicitVoid2: () => any; explicitVoid1(): number; explicitStructural(): number; explicitInterface(): number; explicitThis(): number; implicitMethod(): number; implicitFunction: () => any; } +>{ a: 12, explicitVoid2: () => this.a, // ok, this: any because it refers to some outer object (window?) explicitVoid1() { return 12; }, explicitStructural() { return this.a; }, explicitInterface() { return this.a; }, explicitThis() { return this.a; },} : { a: number; explicitVoid2: () => any; explicitVoid1(): number; explicitStructural(): number; explicitInterface(): number; explicitThis(): number; } a: 12, >a : number @@ -187,28 +176,13 @@ let impl: I = { >a : number }, - implicitMethod() { ->implicitMethod : () => number - - return this.a; ->this.a : number ->this : I ->a : number - - }, - implicitFunction: () => this.a, // ok, this: any because it refers to some outer object (window?) ->implicitFunction : () => any ->() => this.a : () => any ->this.a : any ->this : any ->a : any } impl.explicitVoid1 = function () { return 12; }; ->impl.explicitVoid1 = function () { return 12; } : (this: void) => number +>impl.explicitVoid1 = function () { return 12; } : () => number >impl.explicitVoid1 : (this: void) => number >impl : I >explicitVoid1 : (this: void) => number ->function () { return 12; } : (this: void) => number +>function () { return 12; } : () => number >12 : number impl.explicitVoid2 = () => 12; @@ -220,21 +194,21 @@ impl.explicitVoid2 = () => 12; >12 : number impl.explicitStructural = function() { return this.a; }; ->impl.explicitStructural = function() { return this.a; } : (this: void) => number +>impl.explicitStructural = function() { return this.a; } : () => number >impl.explicitStructural : (this: { a: number; }) => number >impl : I >explicitStructural : (this: { a: number; }) => number ->function() { return this.a; } : (this: void) => number +>function() { return this.a; } : () => number >this.a : number >this : { a: number; } >a : number impl.explicitInterface = function() { return this.a; }; ->impl.explicitInterface = function() { return this.a; } : (this: void) => number +>impl.explicitInterface = function() { return this.a; } : () => number >impl.explicitInterface : (this: I) => number >impl : I >explicitInterface : (this: I) => number ->function() { return this.a; } : (this: void) => number +>function() { return this.a; } : () => number >this.a : number >this : I >a : number @@ -256,43 +230,15 @@ impl.explicitInterface = () => 12; >12 : number impl.explicitThis = function () { return this.a; }; ->impl.explicitThis = function () { return this.a; } : (this: void) => number +>impl.explicitThis = function () { return this.a; } : () => number >impl.explicitThis : (this: I) => number >impl : I >explicitThis : (this: I) => number ->function () { return this.a; } : (this: void) => number ->this.a : number ->this : I ->a : number - -impl.implicitMethod = function () { return this.a; }; ->impl.implicitMethod = function () { return this.a; } : (this: void) => number ->impl.implicitMethod : (this: I) => number ->impl : I ->implicitMethod : (this: I) => number ->function () { return this.a; } : (this: void) => number +>function () { return this.a; } : () => number >this.a : number >this : I >a : number -impl.implicitMethod = () => 12; ->impl.implicitMethod = () => 12 : () => number ->impl.implicitMethod : (this: I) => number ->impl : I ->implicitMethod : (this: I) => number ->() => 12 : () => number ->12 : number - -impl.implicitFunction = () => this.a; // ok, this: any because it refers to some outer object (window?) ->impl.implicitFunction = () => this.a : () => any ->impl.implicitFunction : (this: void) => number ->impl : I ->implicitFunction : (this: void) => number ->() => this.a : () => any ->this.a : any ->this : any ->a : any - // parameter checking let ok: {y: number, f: (this: { y: number }, x: number) => number} = { y: 12, f: explicitStructural }; >ok : { y: number; f: (this: { y: number; }, x: number) => number; } @@ -308,15 +254,15 @@ let ok: {y: number, f: (this: { y: number }, x: number) => number} = { y: 12, f: >explicitStructural : (this: { y: number; }, x: number) => number let implicitAnyOk: {notSpecified: number, f: (x: number) => number} = { notSpecified: 12, f: implicitThis }; ->implicitAnyOk : { notSpecified: number; f: (this: void, x: number) => number; } +>implicitAnyOk : { notSpecified: number; f: (x: number) => number; } >notSpecified : number ->f : (this: void, x: number) => number +>f : (x: number) => number >x : number ->{ notSpecified: 12, f: implicitThis } : { notSpecified: number; f: (this: void, n: number) => number; } +>{ notSpecified: 12, f: implicitThis } : { notSpecified: number; f: (n: number) => number; } >notSpecified : number >12 : number ->f : (this: void, n: number) => number ->implicitThis : (this: void, n: number) => number +>f : (n: number) => number +>implicitThis : (n: number) => number ok.f(13); >ok.f(13) : number @@ -327,14 +273,14 @@ ok.f(13); implicitThis(12); >implicitThis(12) : number ->implicitThis : (this: void, n: number) => number +>implicitThis : (n: number) => number >12 : number implicitAnyOk.f(12); >implicitAnyOk.f(12) : number ->implicitAnyOk.f : (this: void, x: number) => number ->implicitAnyOk : { notSpecified: number; f: (this: void, x: number) => number; } ->f : (this: void, x: number) => number +>implicitAnyOk.f : (x: number) => number +>implicitAnyOk : { notSpecified: number; f: (x: number) => number; } +>f : (x: number) => number >12 : number let c = new C(); @@ -374,13 +320,6 @@ c.explicitThis(12); >explicitThis : (this: C, m: number) => number >12 : number -c.implicitThis(12); ->c.implicitThis(12) : number ->c.implicitThis : (this: C, m: number) => number ->c : C ->implicitThis : (this: C, m: number) => number ->12 : number - d.explicitC(12); >d.explicitC(12) : number >d.explicitC : (this: C, m: number) => number @@ -402,15 +341,8 @@ d.explicitThis(12); >explicitThis : (this: D, m: number) => number >12 : number -d.implicitThis(12); ->d.implicitThis(12) : number ->d.implicitThis : (this: D, m: number) => number ->d : D ->implicitThis : (this: D, m: number) => number ->12 : number - let reconstructed: { ->reconstructed : { n: number; explicitThis(this: C, m: number): number; implicitThis(m: number): number; explicitC(this: C, m: number): number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid(this: void, m: number): number; } +>reconstructed : { n: number; explicitThis(this: C, m: number): number; explicitC(this: C, m: number): number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid(this: void, m: number): number; } n: number, >n : number @@ -419,10 +351,6 @@ let reconstructed: { >explicitThis : (this: C, m: number) => number >this : C >C : C ->m : number - - implicitThis(m: number): number, ->implicitThis : (m: number) => number >m : number explicitC(this: C, m: number): number, @@ -443,7 +371,7 @@ let reconstructed: { >m : number } = { ->{ n: 12, explicitThis: c.explicitThis, implicitThis: c.implicitThis, explicitC: c.explicitC, explicitProperty: c.explicitProperty, explicitVoid: c.explicitVoid} : { n: number; explicitThis: (this: C, m: number) => number; implicitThis: (this: C, m: number) => number; explicitC: (this: C, m: number) => number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid: (this: void, m: number) => number; } +>{ n: 12, explicitThis: c.explicitThis, explicitC: c.explicitC, explicitProperty: c.explicitProperty, explicitVoid: c.explicitVoid} : { n: number; explicitThis: (this: C, m: number) => number; explicitC: (this: C, m: number) => number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid: (this: void, m: number) => number; } n: 12, >n : number @@ -455,12 +383,6 @@ let reconstructed: { >c : C >explicitThis : (this: C, m: number) => number - implicitThis: c.implicitThis, ->implicitThis : (this: C, m: number) => number ->c.implicitThis : (this: C, m: number) => number ->c : C ->implicitThis : (this: C, m: number) => number - explicitC: c.explicitC, >explicitC : (this: C, m: number) => number >c.explicitC : (this: C, m: number) => number @@ -480,19 +402,30 @@ let reconstructed: { >explicitVoid : (this: void, m: number) => number }; +reconstructed.explicitThis(10); +>reconstructed.explicitThis(10) : number +>reconstructed.explicitThis : (this: C, m: number) => number +>reconstructed : { n: number; explicitThis(this: C, m: number): number; explicitC(this: C, m: number): number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid(this: void, m: number): number; } +>explicitThis : (this: C, m: number) => number +>10 : number + reconstructed.explicitProperty(11); >reconstructed.explicitProperty(11) : number >reconstructed.explicitProperty : (this: { n: number; }, m: number) => number ->reconstructed : { n: number; explicitThis(this: C, m: number): number; implicitThis(m: number): number; explicitC(this: C, m: number): number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid(this: void, m: number): number; } +>reconstructed : { n: number; explicitThis(this: C, m: number): number; explicitC(this: C, m: number): number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid(this: void, m: number): number; } >explicitProperty : (this: { n: number; }, m: number) => number >11 : number -reconstructed.implicitThis(11); ->reconstructed.implicitThis(11) : number ->reconstructed.implicitThis : (m: number) => number ->reconstructed : { n: number; explicitThis(this: C, m: number): number; implicitThis(m: number): number; explicitC(this: C, m: number): number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid(this: void, m: number): number; } ->implicitThis : (m: number) => number ->11 : number +let explicitVoid = reconstructed.explicitVoid; +>explicitVoid : (this: void, m: number) => number +>reconstructed.explicitVoid : (this: void, m: number) => number +>reconstructed : { n: number; explicitThis(this: C, m: number): number; explicitC(this: C, m: number): number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid(this: void, m: number): number; } +>explicitVoid : (this: void, m: number) => number + +explicitVoid(12); +>explicitVoid(12) : number +>explicitVoid : (this: void, m: number) => number +>12 : number // assignment checking let unboundToSpecified: (this: { y: number }, x: number) => number = x => x + this.y; // ok, this:any @@ -520,14 +453,14 @@ 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: void, x: number) => number +>function(x: number): number { return x + 12; } : (x: number) => number >x : number >x + 12 : number >x : number >12 : number let unspecifiedLambda: (x: number) => number = x => x + 12; ->unspecifiedLambda : (this: void, x: number) => number +>unspecifiedLambda : (x: number) => number >x : number >x => x + 12 : (x: number) => number >x : number @@ -550,7 +483,7 @@ let unspecifiedLambdaToSpecified: (this: {y: number}, x: number) => number = uns >this : { y: number; } >y : number >x : number ->unspecifiedLambda : (this: void, x: number) => number +>unspecifiedLambda : (x: number) => number let specifiedLambdaToSpecified: (this: {y: number}, x: number) => number = specifiedLambda; >specifiedLambdaToSpecified : (this: { y: number; }, x: number) => number @@ -622,7 +555,7 @@ c.explicitProperty = reconstructed.explicitProperty; >c : C >explicitProperty : (this: { n: number; }, m: number) => number >reconstructed.explicitProperty : (this: { n: number; }, m: number) => number ->reconstructed : { n: number; explicitThis(this: C, m: number): number; implicitThis(m: number): number; explicitC(this: C, m: number): number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid(this: void, m: number): number; } +>reconstructed : { n: number; explicitThis(this: C, m: number): number; explicitC(this: C, m: number): number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid(this: void, m: number): number; } >explicitProperty : (this: { n: number; }, m: number) => number // lambdas are assignable to anything @@ -719,11 +652,11 @@ c.explicitThis = function(this: C, m: number) { return this.n + m }; // this:any compatibility c.explicitC = function(m) { return this.n + m }; ->c.explicitC = function(m) { return this.n + m } : (this: void, m: number) => number +>c.explicitC = function(m) { return this.n + m } : (m: number) => number >c.explicitC : (this: C, m: number) => number >c : C >explicitC : (this: C, m: number) => number ->function(m) { return this.n + m } : (this: void, m: number) => number +>function(m) { return this.n + m } : (m: number) => number >m : number >this.n + m : number >this.n : number @@ -732,11 +665,11 @@ c.explicitC = function(m) { return this.n + m }; >m : number c.explicitProperty = function(m) { return this.n + m }; ->c.explicitProperty = function(m) { return this.n + m } : (this: void, m: number) => number +>c.explicitProperty = function(m) { return this.n + m } : (m: number) => number >c.explicitProperty : (this: { n: number; }, m: number) => number >c : C >explicitProperty : (this: { n: number; }, m: number) => number ->function(m) { return this.n + m } : (this: void, m: number) => number +>function(m) { return this.n + m } : (m: number) => number >m : number >this.n + m : number >this.n : number @@ -745,11 +678,11 @@ c.explicitProperty = function(m) { return this.n + m }; >m : number c.explicitThis = function(m) { return this.n + m }; ->c.explicitThis = function(m) { return this.n + m } : (this: void, m: number) => number +>c.explicitThis = function(m) { return this.n + m } : (m: number) => number >c.explicitThis : (this: C, m: number) => number >c : C >explicitThis : (this: C, m: number) => number ->function(m) { return this.n + m } : (this: void, m: number) => number +>function(m) { return this.n + m } : (m: number) => number >m : number >this.n + m : number >this.n : number @@ -757,28 +690,6 @@ c.explicitThis = function(m) { return this.n + m }; >n : number >m : number -c.implicitThis = function(m) { return this.n + m }; ->c.implicitThis = function(m) { return this.n + m } : (this: void, m: number) => number ->c.implicitThis : (this: C, m: number) => number ->c : C ->implicitThis : (this: C, m: number) => number ->function(m) { return this.n + m } : (this: void, m: number) => number ->m : number ->this.n + m : number ->this.n : number ->this : C ->n : number ->m : number - -c.implicitThis = reconstructed.implicitThis; ->c.implicitThis = reconstructed.implicitThis : (m: number) => number ->c.implicitThis : (this: C, m: number) => number ->c : C ->implicitThis : (this: C, m: number) => number ->reconstructed.implicitThis : (m: number) => number ->reconstructed : { n: number; explicitThis(this: C, m: number): number; implicitThis(m: number): number; explicitC(this: C, m: number): number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid(this: void, m: number): number; } ->implicitThis : (m: number) => number - c.explicitC = function(this: B, m: number) { return this.n + m }; >c.explicitC = function(this: B, m: number) { return this.n + m } : (this: B, m: number) => number >c.explicitC : (this: C, m: number) => number @@ -811,8 +722,9 @@ class Base1 { x: number; >x : number - public implicit(): number { return this.x; } ->implicit : (this: this) => number + public polymorphic(this: this): number { return this.x; } +>polymorphic : (this: this) => number +>this : this >this.x : number >this : this >x : number @@ -825,12 +737,6 @@ class Base1 { >this : Base1 >x : number - static implicitStatic(): number { return this.y; } ->implicitStatic : (this: typeof Base1) => number ->this.y : number ->this : typeof Base1 ->y : number - static explicitStatic(this: typeof Base1): number { return this.y; } >explicitStatic : (this: typeof Base1) => number >this : typeof Base1 @@ -841,7 +747,6 @@ class Base1 { static y: number; >y : number - } class Derived1 extends Base1 { >Derived1 : Derived1 @@ -856,8 +761,9 @@ class Base2 { y: number >y : number - implicit(): number { return this.y; } ->implicit : (this: this) => number + polymorphic(this: this): number { return this.y; } +>polymorphic : (this: this) => number +>this : this >this.y : number >this : this >y : number @@ -897,60 +803,60 @@ let d2 = new Derived2(); >new Derived2() : Derived2 >Derived2 : typeof Derived2 -d2.implicit = d1.implicit // ok, 'x' and 'y' in { x, y } (d assignable to f and vice versa) ->d2.implicit = d1.implicit : (this: Derived1) => number ->d2.implicit : (this: Derived2) => number +d2.polymorphic = d1.polymorphic // ok, 'x' and 'y' in { x, y } +>d2.polymorphic = d1.polymorphic : (this: Derived1) => number +>d2.polymorphic : (this: Derived2) => number >d2 : Derived2 ->implicit : (this: Derived2) => number ->d1.implicit : (this: Derived1) => number +>polymorphic : (this: Derived2) => number +>d1.polymorphic : (this: Derived1) => number >d1 : Derived1 ->implicit : (this: Derived1) => number +>polymorphic : (this: Derived1) => number -d1.implicit = d2.implicit // ok, 'x' and 'y' in { x, y } (f assignable to d and vice versa) ->d1.implicit = d2.implicit : (this: Derived2) => number ->d1.implicit : (this: Derived1) => number +d1.polymorphic = d2.polymorphic // ok, 'x' and 'y' in { x, y } +>d1.polymorphic = d2.polymorphic : (this: Derived2) => number +>d1.polymorphic : (this: Derived1) => number >d1 : Derived1 ->implicit : (this: Derived1) => number ->d2.implicit : (this: Derived2) => number +>polymorphic : (this: Derived1) => number +>d2.polymorphic : (this: Derived2) => number >d2 : Derived2 ->implicit : (this: Derived2) => number +>polymorphic : (this: Derived2) => number // bivariance-allowed cases -d1.implicit = b2.implicit // ok, 'y' in D: { x, y } (d assignable e) ->d1.implicit = b2.implicit : (this: Base2) => number ->d1.implicit : (this: Derived1) => number +d1.polymorphic = b2.polymorphic // ok, 'y' in D: { x, y } +>d1.polymorphic = b2.polymorphic : (this: Base2) => number +>d1.polymorphic : (this: Derived1) => number >d1 : Derived1 ->implicit : (this: Derived1) => number ->b2.implicit : (this: Base2) => number +>polymorphic : (this: Derived1) => number +>b2.polymorphic : (this: Base2) => number >b2 : Base2 ->implicit : (this: Base2) => number +>polymorphic : (this: Base2) => number -d2.implicit = d1.explicit // ok, 'y' in { x, y } (c assignable to f) ->d2.implicit = d1.explicit : (this: Base1) => number ->d2.implicit : (this: Derived2) => number +d2.polymorphic = d1.explicit // ok, 'y' in { x, y } +>d2.polymorphic = d1.explicit : (this: Base1) => number +>d2.polymorphic : (this: Derived2) => number >d2 : Derived2 ->implicit : (this: Derived2) => number +>polymorphic : (this: Derived2) => number >d1.explicit : (this: Base1) => number >d1 : Derived1 >explicit : (this: Base1) => number -b1.implicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) ->b1.implicit = d2.implicit : (this: Derived2) => number ->b1.implicit : (this: Base1) => number +b1.polymorphic = d2.polymorphic // ok, 'x' and 'y' not in Base1: { x } +>b1.polymorphic = d2.polymorphic : (this: Derived2) => number +>b1.polymorphic : (this: Base1) => number >b1 : Base1 ->implicit : (this: Base1) => number ->d2.implicit : (this: Derived2) => number +>polymorphic : (this: Base1) => number +>d2.polymorphic : (this: Derived2) => number >d2 : Derived2 ->implicit : (this: Derived2) => number +>polymorphic : (this: Derived2) => number -b1.explicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) ->b1.explicit = d2.implicit : (this: Derived2) => number +b1.explicit = d2.polymorphic // ok, 'x' and 'y' not in Base1: { x } +>b1.explicit = d2.polymorphic : (this: Derived2) => number >b1.explicit : (this: Base1) => number >b1 : Base1 >explicit : (this: Base1) => number ->d2.implicit : (this: Derived2) => number +>d2.polymorphic : (this: Derived2) => number >d2 : Derived2 ->implicit : (this: Derived2) => number +>polymorphic : (this: Derived2) => number ////// use this-type for construction with new //// function InterfaceThis(this: I) { @@ -1005,16 +911,16 @@ let anyThis = new AnyThis(); //// type parameter inference //// declare var f: { ->f : { (this: void, x: number): number; call(this: (this: void, ...argArray: any[]) => U, ...argArray: any[]): U; } +>f : { (this: void, x: number): number; call(this: (...argArray: any[]) => U, ...argArray: any[]): U; } (this: void, x: number): number, >this : void >x : number call(this: (...argArray: any[]) => U, ...argArray: any[]): U; ->call : (this: (this: void, ...argArray: any[]) => U, ...argArray: any[]) => U +>call : (this: (...argArray: any[]) => U, ...argArray: any[]) => U >U : U ->this : (this: void, ...argArray: any[]) => U +>this : (...argArray: any[]) => U >argArray : any[] >U : U >argArray : any[] @@ -1024,14 +930,18 @@ declare var f: { let n: number = f.call(12); >n : number >f.call(12) : number ->f.call : (this: (this: void, ...argArray: any[]) => U, ...argArray: any[]) => U ->f : { (this: void, x: number): number; call(this: (this: void, ...argArray: any[]) => U, ...argArray: any[]): U; } ->call : (this: (this: void, ...argArray: any[]) => U, ...argArray: any[]) => U +>f.call : (this: (...argArray: any[]) => U, ...argArray: any[]) => U +>f : { (this: void, x: number): number; call(this: (...argArray: any[]) => U, ...argArray: any[]): U; } +>call : (this: (...argArray: any[]) => U, ...argArray: any[]) => U >12 : number -function missingTypeIsImplicitAny(this, a: number) { return a; } ->missingTypeIsImplicitAny : (this: any, a: number) => number +function missingTypeIsImplicitAny(this, a: number) { return this.anything + a; } +>missingTypeIsImplicitAny : (this: any, a: number) => any >this : any >a : number +>this.anything + a : any +>this.anything : any +>this : any +>anything : any >a : number diff --git a/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt b/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt index c48ea11b3b001..c888f4e5ecbc7 100644 --- a/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt +++ b/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt @@ -1,126 +1,103 @@ 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(44,21): error TS2339: Property 'a' does not exist on type 'void'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(55,49): error TS2339: Property 'a' does not exist on type 'void'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(58,1): error TS2345: Argument of type 'void' is not assignable to parameter of type '{ a: number; }'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(60,1): error TS2345: Argument of type 'void' is not assignable to parameter of type 'I'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(62,1): error TS2345: Argument of type 'void' is not assignable to parameter of type 'I'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(67,21): error TS2339: Property 'notFound' does not exist on type '{ y: number; }'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(70,21): error TS2339: Property 'notSpecified' does not exist on type 'void'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(74,21): error TS2339: Property 'notSpecified' does not exist on type 'void'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(76,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; }'. +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 TS2345: Argument of type 'void' is not assignable to parameter of type '{ a: number; }'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(51,1): error TS2345: Argument of type 'void' is not assignable to parameter 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; }'. Object literal may only specify known properties, and 'explicitStructural' does not exist in type '{ y: number; f: (this: { y: number; }, x: number) => number; }'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(77,97): error TS2322: Type '{ y: string; explicitStructural: (this: { y: number; }, x: number) => number; }' is not assignable to type '{ y: string; f: (this: { y: number; }, x: number) => number; }'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(62,97): error TS2322: Type '{ y: string; explicitStructural: (this: { y: number; }, x: number) => number; }' is not assignable to type '{ y: string; f: (this: { y: number; }, x: number) => number; }'. Object literal may only specify known properties, and 'explicitStructural' does not exist in type '{ y: string; f: (this: { y: number; }, x: number) => number; }'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(78,110): error TS2322: Type '{ wrongName: number; explicitStructural: (this: { y: number; }, x: number) => number; }' is not assignable to type '{ wrongName: number; f: (this: { y: number; }, x: number) => number; }'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(63,110): error TS2322: Type '{ wrongName: number; explicitStructural: (this: { y: number; }, x: number) => number; }' is not assignable to type '{ wrongName: number; f: (this: { y: number; }, x: number) => number; }'. Object literal may only specify known properties, and 'explicitStructural' does not exist in type '{ wrongName: number; f: (this: { y: number; }, x: number) => number; }'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(80,1): error TS2346: Supplied parameters do not match any signature of call target. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(81,6): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(82,1): error TS2346: Supplied parameters do not match any signature of call target. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(83,1): error TS2345: Argument of type '{ y: string; f: (this: { y: number; }, x: number) => number; }' is not assignable to parameter of type '{ y: number; }'. +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 TS2345: Argument of type '{ y: string; f: (this: { y: number; }, x: number) => number; }' is not assignable to parameter 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(84,1): error TS2345: Argument of type '{ wrongName: number; f: (this: { y: number; }, x: number) => number; }' is not assignable to parameter of type '{ y: number; }'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(69,1): error TS2345: Argument of type '{ wrongName: number; f: (this: { y: number; }, x: number) => number; }' is not assignable to parameter 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(87,1): error TS2346: Supplied parameters do not match any signature of call target. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(88,13): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(89,1): error TS2346: Supplied parameters do not match any signature of call target. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(90,1): error TS2346: Supplied parameters do not match any signature of call target. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(91,16): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(92,1): error TS2346: Supplied parameters do not match any signature of call target. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(93,1): error TS2346: Supplied parameters do not match any signature of call target. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(94,16): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(95,1): error TS2346: Supplied parameters do not match any signature of call target. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(96,1): error TS2346: Supplied parameters do not match any signature of call target. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(97,20): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(98,1): error TS2346: Supplied parameters do not match any signature of call target. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(101,5): error TS2322: Type '(this: { y: number; }, x: number) => number' is not assignable to type '(this: void, 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'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(74,1): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(75,1): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(76,16): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(77,1): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(78,1): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(79,16): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(80,1): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(81,1): error TS2346: Supplied parameters do not match any signature of call target. +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. Type 'void' is not assignable to type '{ y: number; }'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(124,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(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. Type 'C' is not assignable to type 'D'. Property 'x' is missing in type 'C'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(125,1): error TS2322: Type '(this: { x: number; }, m: number) => number' is not assignable to type '(this: { n: number; }, m: number) => number'. +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. 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(127,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. - Type 'C' is not assignable to type 'D'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(128,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(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. Type 'C' is not assignable to type 'D'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(129,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(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. Type 'C' is not assignable to type 'D'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(130,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(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. Type 'C' is not assignable to type 'D'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(131,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(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. Type 'C' is not assignable to type 'D'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(132,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. - Type 'C' is not assignable to type 'D'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(133,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: { n: number; }, m: number) => number'. +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. Type '{ n: number; }' is not assignable to type 'D'. Property 'x' is missing in type '{ n: number; }'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(134,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. - Type '{ n: number; }' is not assignable to type 'D'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(135,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(136,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. - Type 'void' is not assignable to type 'D'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(137,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: void, m: number) => 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. Type 'void' is not assignable to type 'D'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(138,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: void, m: number) => number'. +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. Type 'void' is not assignable to type 'D'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(146,51): error TS2339: Property 'x' does not exist on type 'typeof Base1'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(147,69): error TS2339: Property 'x' does not exist on type 'typeof Base1'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(167,1): error TS2322: Type '(this: Base2) => number' is not assignable to type '(this: Base1) => number'. +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. Type 'Base1' is not assignable to type 'Base2'. Property 'y' is missing in type 'Base1'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(168,1): error TS2322: Type '(this: Base2) => number' is not assignable to type '(this: Base1) => number'. +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. Type 'Base1' is not assignable to type 'Base2'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(170,1): error TS2322: Type '(this: Base2) => number' is not assignable to type '(this: Base1) => number'. - Types of parameters 'this' and 'this' are incompatible. - Type 'Base1' is not assignable to type 'Base2'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(179,16): error TS2678: 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 TS2678: 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,17): error TS2680: A constructor cannot have a 'this' parameter. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(187,30): error TS2679: 'this' parameter must be the first parameter. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(187,61): error TS2339: Property 'n' does not exist on type 'void'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(190,26): error TS1003: Identifier expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(190,30): error TS1005: ',' expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(190,57): error TS2339: Property 'n' does not exist on type 'void'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(191,20): error TS2370: A rest parameter must be of an array type. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(191,23): error TS1003: Identifier expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(191,27): error TS1005: ',' expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(191,54): error TS2339: Property 'n' does not exist on type 'void'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(192,23): error TS1005: ',' expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(192,24): error TS1138: Parameter declaration expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(193,28): error TS1003: Identifier expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(193,32): error TS1005: ',' expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(193,59): error TS2339: Property 'n' does not exist on type 'void'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(194,30): error TS1005: ',' expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(194,32): error TS1138: Parameter declaration expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(194,39): error TS1005: ';' expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(194,40): error TS1128: Declaration or statement expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(194,42): error TS2304: Cannot find name 'number'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(194,49): error TS1005: ';' expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(197,1): error TS7027: Unreachable code detected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(197,29): error TS2304: Cannot find name 'm'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(197,32): error TS1005: ';' expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(197,35): error TS2304: Cannot find name 'm'. +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 TS2678: 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 TS2680: A constructor cannot have a 'this' parameter. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(161,30): error TS2679: 'this' parameter must be the first parameter. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(164,26): error TS1003: Identifier expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(164,30): error TS1005: ',' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(165,20): error TS2370: A rest parameter must be of an array type. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(165,23): error TS1003: Identifier expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(165,27): error TS1005: ',' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(166,23): error TS1005: ',' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(166,24): error TS1138: Parameter declaration expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(167,28): error TS1003: Identifier expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(167,32): error TS1005: ',' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(168,30): error TS1005: ',' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(168,32): error TS1138: Parameter declaration expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(168,39): error TS1005: ';' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(168,40): error TS1128: Declaration or statement expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(168,42): error TS2304: Cannot find name 'number'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(168,49): error TS1005: ';' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(171,1): error TS7027: Unreachable code detected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(171,29): error TS2304: Cannot find name 'm'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(171,32): error TS1005: ';' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(171,35): error TS2304: Cannot find name 'm'. -==== tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts (76 errors) ==== +==== tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts (63 errors) ==== class C { n: number; explicitThis(this: this, m: number): number { @@ -149,9 +126,6 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(197,35): e explicitD(this: D, m: number): number { return this.x + m; } - implicitD(m: number): number { - return this.x + m; - } } interface I { a: number; @@ -160,8 +134,6 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(197,35): e explicitStructural(this: {a: number}): number; explicitInterface(this: I): number; explicitThis(this: this): number; // TODO: Allow `this` types for interfaces - implicitMethod(): number; - implicitFunction: () => number; } let impl: I = { a: 12, @@ -176,12 +148,6 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(197,35): e explicitThis() { return this.a; }, - implicitMethod() { - return this.a; // ok, I.a: number - }, - implicitFunction: function () { return this.a; } // TODO: error 'a' not found in 'void' - ~ -!!! error TS2339: Property 'a' does not exist on type 'void'. } let implExplicitStructural = impl.explicitStructural; implExplicitStructural(); // error, no 'a' in 'void' @@ -190,10 +156,6 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(197,35): e let implExplicitInterface = impl.explicitInterface; implExplicitInterface(); // error, no 'a' in 'void' ~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2345: Argument of type 'void' is not assignable to parameter of type 'I'. - let implImplicitMethod = impl.implicitMethod; - implImplicitMethod(); // error, no 'a' in 'void' - ~~~~~~~~~~~~~~~~~~~~ !!! error TS2345: Argument of type 'void' is not assignable to parameter of type 'I'. function explicitStructural(this: { y: number }, x: number): number { return x + this.y; @@ -206,12 +168,6 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(197,35): e function voidThisSpecified(this: void, x: number): number { return x + this.notSpecified; ~~~~~~~~~~~~ -!!! error TS2339: Property 'notSpecified' does not exist on type 'void'. - } - function noThisSpecified(x: number): number { - // this:void unless loose-this is on - return x + this.notSpecified; - ~~~~~~~~~~~~ !!! error TS2339: Property 'notSpecified' does not exist on type 'void'. } let ok: {y: number, f: (this: { y: number }, x: number) => number} = { y: 12, explicitStructural }; @@ -285,8 +241,8 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(197,35): e !!! error TS2346: Supplied parameters do not match any signature of call target. // oops, this triggers contextual typing, which needs to be updated to understand that =>'s `this` is void. - let specifiedToImplicitVoid: (x: number) => number = explicitStructural; - ~~~~~~~~~~~~~~~~~~~~~~~ + 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: Type 'void' is not assignable to type '{ y: number; }'. @@ -294,14 +250,12 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(197,35): e let reconstructed: { n: number, explicitThis(this: C, m: number): number, // note: this: this is not allowed in an object literal type. - implicitThis(m: number): number, explicitC(this: C, m: number): number, explicitProperty: (this: {n : number}, m: number) => number, explicitVoid(this: void, m: number): number, } = { n: 12, explicitThis: c.explicitThis, - implicitThis: c.implicitThis, // error not assignable -- c.this:c not assignable to this:void. explicitC: c.explicitC, explicitProperty: c.explicitProperty, explicitVoid: c.explicitVoid @@ -325,11 +279,6 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(197,35): e !!! 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.implicitD; - ~~~~~~~~~~~ -!!! 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: Type 'C' is not assignable to type 'D'. c.explicitC = d.explicitD; ~~~~~~~~~~~ !!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'. @@ -339,11 +288,6 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(197,35): e ~~~~~~~~~~~ !!! 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: Type 'C' is not assignable to type 'D'. - c.explicitThis = d.implicitD; - ~~~~~~~~~~~~~~ -!!! 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: Type 'C' is not assignable to type 'D'. c.explicitThis = d.explicitD; ~~~~~~~~~~~~~~ @@ -361,19 +305,9 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(197,35): e !!! error TS2322: Types of parameters 'this' and 'this' are incompatible. !!! error TS2322: Type '{ n: number; }' is not assignable to type 'D'. !!! error TS2322: Property 'x' is missing in type '{ n: number; }'. - c.explicitProperty = d.implicitD; - ~~~~~~~~~~~~~~~~~~ -!!! 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: Type '{ n: number; }' 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'. - c.explicitVoid = d.implicitD; - ~~~~~~~~~~~~~~ -!!! 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: Type 'void' is not assignable to type 'D'. c.explicitVoid = d.explicitD; ~~~~~~~~~~~~~~ !!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: void, m: number) => number'. @@ -385,15 +319,12 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(197,35): e !!! error TS2322: Types of parameters 'this' and 'this' are incompatible. !!! error TS2322: Type 'void' is not assignable to type 'D'. - /// class-based implicit assignability (with inheritance!) /// + /// class-based polymorphic assignability (with inheritance!) /// class Base1 { x: number - public implicit(): number { return this.x; } + public polymorphic(this: this): number { return this.x; } explicit(this: Base1): number { return this.x; } - static implicitStatic(): number { return this.x; } - ~ -!!! error TS2339: Property 'x' does not exist on type 'typeof Base1'. static explicitStatic(this: typeof Base1): number { return this.x; } ~ !!! error TS2339: Property 'x' does not exist on type 'typeof Base1'. @@ -403,7 +334,7 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(197,35): e } class Base2 { y: number - implicit(): number { return this.y; } + polymorphic(this: this): number { return this.y; } explicit(this: Base1): number { return this.x; } } class Derived2 extends Base2 { @@ -416,37 +347,29 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(197,35): e let b2 = new Base2(); let d2 = new Derived2(); - b1.implicit = b2.implicit // error, 'this.y' not in C: { x } (c assignable to 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: Type 'Base1' is not assignable to type 'Base2'. !!! error TS2322: Property 'y' is missing in type 'Base1'. - b1.explicit = b2.implicit // error, 'y' not in C: { x } (c assignable to e) + 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: Type 'Base1' is not assignable to type 'Base2'. - d1.explicit = b2.implicit // error, 'y' not in C: { x } (c assignable to e) + d1.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: Type 'Base1' is not assignable to type 'Base2'. ////// use this-type for construction with new //// function VoidThis(this: void) { - } - function ImplicitVoidThis() { - } let voidThis = new VoidThis(); ~~~~~~~~~~~~~~ !!! error TS2678: A function that is called with the 'new' keyword cannot have a 'this' type that is void. - let implicitVoidThis = new ImplicitVoidThis(); - ~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2678: A function that is called with the 'new' keyword cannot have a 'this' type that is void. ///// syntax-ish errors ///// class ThisConstructor { @@ -458,8 +381,6 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(197,35): e function notFirst(a: number, this: C): number { return this.n; } ~~~~~~~ !!! error TS2679: 'this' parameter must be the first parameter. - ~ -!!! error TS2339: Property 'n' does not exist on type 'void'. ///// parse errors ///// function modifiers(async this: C): number { return this.n; } @@ -467,8 +388,6 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(197,35): e !!! error TS1003: Identifier expected. ~ !!! error TS1005: ',' expected. - ~ -!!! error TS2339: Property 'n' does not exist on type 'void'. function restParam(...this: C): number { return this.n; } ~~~~~~~ !!! error TS2370: A rest parameter must be of an array type. @@ -476,8 +395,6 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(197,35): e !!! error TS1003: Identifier expected. ~ !!! error TS1005: ',' expected. - ~ -!!! error TS2339: Property 'n' does not exist on type 'void'. function optional(this?: C): number { return this.n; } ~ !!! error TS1005: ',' expected. @@ -488,8 +405,6 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(197,35): e !!! error TS1003: Identifier expected. ~ !!! error TS1005: ',' expected. - ~ -!!! error TS2339: Property 'n' does not exist on type 'void'. function initializer(this: C = new C()): number { return this.n; } ~ !!! error TS1005: ',' expected. diff --git a/tests/baselines/reference/thisTypeInFunctionsNegative.js b/tests/baselines/reference/thisTypeInFunctionsNegative.js index c0892d9e4c835..8fa5aba6ad274 100644 --- a/tests/baselines/reference/thisTypeInFunctionsNegative.js +++ b/tests/baselines/reference/thisTypeInFunctionsNegative.js @@ -25,9 +25,6 @@ class D { explicitD(this: D, m: number): number { return this.x + m; } - implicitD(m: number): number { - return this.x + m; - } } interface I { a: number; @@ -36,8 +33,6 @@ interface I { explicitStructural(this: {a: number}): number; explicitInterface(this: I): number; explicitThis(this: this): number; // TODO: Allow `this` types for interfaces - implicitMethod(): number; - implicitFunction: () => number; } let impl: I = { a: 12, @@ -50,17 +45,11 @@ let impl: I = { explicitThis() { return this.a; }, - implicitMethod() { - return this.a; // ok, I.a: number - }, - implicitFunction: function () { return this.a; } // TODO: error 'a' not found in 'void' } let implExplicitStructural = impl.explicitStructural; implExplicitStructural(); // error, no 'a' in 'void' let implExplicitInterface = impl.explicitInterface; implExplicitInterface(); // error, no 'a' in 'void' -let implImplicitMethod = impl.implicitMethod; -implImplicitMethod(); // error, no 'a' in 'void' function explicitStructural(this: { y: number }, x: number): number { return x + this.y; } @@ -70,10 +59,6 @@ function propertyName(this: { y: number }, x: number): number { function voidThisSpecified(this: void, x: number): number { return x + this.notSpecified; } -function noThisSpecified(x: number): number { - // this:void unless loose-this is on - return x + this.notSpecified; -} let ok: {y: number, f: (this: { y: number }, x: number) => number} = { y: 12, explicitStructural }; let wrongPropertyType: {y: string, f: (this: { y: number }, x: number) => number} = { y: 'foo', explicitStructural }; let wrongPropertyName: {wrongName: number, f: (this: { y: number }, x: number) => number} = { wrongName: 12, explicitStructural }; @@ -99,19 +84,17 @@ c.explicitProperty('wrong type 3'); c.explicitProperty(15, 'too many arguments 3'); // oops, this triggers contextual typing, which needs to be updated to understand that =>'s `this` is void. -let specifiedToImplicitVoid: (x: number) => number = explicitStructural; +let specifiedToVoid: (this: void, x: number) => number = explicitStructural; let reconstructed: { n: number, explicitThis(this: C, m: number): number, // note: this: this is not allowed in an object literal type. - implicitThis(m: number): number, explicitC(this: C, m: number): number, explicitProperty: (this: {n : number}, m: number) => number, explicitVoid(this: void, m: number): number, } = { n: 12, explicitThis: c.explicitThis, - implicitThis: c.implicitThis, // error not assignable -- c.this:c not assignable to this:void. explicitC: c.explicitC, explicitProperty: c.explicitProperty, explicitVoid: c.explicitVoid @@ -125,26 +108,21 @@ let explicitXProperty: (this: { x: number }, m: number) => number; c.explicitC = function(this: D, m: number) { return this.x + m }; c.explicitProperty = explicitXProperty; -c.explicitC = d.implicitD; c.explicitC = d.explicitD; c.explicitC = d.explicitThis; -c.explicitThis = d.implicitD; c.explicitThis = d.explicitD; c.explicitThis = d.explicitThis; c.explicitProperty = d.explicitD; -c.explicitProperty = d.implicitD; c.explicitThis = d.explicitThis; -c.explicitVoid = d.implicitD; c.explicitVoid = d.explicitD; c.explicitVoid = d.explicitThis; -/// class-based implicit assignability (with inheritance!) /// +/// class-based polymorphic assignability (with inheritance!) /// class Base1 { x: number - public implicit(): number { return this.x; } + public polymorphic(this: this): number { return this.x; } explicit(this: Base1): number { return this.x; } - static implicitStatic(): number { return this.x; } static explicitStatic(this: typeof Base1): number { return this.x; } } class Derived1 extends Base1 { @@ -152,7 +130,7 @@ class Derived1 extends Base1 { } class Base2 { y: number - implicit(): number { return this.y; } + polymorphic(this: this): number { return this.y; } explicit(this: Base1): number { return this.x; } } class Derived2 extends Base2 { @@ -165,20 +143,16 @@ let d1 = new Derived1(); let b2 = new Base2(); let d2 = new Derived2(); -b1.implicit = b2.implicit // error, 'this.y' not in C: { x } (c assignable to e) -b1.explicit = b2.implicit // error, 'y' not in C: { x } (c assignable to e) +b1.polymorphic = b2.polymorphic // error, 'this.y' not in Base1: { x } +b1.explicit = b2.polymorphic // error, 'y' not in Base1: { x } -d1.explicit = b2.implicit // error, 'y' not in C: { x } (c assignable to e) +d1.explicit = b2.polymorphic // error, 'y' not in Base1: { x } ////// use this-type for construction with new //// function VoidThis(this: void) { -} -function ImplicitVoidThis() { - } let voidThis = new VoidThis(); -let implicitVoidThis = new ImplicitVoidThis(); ///// syntax-ish errors ///// class ThisConstructor { @@ -234,9 +208,6 @@ var D = (function () { D.prototype.explicitD = function (m) { return this.x + m; }; - D.prototype.implicitD = function (m) { - return this.x + m; - }; return D; }()); var impl = { @@ -249,18 +220,12 @@ var impl = { explicitInterface: function () { return 12; }, explicitThis: function () { return this.a; - }, - implicitMethod: function () { - return this.a; // ok, I.a: number - }, - implicitFunction: function () { return this.a; } // TODO: error 'a' not found in 'void' + } }; var implExplicitStructural = impl.explicitStructural; implExplicitStructural(); // error, no 'a' in 'void' var implExplicitInterface = impl.explicitInterface; implExplicitInterface(); // error, no 'a' in 'void' -var implImplicitMethod = impl.implicitMethod; -implImplicitMethod(); // error, no 'a' in 'void' function explicitStructural(x) { return x + this.y; } @@ -270,10 +235,6 @@ function propertyName(x) { function voidThisSpecified(x) { return x + this.notSpecified; } -function noThisSpecified(x) { - // this:void unless loose-this is on - return x + this.notSpecified; -} var ok = { y: 12, explicitStructural: explicitStructural }; var wrongPropertyType = { y: 'foo', explicitStructural: explicitStructural }; var wrongPropertyName = { wrongName: 12, explicitStructural: explicitStructural }; @@ -296,11 +257,10 @@ c.explicitProperty(); // not enough arguments c.explicitProperty('wrong type 3'); c.explicitProperty(15, 'too many arguments 3'); // oops, this triggers contextual typing, which needs to be updated to understand that =>'s `this` is void. -var specifiedToImplicitVoid = explicitStructural; +var specifiedToVoid = explicitStructural; var reconstructed = { n: 12, explicitThis: c.explicitThis, - implicitThis: c.implicitThis, explicitC: c.explicitC, explicitProperty: c.explicitProperty, explicitVoid: c.explicitVoid @@ -312,25 +272,20 @@ var explicitXProperty; // from differing object types c.explicitC = function (m) { return this.x + m; }; c.explicitProperty = explicitXProperty; -c.explicitC = d.implicitD; c.explicitC = d.explicitD; c.explicitC = d.explicitThis; -c.explicitThis = d.implicitD; c.explicitThis = d.explicitD; c.explicitThis = d.explicitThis; c.explicitProperty = d.explicitD; -c.explicitProperty = d.implicitD; c.explicitThis = d.explicitThis; -c.explicitVoid = d.implicitD; c.explicitVoid = d.explicitD; c.explicitVoid = d.explicitThis; -/// class-based implicit assignability (with inheritance!) /// +/// class-based polymorphic assignability (with inheritance!) /// var Base1 = (function () { function Base1() { } - Base1.prototype.implicit = function () { return this.x; }; + Base1.prototype.polymorphic = function () { return this.x; }; Base1.prototype.explicit = function () { return this.x; }; - Base1.implicitStatic = function () { return this.x; }; Base1.explicitStatic = function () { return this.x; }; return Base1; }()); @@ -344,7 +299,7 @@ var Derived1 = (function (_super) { var Base2 = (function () { function Base2() { } - Base2.prototype.implicit = function () { return this.y; }; + Base2.prototype.polymorphic = function () { return this.y; }; Base2.prototype.explicit = function () { return this.x; }; return Base2; }()); @@ -359,16 +314,13 @@ var b1 = new Base1(); var d1 = new Derived1(); var b2 = new Base2(); var d2 = new Derived2(); -b1.implicit = b2.implicit; // error, 'this.y' not in C: { x } (c assignable to e) -b1.explicit = b2.implicit; // error, 'y' not in C: { x } (c assignable to e) -d1.explicit = b2.implicit; // error, 'y' not in C: { x } (c assignable to e) +b1.polymorphic = b2.polymorphic; // error, 'this.y' not in Base1: { x } +b1.explicit = b2.polymorphic; // error, 'y' not in Base1: { x } +d1.explicit = b2.polymorphic; // error, 'y' not in Base1: { x } ////// use this-type for construction with new //// function VoidThis() { } -function ImplicitVoidThis() { -} var voidThis = new VoidThis(); -var implicitVoidThis = new ImplicitVoidThis(); ///// syntax-ish errors ///// var ThisConstructor = (function () { function ThisConstructor(n) { diff --git a/tests/baselines/reference/unionThisTypeInFunctions.js b/tests/baselines/reference/unionThisTypeInFunctions.js index 31ff266087b70..0d4b535ff8b62 100644 --- a/tests/baselines/reference/unionThisTypeInFunctions.js +++ b/tests/baselines/reference/unionThisTypeInFunctions.js @@ -1,10 +1,10 @@ //// [unionThisTypeInFunctions.ts] interface Real { - method(n: number): void; + method(this: this, n: number): void; data: string; } interface Fake { - method(n: number): void; + method(this: this, n: number): void; data: number; } function test(r: Real | Fake) { diff --git a/tests/baselines/reference/unionThisTypeInFunctions.symbols b/tests/baselines/reference/unionThisTypeInFunctions.symbols index 8b5f2af01e0ba..d18fb3475bbc8 100644 --- a/tests/baselines/reference/unionThisTypeInFunctions.symbols +++ b/tests/baselines/reference/unionThisTypeInFunctions.symbols @@ -2,22 +2,24 @@ interface Real { >Real : Symbol(Real, Decl(unionThisTypeInFunctions.ts, 0, 0)) - method(n: number): void; + method(this: this, n: number): void; >method : Symbol(method, Decl(unionThisTypeInFunctions.ts, 0, 16)) ->n : Symbol(n, Decl(unionThisTypeInFunctions.ts, 1, 11)) +>this : Symbol(this, Decl(unionThisTypeInFunctions.ts, 1, 11)) +>n : Symbol(n, Decl(unionThisTypeInFunctions.ts, 1, 22)) data: string; ->data : Symbol(data, Decl(unionThisTypeInFunctions.ts, 1, 28)) +>data : Symbol(data, Decl(unionThisTypeInFunctions.ts, 1, 40)) } interface Fake { >Fake : Symbol(Fake, Decl(unionThisTypeInFunctions.ts, 3, 1)) - method(n: number): void; + method(this: this, n: number): void; >method : Symbol(method, Decl(unionThisTypeInFunctions.ts, 4, 16)) ->n : Symbol(n, Decl(unionThisTypeInFunctions.ts, 5, 11)) +>this : Symbol(this, Decl(unionThisTypeInFunctions.ts, 5, 11)) +>n : Symbol(n, Decl(unionThisTypeInFunctions.ts, 5, 22)) data: number; ->data : Symbol(data, Decl(unionThisTypeInFunctions.ts, 5, 28)) +>data : Symbol(data, Decl(unionThisTypeInFunctions.ts, 5, 40)) } function test(r: Real | Fake) { >test : Symbol(test, Decl(unionThisTypeInFunctions.ts, 7, 1)) diff --git a/tests/baselines/reference/unionThisTypeInFunctions.types b/tests/baselines/reference/unionThisTypeInFunctions.types index f2c4f7ee4ec42..3c5181166b636 100644 --- a/tests/baselines/reference/unionThisTypeInFunctions.types +++ b/tests/baselines/reference/unionThisTypeInFunctions.types @@ -2,8 +2,9 @@ interface Real { >Real : Real - method(n: number): void; + method(this: this, n: number): void; >method : (this: this, n: number) => void +>this : this >n : number data: string; @@ -12,15 +13,16 @@ interface Real { interface Fake { >Fake : Fake - method(n: number): void; + method(this: this, n: number): void; >method : (this: this, n: number) => void +>this : this >n : number data: number; >data : number } function test(r: Real | Fake) { ->test : (this: void, r: Real | Fake) => void +>test : (r: Real | Fake) => void >r : Real | Fake >Real : Real >Fake : Fake diff --git a/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts b/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts index 3a1de178eea09..80f5fce9a9774 100644 --- a/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts +++ b/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts @@ -1,4 +1,3 @@ -// @strictThisChecks: true // body checking class B { n: number; @@ -8,9 +7,6 @@ class C { explicitThis(this: this, m: number): number { return this.n + m; } - implicitThis(m: number): number { - return this.n + m; - } explicitC(this: C, m: number): number { return this.n + m; } @@ -29,8 +25,6 @@ interface I { explicitStructural(this: {a: number}): number; explicitInterface(this: I): number; explicitThis(this: this): number; - implicitMethod(): number; - implicitFunction: () => number; } function explicitStructural(this: { y: number }, x: number): number { return x + this.y; @@ -39,7 +33,7 @@ function justThis(this: { y: number }): number { return this.y; } function implicitThis(n: number): number { - return 12; + return this.m + n + 12; } let impl: I = { a: 12, @@ -54,10 +48,6 @@ let impl: I = { explicitThis() { return this.a; }, - implicitMethod() { - return this.a; - }, - implicitFunction: () => this.a, // ok, this: any because it refers to some outer object (window?) } impl.explicitVoid1 = function () { return 12; }; impl.explicitVoid2 = () => 12; @@ -66,9 +56,6 @@ impl.explicitInterface = function() { return this.a; }; impl.explicitStructural = () => 12; impl.explicitInterface = () => 12; impl.explicitThis = function () { return this.a; }; -impl.implicitMethod = function () { return this.a; }; -impl.implicitMethod = () => 12; -impl.implicitFunction = () => this.a; // ok, this: any because it refers to some outer object (window?) // parameter checking let ok: {y: number, f: (this: { y: number }, x: number) => number} = { y: 12, f: explicitStructural }; let implicitAnyOk: {notSpecified: number, f: (x: number) => number} = { notSpecified: 12, f: implicitThis }; @@ -82,29 +69,26 @@ let ripped = c.explicitC; c.explicitC(12); c.explicitProperty(12); c.explicitThis(12); -c.implicitThis(12); d.explicitC(12); d.explicitProperty(12); d.explicitThis(12); -d.implicitThis(12); let reconstructed: { n: number, explicitThis(this: C, m: number): number, // note: this: this is not allowed in an object literal type. - implicitThis(m: number): number, explicitC(this: C, m: number): number, explicitProperty: (this: {n : number}, m: number) => number, explicitVoid(this: void, m: number): number, } = { n: 12, explicitThis: c.explicitThis, - implicitThis: c.implicitThis, explicitC: c.explicitC, explicitProperty: c.explicitProperty, explicitVoid: c.explicitVoid }; +reconstructed.explicitThis(10); reconstructed.explicitProperty(11); -reconstructed.implicitThis(11); - +let explicitVoid = reconstructed.explicitVoid; +explicitVoid(12); // assignment checking let unboundToSpecified: (this: { y: number }, x: number) => number = x => x + this.y; // ok, this:any let specifiedToSpecified: (this: {y: number}, x: number) => number = explicitStructural; @@ -143,8 +127,6 @@ c.explicitThis = function(this: C, 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 }; @@ -154,19 +136,17 @@ c.explicitVoid = n => n; // class-based assignability class Base1 { x: number; - public implicit(): number { return this.x; } + public polymorphic(this: this): number { return this.x; } explicit(this: Base1): number { return this.x; } - static implicitStatic(): number { return this.y; } static explicitStatic(this: typeof Base1): number { return this.y; } static y: number; - } class Derived1 extends Base1 { y: number } class Base2 { y: number - implicit(): number { return this.y; } + polymorphic(this: this): number { return this.y; } explicit(this: Base1): number { return this.x; } } class Derived2 extends Base2 { @@ -176,14 +156,14 @@ let b1 = new Base1(); let b2 = new Base2(); let d1 = new Derived1(); let d2 = new Derived2(); -d2.implicit = d1.implicit // ok, 'x' and 'y' in { x, y } (d assignable to f and vice versa) -d1.implicit = d2.implicit // ok, 'x' and 'y' in { x, y } (f assignable to d and vice versa) +d2.polymorphic = d1.polymorphic // ok, 'x' and 'y' in { x, y } +d1.polymorphic = d2.polymorphic // ok, 'x' and 'y' in { x, y } // bivariance-allowed cases -d1.implicit = b2.implicit // ok, 'y' in D: { x, y } (d assignable e) -d2.implicit = d1.explicit // ok, 'y' in { x, y } (c assignable to f) -b1.implicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) -b1.explicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) +d1.polymorphic = b2.polymorphic // ok, 'y' in D: { x, y } +d2.polymorphic = d1.explicit // ok, 'y' in { x, y } +b1.polymorphic = d2.polymorphic // ok, 'x' and 'y' not in Base1: { x } +b1.explicit = d2.polymorphic // ok, 'x' and 'y' not in Base1: { x } ////// use this-type for construction with new //// function InterfaceThis(this: I) { @@ -206,4 +186,4 @@ declare var f: { }; let n: number = f.call(12); -function missingTypeIsImplicitAny(this, a: number) { return a; } +function missingTypeIsImplicitAny(this, a: number) { return this.anything + a; } diff --git a/tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts b/tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts index bec0b9ab43454..394b186749086 100644 --- a/tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts +++ b/tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts @@ -1,4 +1,3 @@ -// @strictThisChecks: true class C { n: number; explicitThis(this: this, m: number): number { @@ -25,9 +24,6 @@ class D { explicitD(this: D, m: number): number { return this.x + m; } - implicitD(m: number): number { - return this.x + m; - } } interface I { a: number; @@ -36,8 +32,6 @@ interface I { explicitStructural(this: {a: number}): number; explicitInterface(this: I): number; explicitThis(this: this): number; // TODO: Allow `this` types for interfaces - implicitMethod(): number; - implicitFunction: () => number; } let impl: I = { a: 12, @@ -50,17 +44,11 @@ let impl: I = { explicitThis() { return this.a; }, - implicitMethod() { - return this.a; // ok, I.a: number - }, - implicitFunction: function () { return this.a; } // TODO: error 'a' not found in 'void' } let implExplicitStructural = impl.explicitStructural; implExplicitStructural(); // error, no 'a' in 'void' let implExplicitInterface = impl.explicitInterface; implExplicitInterface(); // error, no 'a' in 'void' -let implImplicitMethod = impl.implicitMethod; -implImplicitMethod(); // error, no 'a' in 'void' function explicitStructural(this: { y: number }, x: number): number { return x + this.y; } @@ -70,10 +58,6 @@ function propertyName(this: { y: number }, x: number): number { function voidThisSpecified(this: void, x: number): number { return x + this.notSpecified; } -function noThisSpecified(x: number): number { - // this:void unless loose-this is on - return x + this.notSpecified; -} let ok: {y: number, f: (this: { y: number }, x: number) => number} = { y: 12, explicitStructural }; let wrongPropertyType: {y: string, f: (this: { y: number }, x: number) => number} = { y: 'foo', explicitStructural }; let wrongPropertyName: {wrongName: number, f: (this: { y: number }, x: number) => number} = { wrongName: 12, explicitStructural }; @@ -99,19 +83,17 @@ c.explicitProperty('wrong type 3'); c.explicitProperty(15, 'too many arguments 3'); // oops, this triggers contextual typing, which needs to be updated to understand that =>'s `this` is void. -let specifiedToImplicitVoid: (x: number) => number = explicitStructural; +let specifiedToVoid: (this: void, x: number) => number = explicitStructural; let reconstructed: { n: number, explicitThis(this: C, m: number): number, // note: this: this is not allowed in an object literal type. - implicitThis(m: number): number, explicitC(this: C, m: number): number, explicitProperty: (this: {n : number}, m: number) => number, explicitVoid(this: void, m: number): number, } = { n: 12, explicitThis: c.explicitThis, - implicitThis: c.implicitThis, // error not assignable -- c.this:c not assignable to this:void. explicitC: c.explicitC, explicitProperty: c.explicitProperty, explicitVoid: c.explicitVoid @@ -125,26 +107,21 @@ let explicitXProperty: (this: { x: number }, m: number) => number; c.explicitC = function(this: D, m: number) { return this.x + m }; c.explicitProperty = explicitXProperty; -c.explicitC = d.implicitD; c.explicitC = d.explicitD; c.explicitC = d.explicitThis; -c.explicitThis = d.implicitD; c.explicitThis = d.explicitD; c.explicitThis = d.explicitThis; c.explicitProperty = d.explicitD; -c.explicitProperty = d.implicitD; c.explicitThis = d.explicitThis; -c.explicitVoid = d.implicitD; c.explicitVoid = d.explicitD; c.explicitVoid = d.explicitThis; -/// class-based implicit assignability (with inheritance!) /// +/// class-based polymorphic assignability (with inheritance!) /// class Base1 { x: number - public implicit(): number { return this.x; } + public polymorphic(this: this): number { return this.x; } explicit(this: Base1): number { return this.x; } - static implicitStatic(): number { return this.x; } static explicitStatic(this: typeof Base1): number { return this.x; } } class Derived1 extends Base1 { @@ -152,7 +129,7 @@ class Derived1 extends Base1 { } class Base2 { y: number - implicit(): number { return this.y; } + polymorphic(this: this): number { return this.y; } explicit(this: Base1): number { return this.x; } } class Derived2 extends Base2 { @@ -165,20 +142,16 @@ let d1 = new Derived1(); let b2 = new Base2(); let d2 = new Derived2(); -b1.implicit = b2.implicit // error, 'this.y' not in C: { x } (c assignable to e) -b1.explicit = b2.implicit // error, 'y' not in C: { x } (c assignable to e) +b1.polymorphic = b2.polymorphic // error, 'this.y' not in Base1: { x } +b1.explicit = b2.polymorphic // error, 'y' not in Base1: { x } -d1.explicit = b2.implicit // error, 'y' not in C: { x } (c assignable to e) +d1.explicit = b2.polymorphic // error, 'y' not in Base1: { x } ////// use this-type for construction with new //// function VoidThis(this: void) { -} -function ImplicitVoidThis() { - } let voidThis = new VoidThis(); -let implicitVoidThis = new ImplicitVoidThis(); ///// syntax-ish errors ///// class ThisConstructor { diff --git a/tests/cases/conformance/types/thisType/unionThisTypeInFunctions.ts b/tests/cases/conformance/types/thisType/unionThisTypeInFunctions.ts index c0a55f138ce0f..4f74058cc487d 100644 --- a/tests/cases/conformance/types/thisType/unionThisTypeInFunctions.ts +++ b/tests/cases/conformance/types/thisType/unionThisTypeInFunctions.ts @@ -1,10 +1,9 @@ -// @strictThisChecks: true interface Real { - method(n: number): void; + method(this: this, n: number): void; data: string; } interface Fake { - method(n: number): void; + method(this: this, n: number): void; data: number; } function test(r: Real | Fake) { diff --git a/tests/cases/fourslash/memberListOnExplicitThis.ts b/tests/cases/fourslash/memberListOnExplicitThis.ts index 207ec8796fab6..b776a7c06417e 100644 --- a/tests/cases/fourslash/memberListOnExplicitThis.ts +++ b/tests/cases/fourslash/memberListOnExplicitThis.ts @@ -1,4 +1,3 @@ -// @strictThisChecks: true /// ////interface Restricted { @@ -7,10 +6,10 @@ ////class C1 implements Restricted { //// n: number; //// m: number; -//// f() {this./*1*/} // test on 'this.' +//// f(this: this) {this./*1*/} // test on 'this.' //// g(this: Restricted) {this./*2*/} ////} -////function f() {this./*3*/} +////function f(this: void) {this./*3*/} ////function g(this: Restricted) {this./*4*/} goTo.marker('1'); diff --git a/tests/cases/fourslash/quickInfoOnThis.ts b/tests/cases/fourslash/quickInfoOnThis.ts index bfed13ea89c9f..91083d41e6b7c 100644 --- a/tests/cases/fourslash/quickInfoOnThis.ts +++ b/tests/cases/fourslash/quickInfoOnThis.ts @@ -1,4 +1,3 @@ -// @strictThisChecks: true /// ////interface Restricted { //// n: number; @@ -6,9 +5,9 @@ ////function wrapper(wrapped: { (): void; }) { } ////class Foo { //// n: number; -//// public implicitThis() { +//// public explicitThis(this: this) { //// wrapper( -//// function implicitVoid() { +//// function explicitVoid(this: void) { //// console.log(th/*1*/is); //// } //// ) @@ -22,15 +21,15 @@ //// } ////} ////class Bar { -//// public implicitThis() { +//// public explicitThis(this: this) { //// console.log(th/*7*/is); //// } -//// public explicitThis(this: Bar) { +//// public explicitClass(this: Bar) { //// console.log(thi/*8*/s); //// } ////} //// -////function implicitVoid(x: number): void { +////function implicitAny(x: number): void { //// return th/*9*/is; ////} ////function explicitVoid(th/*10*/is: void, x: number): void { @@ -75,7 +74,7 @@ verify.quickInfoIs('this: this'); goTo.marker('8'); verify.quickInfoIs('this: Bar'); goTo.marker('9'); -verify.quickInfoIs('void'); +verify.quickInfoIs('any'); goTo.marker('10'); verify.quickInfoIs('(parameter) this: void'); goTo.marker('11'); From a91cdccfc509e0878a8b8993e10aaa3a65246673 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 25 Mar 2016 16:37:28 -0700 Subject: [PATCH 30/41] 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 51fad3e7f3310..0f9287f9c5268 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 cf55f030c3382..363a3fdfc8f5c 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 5ea860f00af7a..53d0bcc07b8bc 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 5965a39a79ef7..e4c376b7b25be 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 0000000000000..b00949d50868f --- /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 0000000000000..e256df2d77fe3 --- /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 0000000000000..1e0aa0c4da003 --- /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; From f64110aa0f6f3ffced6142a6465d6038b128bfd9 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Mon, 28 Mar 2016 10:37:39 -0700 Subject: [PATCH 31/41] Update baselines after merging from master --- .../reference/thisTypeInFunctions.symbols | 60 +++++++++---------- .../unionThisTypeInFunctions.symbols | 8 +-- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/tests/baselines/reference/thisTypeInFunctions.symbols b/tests/baselines/reference/thisTypeInFunctions.symbols index 1d51f4aaca07a..0d7c82632063f 100644 --- a/tests/baselines/reference/thisTypeInFunctions.symbols +++ b/tests/baselines/reference/thisTypeInFunctions.symbols @@ -4,39 +4,39 @@ class B { >B : Symbol(B, Decl(thisTypeInFunctions.ts, 0, 0)) n: number; ->n : Symbol(n, Decl(thisTypeInFunctions.ts, 1, 9)) +>n : Symbol(B.n, Decl(thisTypeInFunctions.ts, 1, 9)) } class C { >C : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) n: number; ->n : Symbol(n, Decl(thisTypeInFunctions.ts, 4, 9)) +>n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 4, 9)) explicitThis(this: this, m: number): number { ->explicitThis : Symbol(explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) +>explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) >this : Symbol(this, Decl(thisTypeInFunctions.ts, 6, 17)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 6, 28)) return this.n + m; ->this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 4, 9)) +>this.n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 4, 9)) >this : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) ->n : Symbol(n, Decl(thisTypeInFunctions.ts, 4, 9)) +>n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 4, 9)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 6, 28)) } explicitC(this: C, m: number): number { ->explicitC : Symbol(explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) >this : Symbol(this, Decl(thisTypeInFunctions.ts, 9, 14)) >C : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 9, 22)) return this.n + m; ->this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 4, 9)) +>this.n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 4, 9)) >this : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) ->n : Symbol(n, Decl(thisTypeInFunctions.ts, 4, 9)) +>n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 4, 9)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 9, 22)) } explicitProperty(this: {n: number}, m: number): number { ->explicitProperty : Symbol(explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) >this : Symbol(this, Decl(thisTypeInFunctions.ts, 12, 21)) >n : Symbol(n, Decl(thisTypeInFunctions.ts, 12, 28)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 12, 39)) @@ -48,7 +48,7 @@ class C { >m : Symbol(m, Decl(thisTypeInFunctions.ts, 12, 39)) } explicitVoid(this: void, m: number): number { ->explicitVoid : Symbol(explicitVoid, Decl(thisTypeInFunctions.ts, 14, 5)) +>explicitVoid : Symbol(C.explicitVoid, Decl(thisTypeInFunctions.ts, 14, 5)) >this : Symbol(this, Decl(thisTypeInFunctions.ts, 15, 17)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 15, 28)) @@ -64,28 +64,28 @@ interface I { >I : Symbol(I, Decl(thisTypeInFunctions.ts, 19, 21)) a: number; ->a : Symbol(a, Decl(thisTypeInFunctions.ts, 20, 13)) +>a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 20, 13)) explicitVoid1(this: void): number; ->explicitVoid1 : Symbol(explicitVoid1, Decl(thisTypeInFunctions.ts, 21, 14)) +>explicitVoid1 : Symbol(I.explicitVoid1, Decl(thisTypeInFunctions.ts, 21, 14)) >this : Symbol(this, Decl(thisTypeInFunctions.ts, 22, 18)) explicitVoid2(this: void): number; ->explicitVoid2 : Symbol(explicitVoid2, Decl(thisTypeInFunctions.ts, 22, 38)) +>explicitVoid2 : Symbol(I.explicitVoid2, Decl(thisTypeInFunctions.ts, 22, 38)) >this : Symbol(this, Decl(thisTypeInFunctions.ts, 23, 18)) explicitStructural(this: {a: number}): number; ->explicitStructural : Symbol(explicitStructural, Decl(thisTypeInFunctions.ts, 23, 38)) +>explicitStructural : Symbol(I.explicitStructural, Decl(thisTypeInFunctions.ts, 23, 38)) >this : Symbol(this, Decl(thisTypeInFunctions.ts, 24, 23)) >a : Symbol(a, Decl(thisTypeInFunctions.ts, 24, 30)) explicitInterface(this: I): number; ->explicitInterface : Symbol(explicitInterface, Decl(thisTypeInFunctions.ts, 24, 50)) +>explicitInterface : Symbol(I.explicitInterface, Decl(thisTypeInFunctions.ts, 24, 50)) >this : Symbol(this, Decl(thisTypeInFunctions.ts, 25, 22)) >I : Symbol(I, Decl(thisTypeInFunctions.ts, 19, 21)) explicitThis(this: this): number; ->explicitThis : Symbol(explicitThis, Decl(thisTypeInFunctions.ts, 25, 39)) +>explicitThis : Symbol(I.explicitThis, Decl(thisTypeInFunctions.ts, 25, 39)) >this : Symbol(this, Decl(thisTypeInFunctions.ts, 26, 17)) } function explicitStructural(this: { y: number }, x: number): number { @@ -585,22 +585,22 @@ class Base1 { >Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 133, 24)) x: number; ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 136, 13)) +>x : Symbol(Base1.x, Decl(thisTypeInFunctions.ts, 136, 13)) public polymorphic(this: this): number { return this.x; } ->polymorphic : Symbol(polymorphic, Decl(thisTypeInFunctions.ts, 137, 14)) +>polymorphic : Symbol(Base1.polymorphic, Decl(thisTypeInFunctions.ts, 137, 14)) >this : Symbol(this, Decl(thisTypeInFunctions.ts, 138, 23)) ->this.x : Symbol(x, Decl(thisTypeInFunctions.ts, 136, 13)) +>this.x : Symbol(Base1.x, Decl(thisTypeInFunctions.ts, 136, 13)) >this : Symbol(Base1, Decl(thisTypeInFunctions.ts, 133, 24)) ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 136, 13)) +>x : Symbol(Base1.x, Decl(thisTypeInFunctions.ts, 136, 13)) explicit(this: Base1): number { return this.x; } ->explicit : Symbol(explicit, Decl(thisTypeInFunctions.ts, 138, 61)) +>explicit : Symbol(Base1.explicit, Decl(thisTypeInFunctions.ts, 138, 61)) >this : Symbol(this, Decl(thisTypeInFunctions.ts, 139, 13)) >Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 133, 24)) ->this.x : Symbol(x, Decl(thisTypeInFunctions.ts, 136, 13)) +>this.x : Symbol(Base1.x, Decl(thisTypeInFunctions.ts, 136, 13)) >this : Symbol(Base1, Decl(thisTypeInFunctions.ts, 133, 24)) ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 136, 13)) +>x : Symbol(Base1.x, Decl(thisTypeInFunctions.ts, 136, 13)) static explicitStatic(this: typeof Base1): number { return this.y; } >explicitStatic : Symbol(Base1.explicitStatic, Decl(thisTypeInFunctions.ts, 139, 52)) @@ -618,23 +618,23 @@ class Derived1 extends Base1 { >Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 133, 24)) y: number ->y : Symbol(y, Decl(thisTypeInFunctions.ts, 143, 30)) +>y : Symbol(Derived1.y, Decl(thisTypeInFunctions.ts, 143, 30)) } class Base2 { >Base2 : Symbol(Base2, Decl(thisTypeInFunctions.ts, 145, 1)) y: number ->y : Symbol(y, Decl(thisTypeInFunctions.ts, 146, 13)) +>y : Symbol(Base2.y, Decl(thisTypeInFunctions.ts, 146, 13)) polymorphic(this: this): number { return this.y; } ->polymorphic : Symbol(polymorphic, Decl(thisTypeInFunctions.ts, 147, 13)) +>polymorphic : Symbol(Base2.polymorphic, Decl(thisTypeInFunctions.ts, 147, 13)) >this : Symbol(this, Decl(thisTypeInFunctions.ts, 148, 16)) ->this.y : Symbol(y, Decl(thisTypeInFunctions.ts, 146, 13)) +>this.y : Symbol(Base2.y, Decl(thisTypeInFunctions.ts, 146, 13)) >this : Symbol(Base2, Decl(thisTypeInFunctions.ts, 145, 1)) ->y : Symbol(y, Decl(thisTypeInFunctions.ts, 146, 13)) +>y : Symbol(Base2.y, Decl(thisTypeInFunctions.ts, 146, 13)) explicit(this: Base1): number { return this.x; } ->explicit : Symbol(explicit, Decl(thisTypeInFunctions.ts, 148, 54)) +>explicit : Symbol(Base2.explicit, Decl(thisTypeInFunctions.ts, 148, 54)) >this : Symbol(this, Decl(thisTypeInFunctions.ts, 149, 13)) >Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 133, 24)) >this.x : Symbol(Base1.x, Decl(thisTypeInFunctions.ts, 136, 13)) @@ -646,7 +646,7 @@ class Derived2 extends Base2 { >Base2 : Symbol(Base2, Decl(thisTypeInFunctions.ts, 145, 1)) x: number ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 151, 30)) +>x : Symbol(Derived2.x, Decl(thisTypeInFunctions.ts, 151, 30)) } let b1 = new Base1(); >b1 : Symbol(b1, Decl(thisTypeInFunctions.ts, 154, 3)) diff --git a/tests/baselines/reference/unionThisTypeInFunctions.symbols b/tests/baselines/reference/unionThisTypeInFunctions.symbols index d18fb3475bbc8..eada12317504b 100644 --- a/tests/baselines/reference/unionThisTypeInFunctions.symbols +++ b/tests/baselines/reference/unionThisTypeInFunctions.symbols @@ -3,23 +3,23 @@ interface Real { >Real : Symbol(Real, Decl(unionThisTypeInFunctions.ts, 0, 0)) method(this: this, n: number): void; ->method : Symbol(method, Decl(unionThisTypeInFunctions.ts, 0, 16)) +>method : Symbol(Real.method, Decl(unionThisTypeInFunctions.ts, 0, 16)) >this : Symbol(this, Decl(unionThisTypeInFunctions.ts, 1, 11)) >n : Symbol(n, Decl(unionThisTypeInFunctions.ts, 1, 22)) data: string; ->data : Symbol(data, Decl(unionThisTypeInFunctions.ts, 1, 40)) +>data : Symbol(Real.data, Decl(unionThisTypeInFunctions.ts, 1, 40)) } interface Fake { >Fake : Symbol(Fake, Decl(unionThisTypeInFunctions.ts, 3, 1)) method(this: this, n: number): void; ->method : Symbol(method, Decl(unionThisTypeInFunctions.ts, 4, 16)) +>method : Symbol(Fake.method, Decl(unionThisTypeInFunctions.ts, 4, 16)) >this : Symbol(this, Decl(unionThisTypeInFunctions.ts, 5, 11)) >n : Symbol(n, Decl(unionThisTypeInFunctions.ts, 5, 22)) data: number; ->data : Symbol(data, Decl(unionThisTypeInFunctions.ts, 5, 40)) +>data : Symbol(Fake.data, Decl(unionThisTypeInFunctions.ts, 5, 40)) } function test(r: Real | Fake) { >test : Symbol(test, Decl(unionThisTypeInFunctions.ts, 7, 1)) From 0113ad525069ca77e69d7b98fd429e5a5f178d22 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 30 Mar 2016 13:31:10 -0700 Subject: [PATCH 32/41] Error on all uses of this that are implicitly any Previously it was only an error inside an function. --- src/compiler/checker.ts | 2 +- .../baselines/reference/noImplicitThisFunctions.errors.txt | 7 +++++-- tests/baselines/reference/noImplicitThisFunctions.js | 4 ++-- tests/cases/compiler/noImplicitThisFunctions.ts | 2 +- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 272dbb12b97c0..9a2a6e1f8e7e8 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8110,7 +8110,7 @@ namespace ts { } } - if (compilerOptions.noImplicitThis && isFunctionLike(container)) { + if (compilerOptions.noImplicitThis) { // 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); } diff --git a/tests/baselines/reference/noImplicitThisFunctions.errors.txt b/tests/baselines/reference/noImplicitThisFunctions.errors.txt index b00949d50868f..f1742bc758ae7 100644 --- a/tests/baselines/reference/noImplicitThisFunctions.errors.txt +++ b/tests/baselines/reference/noImplicitThisFunctions.errors.txt @@ -1,7 +1,8 @@ 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(18,38): error TS2681: 'this' implicitly has type 'any' because it does not have a type annotation. -==== tests/cases/compiler/noImplicitThisFunctions.ts (1 errors) ==== +==== tests/cases/compiler/noImplicitThisFunctions.ts (2 errors) ==== function f1(x) { // implicit any is still allowed @@ -20,6 +21,8 @@ tests/cases/compiler/noImplicitThisFunctions.ts(14,12): error TS2681: 'this' imp !!! 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` + // error: `this` is `window`, but is still of type `any` let f4: (b: number) => number = b => this.c + b; + ~~~~ +!!! error TS2681: 'this' implicitly has type 'any' because it does not have a type annotation. \ No newline at end of file diff --git a/tests/baselines/reference/noImplicitThisFunctions.js b/tests/baselines/reference/noImplicitThisFunctions.js index e256df2d77fe3..80ceccbe75176 100644 --- a/tests/baselines/reference/noImplicitThisFunctions.js +++ b/tests/baselines/reference/noImplicitThisFunctions.js @@ -15,7 +15,7 @@ function f3(z: number): number { return this.a + z; } -// ok, arrow functions don't even bind `this`, so `this` is just `window` +// error: `this` is `window`, but is still of type `any` let f4: (b: number) => number = b => this.c + b; @@ -33,5 +33,5 @@ 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` +// error: `this` is `window`, but is still of type `any` var f4 = function (b) { return _this.c + b; }; diff --git a/tests/cases/compiler/noImplicitThisFunctions.ts b/tests/cases/compiler/noImplicitThisFunctions.ts index 1e0aa0c4da003..45f0e5a1eb9ea 100644 --- a/tests/cases/compiler/noImplicitThisFunctions.ts +++ b/tests/cases/compiler/noImplicitThisFunctions.ts @@ -15,5 +15,5 @@ function f3(z: number): number { return this.a + z; } -// ok, arrow functions don't even bind `this`, so `this` is just `window` +// error: `this` is `window`, but is still of type `any` let f4: (b: number) => number = b => this.c + b; From e4ed7f904e43424ea9fac3e2e8f3ac6435949daf Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 30 Mar 2016 15:01:16 -0700 Subject: [PATCH 33/41] Address PR comments --- src/compiler/checker.ts | 28 +++++----- src/compiler/commandLineParser.ts | 1 + src/compiler/diagnosticMessages.json | 10 +++- .../noImplicitThisFunctions.errors.txt | 8 +-- .../thisTypeInFunctionsNegative.errors.txt | 53 +++++++++++-------- .../reference/thisTypeInFunctionsNegative.js | 11 ++++ .../thisType/thisTypeInFunctionsNegative.ts | 5 ++ 7 files changed, 76 insertions(+), 40 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9a2a6e1f8e7e8..e5a57cd96a9ee 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5379,11 +5379,8 @@ namespace ts { function isContextSensitiveFunctionLikeDeclaration(node: FunctionLikeDeclaration) { 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 && (node.parameters[0].name).text === "this" && node.parameters[0].type; - return !node.typeParameters && areAllParametersUntyped && !hasThisType; + const isNullaryArrow = node.kind === SyntaxKind.ArrowFunction && !node.parameters.length; + return !node.typeParameters && areAllParametersUntyped && !isNullaryArrow; } function getTypeWithoutSignatures(type: Type): Type { @@ -8072,20 +8069,20 @@ namespace ts { if (signature.thisType) { return signature.thisType; } + if (container.parent && container.parent.kind === SyntaxKind.ObjectLiteralExpression) { + // Note: this works because object literal methods are deferred, + // which means that the type of the containing object literal is already known. + const type = checkExpressionCached(container.parent); + if (type) { + return type; + } + } } if (isClassLike(container.parent)) { const symbol = getSymbolOfNode(container.parent); const type = container.flags & NodeFlags.Static ? getTypeOfSymbol(symbol) : (getDeclaredTypeOfSymbol(symbol)).thisType; return getNarrowedTypeOfReference(type, node); } - if (container.parent && container.parent.kind === SyntaxKind.ObjectLiteralExpression) { - // Note: this works because object literal methods are deferred, - // which means that the type of the containing object literal is already known. - const type = checkExpressionCached(container.parent); - if (type) { - return type; - } - } if (isInJavaScriptFile(node)) { const type = getTypeForThisExpressionFromJSDoc(container); @@ -12401,9 +12398,12 @@ namespace ts { if (indexOf(func.parameters, node) !== 0) { error(node, Diagnostics.this_parameter_must_be_the_first_parameter); } - if (func.kind === SyntaxKind.Constructor) { + if (func.kind === SyntaxKind.Constructor || func.kind === SyntaxKind.ConstructSignature) { error(node, Diagnostics.A_constructor_cannot_have_a_this_parameter); } + if (func.kind === SyntaxKind.SetAccessor) { + error(node, Diagnostics.A_setter_cannot_have_a_this_parameter); + } } // Only check rest parameter type if it's not a binding pattern. Since binding patterns are diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index e418a529386df..81d5d190fc7a0 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -125,6 +125,7 @@ namespace ts { { name: "noImplicitThis", type: "boolean", + description: Diagnostics.Raise_error_on_this_expressions_with_an_implied_any_type, }, { name: "noLib", diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index f0df9c4f9cb6f..0da7cb72932ec 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1887,10 +1887,14 @@ "category": "Error", "code": 2680 }, - "'this' implicitly has type 'any' because it does not have a type annotation.": { + "A setter cannot have a 'this' parameter.": { "category": "Error", "code": 2681 }, + "'this' implicitly has type 'any' because it does not have a type annotation.": { + "category": "Error", + "code": 2682 + }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", "code": 4000 @@ -2636,6 +2640,10 @@ "category": "Message", "code": 6113 }, + "Raise error on 'this' expressions with an implied 'any' type.": { + "category": "Message", + "code": 6114 + }, "Variable '{0}' implicitly has an '{1}' type.": { "category": "Error", diff --git a/tests/baselines/reference/noImplicitThisFunctions.errors.txt b/tests/baselines/reference/noImplicitThisFunctions.errors.txt index f1742bc758ae7..c80552c6b37e2 100644 --- a/tests/baselines/reference/noImplicitThisFunctions.errors.txt +++ b/tests/baselines/reference/noImplicitThisFunctions.errors.txt @@ -1,5 +1,5 @@ -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(18,38): error TS2681: 'this' implicitly has type 'any' because it does not have a type annotation. +tests/cases/compiler/noImplicitThisFunctions.ts(14,12): error TS2682: 'this' implicitly has type 'any' because it does not have a type annotation. +tests/cases/compiler/noImplicitThisFunctions.ts(18,38): error TS2682: 'this' implicitly has type 'any' because it does not have a type annotation. ==== tests/cases/compiler/noImplicitThisFunctions.ts (2 errors) ==== @@ -18,11 +18,11 @@ tests/cases/compiler/noImplicitThisFunctions.ts(18,38): error TS2681: 'this' imp // error: this is implicitly any return this.a + z; ~~~~ -!!! error TS2681: 'this' implicitly has type 'any' because it does not have a type annotation. +!!! error TS2682: 'this' implicitly has type 'any' because it does not have a type annotation. } // error: `this` is `window`, but is still of type `any` let f4: (b: number) => number = b => this.c + b; ~~~~ -!!! error TS2681: 'this' implicitly has type 'any' because it does not have a type annotation. +!!! error TS2682: 'this' implicitly has type 'any' because it does not have a type annotation. \ No newline at end of file diff --git a/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt b/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt index c888f4e5ecbc7..305208ac7d723 100644 --- a/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt +++ b/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt @@ -75,29 +75,31 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(146,1): er 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 TS2678: 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 TS2680: A constructor cannot have a 'this' parameter. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(161,30): error TS2679: 'this' parameter must be the first parameter. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(164,26): error TS1003: Identifier expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(164,30): error TS1005: ',' expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(165,20): error TS2370: A rest parameter must be of an array type. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(165,23): error TS1003: Identifier expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(165,27): error TS1005: ',' expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(166,23): error TS1005: ',' expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(166,24): error TS1138: Parameter declaration expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(167,28): error TS1003: Identifier expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(167,32): error TS1005: ',' expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(168,30): error TS1005: ',' expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(168,32): error TS1138: Parameter declaration expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(168,39): error TS1005: ';' expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(168,40): error TS1128: Declaration or statement expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(168,42): error TS2304: Cannot find name 'number'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(168,49): error TS1005: ';' expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(171,1): error TS7027: Unreachable code detected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(171,29): error TS2304: Cannot find name 'm'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(171,32): error TS1005: ';' expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(171,35): error TS2304: Cannot find name 'm'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(160,11): error TS2681: A setter cannot have a 'this' parameter. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(164,9): error TS2680: A constructor cannot have a 'this' parameter. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(166,30): error TS2679: 'this' parameter must be the first parameter. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(169,26): error TS1003: Identifier expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(169,30): error TS1005: ',' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(170,20): error TS2370: A rest parameter must be of an array type. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(170,23): error TS1003: Identifier expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(170,27): error TS1005: ',' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(171,23): error TS1005: ',' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(171,24): error TS1138: Parameter declaration expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(172,28): error TS1003: Identifier expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(172,32): error TS1005: ',' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(173,30): error TS1005: ',' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(173,32): error TS1138: Parameter declaration expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(173,39): error TS1005: ';' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(173,40): error TS1128: Declaration or statement expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(173,42): error TS2304: Cannot find name 'number'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(173,49): error TS1005: ';' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(176,1): error TS7027: Unreachable code detected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(176,29): error TS2304: Cannot find name 'm'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(176,32): error TS1005: ';' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(176,35): error TS2304: Cannot find name 'm'. -==== tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts (63 errors) ==== +==== tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts (65 errors) ==== class C { n: number; explicitThis(this: this, m: number): number { @@ -377,6 +379,15 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(171,35): e ~~~~~~~~~~~~~~~~~~~~~ !!! error TS2680: A constructor cannot have a 'this' parameter. } + set p(this: void) { + ~~~~~~~~~~ +!!! error TS2681: A setter cannot have a 'this' parameter. + } + } + interface ThisConstructorInterface { + new(this: ThisConstructor, n: number); + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2680: A constructor cannot have a 'this' parameter. } function notFirst(a: number, this: C): number { return this.n; } ~~~~~~~ diff --git a/tests/baselines/reference/thisTypeInFunctionsNegative.js b/tests/baselines/reference/thisTypeInFunctionsNegative.js index 8fa5aba6ad274..1cfb38bb100c1 100644 --- a/tests/baselines/reference/thisTypeInFunctionsNegative.js +++ b/tests/baselines/reference/thisTypeInFunctionsNegative.js @@ -158,6 +158,11 @@ let voidThis = new VoidThis(); class ThisConstructor { constructor(this: ThisConstructor, private n: number) { } + set p(this: void) { + } +} +interface ThisConstructorInterface { + new(this: ThisConstructor, n: number); } function notFirst(a: number, this: C): number { return this.n; } @@ -326,6 +331,12 @@ var ThisConstructor = (function () { function ThisConstructor(n) { this.n = n; } + Object.defineProperty(ThisConstructor.prototype, "p", { + set: function () { + }, + enumerable: true, + configurable: true + }); return ThisConstructor; }()); function notFirst(a, this) { return this.n; } diff --git a/tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts b/tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts index 394b186749086..1b049aeec5046 100644 --- a/tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts +++ b/tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts @@ -157,6 +157,11 @@ let voidThis = new VoidThis(); class ThisConstructor { constructor(this: ThisConstructor, private n: number) { } + set p(this: void) { + } +} +interface ThisConstructorInterface { + new(this: ThisConstructor, n: number); } function notFirst(a: number, this: C): number { return this.n; } From 0060b4d66332adb2fc5eb99b84f3e2095d176d58 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 31 Mar 2016 09:32:34 -0700 Subject: [PATCH 34/41] Test that signature help doesn't show 'this' --- tests/cases/fourslash/signatureHelpThis.ts | 43 ++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 tests/cases/fourslash/signatureHelpThis.ts diff --git a/tests/cases/fourslash/signatureHelpThis.ts b/tests/cases/fourslash/signatureHelpThis.ts new file mode 100644 index 0000000000000..2ac19c823c05a --- /dev/null +++ b/tests/cases/fourslash/signatureHelpThis.ts @@ -0,0 +1,43 @@ +/// +////class Foo { +//// public implicitAny(n: number) { +//// } +//// public explicitThis(this: this, n: number) { +//// console.log(this); +//// } +//// public explicitClass(this: Foo, n: number) { +//// console.log(this); +//// } +////} +//// +////function implicitAny(x: number): void { +//// return this; +////} +////function explicitVoid(this: void, x: number): void { +//// return this; +////} +////function explicitLiteral(this: { n: number }, x: number): void { +//// console.log(this); +////} +////let foo = new Foo(); +////foo.implicitAny(/*1*/); +////foo.explicitThis(/*2*/); +////foo.explicitClass(/*3*/); +////implicitAny(/*4*/12); +////explicitVoid(/*5*/13); +////let o = { n: 14, m: explicitLiteral }; +////o.m(/*6*/); + + +goTo.marker('1'); +verify.currentParameterHelpArgumentNameIs("n"); +goTo.marker('2'); +verify.currentParameterHelpArgumentNameIs("n"); +goTo.marker('3'); +verify.currentParameterHelpArgumentNameIs("n"); +goTo.marker('4'); +verify.currentParameterHelpArgumentNameIs("x"); +goTo.marker('5'); +verify.currentParameterHelpArgumentNameIs("x"); +goTo.marker('6'); +verify.currentParameterHelpArgumentNameIs("x"); From da982587032f50d9d4a6ca7e7969487690d3c395 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 31 Mar 2016 10:28:06 -0700 Subject: [PATCH 35/41] Improve error messages and code style --- src/compiler/checker.ts | 32 +++++++++---------- src/compiler/diagnosticMessages.json | 6 +++- .../looseThisTypeInFunctions.errors.txt | 4 +-- .../thisTypeInFunctionsNegative.errors.txt | 26 +++++++-------- 4 files changed, 35 insertions(+), 33 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e5a57cd96a9ee..4ce7f6cd0a8cd 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5465,21 +5465,17 @@ namespace ts { target = getErasedSignature(target); let result = Ternary.True; - if (source.thisType && target.thisType) { - if (source.thisType !== voidType) { - // void sources are assignable to anything. - let related = compareTypes(target.thisType, source.thisType, reportErrors); - if (!related) { - related = compareTypes(source.thisType, target.thisType, /*reportErrors*/ false); - if (!related) { - if (reportErrors) { - errorReporter(Diagnostics.Types_of_parameters_0_and_1_are_incompatible, "this", "this"); - } - return Ternary.False; - } + if (source.thisType && target.thisType && source.thisType !== voidType) { + // void sources are assignable to anything. + const related = compareTypes(source.thisType, target.thisType, /*reportErrors*/ false) + || compareTypes(target.thisType, source.thisType, reportErrors); + if (!related) { + if (reportErrors) { + errorReporter(Diagnostics.Types_of_parameters_0_and_1_are_incompatible, "this", "this"); } - result &= related; + return Ternary.False; } + result &= related; } const sourceMax = getNumNonRestParameters(source); @@ -10199,18 +10195,20 @@ namespace ts { } function checkApplicableSignature(node: CallLikeExpression, args: Expression[], signature: Signature, relation: Map, excludeArgument: boolean[], reportErrors: boolean) { - const headMessage = Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1; + if (signature.thisType && signature.thisType !== voidType && node.kind !== SyntaxKind.NewExpression) { - // If the source's this is not of the form `x.f` or `x[f]`, then sourceType = voidType - // If the target's this is voidType, then the check is skipped -- anything is compatible. + // If the called expression is not of the form `x.f` or `x["f"]`, then sourceType = voidType + // If the signature's 'this' type is voidType, then the check is skipped -- anything is compatible. // If the expression is a new expression, then the check is skipped. 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; if (!checkTypeRelatedTo(thisArgumentType, signature.thisType, relation, errorNode, headMessage)) { return false; } } + const headMessage = Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1; const argCount = getEffectiveArgumentCount(node, args, signature); for (let i = 0; i < argCount; i++) { const arg = getEffectiveArgument(node, args, i); @@ -12396,7 +12394,7 @@ namespace ts { } if ((node.name).text === "this") { if (indexOf(func.parameters, node) !== 0) { - error(node, Diagnostics.this_parameter_must_be_the_first_parameter); + error(node, Diagnostics.A_this_parameter_must_be_the_first_parameter); } if (func.kind === SyntaxKind.Constructor || func.kind === SyntaxKind.ConstructSignature) { error(node, Diagnostics.A_constructor_cannot_have_a_this_parameter); diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 0da7cb72932ec..1f282b10fd847 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1879,7 +1879,7 @@ "category": "Error", "code": 2678 }, - "'this' parameter must be the first parameter.": { + "A 'this' parameter must be the first parameter.": { "category": "Error", "code": 2679 }, @@ -1895,6 +1895,10 @@ "category": "Error", "code": 2682 }, + "'this' context of type '{0}' is not assignable to method 'this' of type '{1}'.": { + "category": "Error", + "code": 2683 + }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", "code": 4000 diff --git a/tests/baselines/reference/looseThisTypeInFunctions.errors.txt b/tests/baselines/reference/looseThisTypeInFunctions.errors.txt index caaf7afb09cab..4531797586cca 100644 --- a/tests/baselines/reference/looseThisTypeInFunctions.errors.txt +++ b/tests/baselines/reference/looseThisTypeInFunctions.errors.txt @@ -2,7 +2,7 @@ tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(21,1): error Types of parameters 'this' and 'this' 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 TS2345: Argument of type 'void' is not assignable to parameter of type 'I'. +tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(37,9): error TS2683: 'this' context of type 'void' is not assignable to method 'this' of type 'I'. tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(46,20): error TS2339: Property 'length' does not exist on type 'number'. @@ -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 TS2345: Argument of type 'void' is not assignable to parameter of type 'I'. +!!! error TS2683: 'this' context of type 'void' is not assignable to method 'this' of type 'I'. let u: Unused; let y = u.implicitNoThis; n = y(12); // ok, callee:void matches this:any diff --git a/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt b/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt index 305208ac7d723..3c25b31e0a8b5 100644 --- a/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt +++ b/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt @@ -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 TS2345: Argument of type 'void' is not assignable to parameter of type '{ a: number; }'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(51,1): error TS2345: Argument of type 'void' is not assignable to parameter of type 'I'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(49,1): error TS2683: '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 TS2683: 'this' context of type 'void' is not assignable to method '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 TS2345: Argument of type '{ y: string; f: (this: { y: number; }, x: number) => number; }' is not assignable to parameter of type '{ y: number; }'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(68,1): error TS2683: 'this' context of type '{ y: string; f: (this: { y: number; }, x: number) => number; }' is not assignable to method '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 TS2345: Argument of type '{ wrongName: number; f: (this: { y: number; }, x: number) => number; }' is not assignable to parameter of type '{ y: number; }'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(69,1): error TS2683: 'this' context of type '{ wrongName: number; f: (this: { y: number; }, x: number) => number; }' is not assignable to method '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'. @@ -77,7 +77,7 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(154,16): e tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(158,17): error TS2680: A constructor cannot have a 'this' parameter. tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(160,11): error TS2681: A setter cannot have a 'this' parameter. tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(164,9): error TS2680: A constructor cannot have a 'this' parameter. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(166,30): error TS2679: 'this' parameter must be the first parameter. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(166,30): error TS2679: A 'this' parameter must be the first parameter. tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(169,26): error TS1003: Identifier expected. tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(169,30): error TS1005: ',' expected. tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(170,20): error TS2370: A rest parameter must be of an array type. @@ -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 TS2345: Argument of type 'void' is not assignable to parameter of type '{ a: number; }'. +!!! error TS2683: 'this' context of type 'void' is not assignable to method 'this' of type '{ a: number; }'. let implExplicitInterface = impl.explicitInterface; implExplicitInterface(); // error, no 'a' in 'void' ~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2345: Argument of type 'void' is not assignable to parameter of type 'I'. +!!! error TS2683: 'this' context of type 'void' is not assignable to method 'this' of type 'I'. function explicitStructural(this: { y: number }, x: number): number { return x + this.y; } @@ -196,13 +196,13 @@ 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 TS2345: Argument of type '{ y: string; f: (this: { y: number; }, x: number) => number; }' is not assignable to parameter of type '{ y: number; }'. -!!! error TS2345: Types of property 'y' are incompatible. -!!! error TS2345: Type 'string' is not assignable to type 'number'. +!!! error TS2683: 'this' context of type '{ y: string; f: (this: { y: number; }, x: number) => number; }' is not assignable to method 'this' of type '{ y: number; }'. +!!! error TS2683: Types of property 'y' are incompatible. +!!! error TS2683: Type 'string' is not assignable to type 'number'. wrongPropertyName.f(13); ~~~~~~~~~~~~~~~~~ -!!! error TS2345: Argument of type '{ wrongName: number; f: (this: { y: number; }, x: number) => number; }' is not assignable to parameter of type '{ y: number; }'. -!!! error TS2345: Property 'y' is missing in type '{ wrongName: number; f: (this: { y: number; }, x: number) => number; }'. +!!! error TS2683: 'this' context of type '{ wrongName: number; f: (this: { y: number; }, x: number) => number; }' is not assignable to method 'this' of type '{ y: number; }'. +!!! error TS2683: Property 'y' is missing in type '{ wrongName: number; f: (this: { y: number; }, x: number) => number; }'. let c = new C(); c.explicitC(); // not enough arguments @@ -391,7 +391,7 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(176,35): e } function notFirst(a: number, this: C): number { return this.n; } ~~~~~~~ -!!! error TS2679: 'this' parameter must be the first parameter. +!!! error TS2679: A 'this' parameter must be the first parameter. ///// parse errors ///// function modifiers(async this: C): number { return this.n; } From 81f0d86634255f12bcff789047b546a0200399d2 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 31 Mar 2016 10:58:59 -0700 Subject: [PATCH 36/41] Fix up baselines and missing , after merge --- src/compiler/diagnosticMessages.json | 2 +- ...ArrowFunctionCapturesArguments_es6.symbols | 4 +- ...declarationEmitThisPredicates02.errors.txt | 4 +- ...ThisPredicatesWithPrivateName02.errors.txt | 4 +- .../looseThisTypeInFunctions.errors.txt | 4 +- .../noImplicitThisFunctions.errors.txt | 8 ++-- .../thisTypeInFunctionsNegative.errors.txt | 42 +++++++++---------- 7 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index c1910fa9e05da..1fa9151d50086 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2659,7 +2659,7 @@ "Raise error on 'this' expressions with an implied 'any' type.": { "category": "Message", "code": 6115 - } + }, "Variable '{0}' implicitly has an '{1}' type.": { "category": "Error", "code": 7005 diff --git a/tests/baselines/reference/asyncArrowFunctionCapturesArguments_es6.symbols b/tests/baselines/reference/asyncArrowFunctionCapturesArguments_es6.symbols index 4b312fd464633..06999513192ae 100644 --- a/tests/baselines/reference/asyncArrowFunctionCapturesArguments_es6.symbols +++ b/tests/baselines/reference/asyncArrowFunctionCapturesArguments_es6.symbols @@ -10,9 +10,9 @@ class C { var fn = async () => await other.apply(this, arguments); >fn : Symbol(fn, Decl(asyncArrowFunctionCapturesArguments_es6.ts, 3, 9)) ->other.apply : Symbol(Function.apply, Decl(lib.es5.d.ts, --, --)) +>other.apply : Symbol(Function.apply, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) >other : Symbol(other, Decl(asyncArrowFunctionCapturesArguments_es6.ts, 1, 13)) ->apply : Symbol(Function.apply, Decl(lib.es5.d.ts, --, --)) +>apply : Symbol(Function.apply, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) >this : Symbol(C, Decl(asyncArrowFunctionCapturesArguments_es6.ts, 0, 0)) >arguments : Symbol(arguments) } diff --git a/tests/baselines/reference/declarationEmitThisPredicates02.errors.txt b/tests/baselines/reference/declarationEmitThisPredicates02.errors.txt index 8cf85d4f7647d..d3597ad2507b5 100644 --- a/tests/baselines/reference/declarationEmitThisPredicates02.errors.txt +++ b/tests/baselines/reference/declarationEmitThisPredicates02.errors.txt @@ -1,5 +1,5 @@ tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicates02.ts(9,10): error TS2526: A 'this' type is available only in a non-static member of a class or interface. -tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicates02.ts(10,19): error TS2352: Neither type '{ m(): this is Foo; }' nor type 'Foo' is assignable to the other. +tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicates02.ts(10,19): error TS2352: Type '{ m(): this is Foo; }' cannot be converted to type 'Foo'. Property 'a' is missing in type '{ m(): this is Foo; }'. @@ -17,7 +17,7 @@ tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredic !!! error TS2526: A 'this' type is available only in a non-static member of a class or interface. let dis = this as Foo; ~~~~~~~~~~~ -!!! error TS2352: Neither type '{ m(): this is Foo; }' nor type 'Foo' is assignable to the other. +!!! error TS2352: Type '{ m(): this is Foo; }' cannot be converted to type 'Foo'. !!! error TS2352: Property 'a' is missing in type '{ m(): this is Foo; }'. return dis.a != null && dis.b != null && dis.c != null; } diff --git a/tests/baselines/reference/declarationEmitThisPredicatesWithPrivateName02.errors.txt b/tests/baselines/reference/declarationEmitThisPredicatesWithPrivateName02.errors.txt index 0c0661023f5df..7a4716a92e082 100644 --- a/tests/baselines/reference/declarationEmitThisPredicatesWithPrivateName02.errors.txt +++ b/tests/baselines/reference/declarationEmitThisPredicatesWithPrivateName02.errors.txt @@ -1,6 +1,6 @@ tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicatesWithPrivateName02.ts(8,14): error TS4025: Exported variable 'obj' has or is using private name 'Foo'. tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicatesWithPrivateName02.ts(9,10): error TS2526: A 'this' type is available only in a non-static member of a class or interface. -tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicatesWithPrivateName02.ts(10,19): error TS2352: Neither type '{ m(): this is Foo; }' nor type 'Foo' is assignable to the other. +tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicatesWithPrivateName02.ts(10,19): error TS2352: Type '{ m(): this is Foo; }' cannot be converted to type 'Foo'. Property 'a' is missing in type '{ m(): this is Foo; }'. @@ -20,7 +20,7 @@ tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredic !!! error TS2526: A 'this' type is available only in a non-static member of a class or interface. let dis = this as Foo; ~~~~~~~~~~~ -!!! error TS2352: Neither type '{ m(): this is Foo; }' nor type 'Foo' is assignable to the other. +!!! error TS2352: Type '{ m(): this is Foo; }' cannot be converted to type 'Foo'. !!! error TS2352: Property 'a' is missing in type '{ m(): this is Foo; }'. return dis.a != null && dis.b != null && dis.c != null; } diff --git a/tests/baselines/reference/looseThisTypeInFunctions.errors.txt b/tests/baselines/reference/looseThisTypeInFunctions.errors.txt index 4531797586cca..69e9493b24a91 100644 --- a/tests/baselines/reference/looseThisTypeInFunctions.errors.txt +++ b/tests/baselines/reference/looseThisTypeInFunctions.errors.txt @@ -2,7 +2,7 @@ tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(21,1): error Types of parameters 'this' and 'this' 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 TS2683: '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 'this' of type 'I'. tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(46,20): error TS2339: Property 'length' does not exist on type 'number'. @@ -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 TS2683: '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 'this' of type 'I'. let u: Unused; let y = u.implicitNoThis; n = y(12); // ok, callee:void matches this:any diff --git a/tests/baselines/reference/noImplicitThisFunctions.errors.txt b/tests/baselines/reference/noImplicitThisFunctions.errors.txt index c80552c6b37e2..5f66ac3553fac 100644 --- a/tests/baselines/reference/noImplicitThisFunctions.errors.txt +++ b/tests/baselines/reference/noImplicitThisFunctions.errors.txt @@ -1,5 +1,5 @@ -tests/cases/compiler/noImplicitThisFunctions.ts(14,12): error TS2682: 'this' implicitly has type 'any' because it does not have a type annotation. -tests/cases/compiler/noImplicitThisFunctions.ts(18,38): error TS2682: 'this' implicitly has type 'any' because it does not have a type annotation. +tests/cases/compiler/noImplicitThisFunctions.ts(14,12): error TS2683: 'this' implicitly has type 'any' because it does not have a type annotation. +tests/cases/compiler/noImplicitThisFunctions.ts(18,38): error TS2683: 'this' implicitly has type 'any' because it does not have a type annotation. ==== tests/cases/compiler/noImplicitThisFunctions.ts (2 errors) ==== @@ -18,11 +18,11 @@ tests/cases/compiler/noImplicitThisFunctions.ts(18,38): error TS2682: 'this' imp // error: this is implicitly any return this.a + z; ~~~~ -!!! error TS2682: 'this' implicitly has type 'any' because it does not have a type annotation. +!!! error TS2683: 'this' implicitly has type 'any' because it does not have a type annotation. } // error: `this` is `window`, but is still of type `any` let f4: (b: number) => number = b => this.c + b; ~~~~ -!!! error TS2682: 'this' implicitly has type 'any' because it does not have a type annotation. +!!! error TS2683: 'this' implicitly has type 'any' because it does not have a type annotation. \ No newline at end of file diff --git a/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt b/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt index 3c25b31e0a8b5..41711b526c70f 100644 --- a/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt +++ b/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt @@ -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 TS2683: '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 TS2683: '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 '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(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 TS2683: '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 '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 TS2683: '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 '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'. @@ -73,11 +73,11 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(146,1): er Types of parameters 'this' and 'this' 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 TS2678: 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 TS2680: A constructor cannot have a 'this' parameter. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(160,11): error TS2681: A setter cannot have a 'this' parameter. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(164,9): error TS2680: A constructor cannot have a 'this' parameter. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(166,30): error TS2679: A 'this' parameter must be the first parameter. +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. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(166,30): error TS2680: A 'this' parameter must be the first parameter. tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(169,26): error TS1003: Identifier expected. tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(169,30): error TS1005: ',' expected. tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(170,20): error TS2370: A rest parameter must be of an array type. @@ -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 TS2683: '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 'this' of type '{ a: number; }'. let implExplicitInterface = impl.explicitInterface; implExplicitInterface(); // error, no 'a' in 'void' ~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2683: '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 'this' of type 'I'. function explicitStructural(this: { y: number }, x: number): number { return x + this.y; } @@ -196,13 +196,13 @@ 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 TS2683: 'this' context of type '{ y: string; f: (this: { y: number; }, x: number) => number; }' is not assignable to method 'this' of type '{ y: number; }'. -!!! error TS2683: Types of property 'y' are incompatible. -!!! error TS2683: Type 'string' is not assignable to type 'number'. +!!! 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: Types of property 'y' are incompatible. +!!! error TS2684: Type 'string' is not assignable to type 'number'. wrongPropertyName.f(13); ~~~~~~~~~~~~~~~~~ -!!! error TS2683: 'this' context of type '{ wrongName: number; f: (this: { y: number; }, x: number) => number; }' is not assignable to method 'this' of type '{ y: number; }'. -!!! error TS2683: Property 'y' is missing in type '{ wrongName: number; f: (this: { y: number; }, x: number) => number; }'. +!!! 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: Property 'y' is missing in type '{ wrongName: number; f: (this: { y: number; }, x: number) => number; }'. let c = new C(); c.explicitC(); // not enough arguments @@ -371,27 +371,27 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(176,35): e } let voidThis = new VoidThis(); ~~~~~~~~~~~~~~ -!!! error TS2678: 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 { constructor(this: ThisConstructor, private n: number) { ~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2680: A constructor cannot have a 'this' parameter. +!!! error TS2681: A constructor cannot have a 'this' parameter. } set p(this: void) { ~~~~~~~~~~ -!!! error TS2681: A setter cannot have a 'this' parameter. +!!! error TS2682: A setter cannot have a 'this' parameter. } } interface ThisConstructorInterface { new(this: ThisConstructor, n: number); ~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2680: A constructor cannot have a 'this' parameter. +!!! error TS2681: A constructor cannot have a 'this' parameter. } function notFirst(a: number, this: C): number { return this.n; } ~~~~~~~ -!!! error TS2679: A 'this' parameter must be the first parameter. +!!! error TS2680: A 'this' parameter must be the first parameter. ///// parse errors ///// function modifiers(async this: C): number { return this.n; } From 4197a30f0caffaf8bfdd4c5f57cba12353417d0b Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 31 Mar 2016 14:32:56 -0700 Subject: [PATCH 37/41] 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. --- src/compiler/checker.ts | 10 +-- src/compiler/diagnosticMessages.json | 8 ++- .../looseThisTypeInFunctions.errors.txt | 8 +-- .../reference/thisTypeInFunctions.types | 8 +-- .../thisTypeInFunctionsNegative.errors.txt | 68 +++++++++---------- 5 files changed, 53 insertions(+), 49 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 45ec89086f62d..37f714a6e097e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -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; } } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 1fa9151d50086..fcca93b92dc57 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -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 diff --git a/tests/baselines/reference/looseThisTypeInFunctions.errors.txt b/tests/baselines/reference/looseThisTypeInFunctions.errors.txt index 69e9493b24a91..c290ad2d83356 100644 --- a/tests/baselines/reference/looseThisTypeInFunctions.errors.txt +++ b/tests/baselines/reference/looseThisTypeInFunctions.errors.txt @@ -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 diff --git a/tests/baselines/reference/thisTypeInFunctions.types b/tests/baselines/reference/thisTypeInFunctions.types index 48186eee2d067..24d3bf9f17865 100644 --- a/tests/baselines/reference/thisTypeInFunctions.types +++ b/tests/baselines/reference/thisTypeInFunctions.types @@ -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(); diff --git a/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt b/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt index 41711b526c70f..955469f9bf346 100644 --- a/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt +++ b/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt @@ -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 { From 9e5fba6036544f3bc22c85cc3b2edc47c9a63c98 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 1 Apr 2016 11:33:33 -0700 Subject: [PATCH 38/41] Prepend 'the' to a couple of ambiguous messages. Based on feedback from @DanielRosenwasser @Arnavion and @RichiCoder1 --- src/compiler/checker.ts | 4 +- src/compiler/diagnosticMessages.json | 4 +- .../looseThisTypeInFunctions.errors.txt | 8 +-- .../thisTypeInFunctionsNegative.errors.txt | 64 +++++++++---------- 4 files changed, 40 insertions(+), 40 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 37f714a6e097e..bbc22e1b88bac 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5480,7 +5480,7 @@ namespace ts { || compareTypes(target.thisType, source.thisType, reportErrors); if (!related) { if (reportErrors) { - errorReporter(Diagnostics.this_types_of_each_signature_are_incompatible); + errorReporter(Diagnostics.The_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_s_this_of_type_1; + const headMessage = Diagnostics.The_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; } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index fcca93b92dc57..6134f1e82b2d4 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1899,11 +1899,11 @@ "category": "Error", "code": 2683 }, - "'this' context of type '{0}' is not assignable to method's 'this' of type '{1}'.": { + "The '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.": { + "The 'this' types of each signature are incompatible.": { "category": "Error", "code": 2685 }, diff --git a/tests/baselines/reference/looseThisTypeInFunctions.errors.txt b/tests/baselines/reference/looseThisTypeInFunctions.errors.txt index c290ad2d83356..b7a36b99ad441 100644 --- a/tests/baselines/reference/looseThisTypeInFunctions.errors.txt +++ b/tests/baselines/reference/looseThisTypeInFunctions.errors.txt @@ -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'. - 'this' types of each signature are incompatible. + The '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's 'this' of type 'I'. +tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(37,9): error TS2684: The '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: 'this' types of each signature are incompatible. +!!! error TS2322: The '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's 'this' of type 'I'. +!!! error TS2684: The '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 diff --git a/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt b/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt index 955469f9bf346..e4891fe322def 100644 --- a/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt +++ b/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt @@ -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'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(49,1): error TS2684: The '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: The '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's 'this' of type '{ y: number; }'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(68,1): error TS2684: The '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's 'this' of type '{ y: number; }'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(69,1): error TS2684: The '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,46 +31,46 @@ 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'. - 'this' types of each signature are incompatible. + The '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'. - 'this' types of each signature are incompatible. + The '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'. - 'this' types of each signature are incompatible. + The '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'. - 'this' types of each signature are incompatible. + The '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'. - 'this' types of each signature are incompatible. + The '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'. - 'this' types of each signature are incompatible. + The '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'. - 'this' types of each signature are incompatible. + The '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'. - 'this' types of each signature are incompatible. + The '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'. - 'this' types of each signature are incompatible. + The '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'. - 'this' types of each signature are incompatible. + The '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'. - 'this' types of each signature are incompatible. + The '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'. - 'this' types of each signature are incompatible. + The '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'. @@ -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's 'this' of type '{ a: number; }'. +!!! error TS2684: The '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's 'this' of type 'I'. +!!! error TS2684: The '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's 'this' of type '{ y: number; }'. +!!! error TS2684: The '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's 'this' of type '{ y: number; }'. +!!! error TS2684: The '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: 'this' types of each signature are incompatible. +!!! error TS2322: The '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: 'this' types of each signature are incompatible. +!!! error TS2322: The '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: 'this' types of each signature are incompatible. +!!! error TS2322: The '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: 'this' types of each signature are incompatible. +!!! error TS2322: The '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: 'this' types of each signature are incompatible. +!!! error TS2322: The '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: 'this' types of each signature are incompatible. +!!! error TS2322: The '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: 'this' types of each signature are incompatible. +!!! error TS2322: The '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: 'this' types of each signature are incompatible. +!!! error TS2322: The '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: 'this' types of each signature are incompatible. +!!! error TS2322: The '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: 'this' types of each signature are incompatible. +!!! error TS2322: The '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: 'this' types of each signature are incompatible. +!!! error TS2322: The '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: 'this' types of each signature are incompatible. +!!! error TS2322: The '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 } From 2a9f39b1320849b84b869f3aad59fb278110cdaf Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 1 Apr 2016 13:06:55 -0700 Subject: [PATCH 39/41] Forbid ConstructType as part of 'no this in constructors' --- src/compiler/checker.ts | 2 +- .../thisTypeInFunctionsNegative.errors.txt | 46 ++++++++++--------- .../reference/thisTypeInFunctionsNegative.js | 2 + .../thisType/thisTypeInFunctionsNegative.ts | 1 + 4 files changed, 29 insertions(+), 22 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index bbc22e1b88bac..8178025c7ae6b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -12416,7 +12416,7 @@ namespace ts { if (indexOf(func.parameters, node) !== 0) { error(node, Diagnostics.A_this_parameter_must_be_the_first_parameter); } - if (func.kind === SyntaxKind.Constructor || func.kind === SyntaxKind.ConstructSignature) { + if (func.kind === SyntaxKind.Constructor || func.kind === SyntaxKind.ConstructSignature || func.kind === SyntaxKind.ConstructorType) { error(node, Diagnostics.A_constructor_cannot_have_a_this_parameter); } if (func.kind === SyntaxKind.SetAccessor) { diff --git a/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt b/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt index e4891fe322def..017550dcecd9d 100644 --- a/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt +++ b/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt @@ -77,29 +77,30 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(154,16): e 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. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(166,30): error TS2680: A 'this' parameter must be the first parameter. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(169,26): error TS1003: Identifier expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(169,30): error TS1005: ',' expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(170,20): error TS2370: A rest parameter must be of an array type. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(170,23): error TS1003: Identifier expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(170,27): error TS1005: ',' expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(171,23): error TS1005: ',' expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(171,24): error TS1138: Parameter declaration expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(172,28): error TS1003: Identifier expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(172,32): error TS1005: ',' expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(173,30): error TS1005: ',' expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(173,32): error TS1138: Parameter declaration expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(173,39): error TS1005: ';' expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(173,40): error TS1128: Declaration or statement expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(173,42): error TS2304: Cannot find name 'number'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(173,49): error TS1005: ';' expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(176,1): error TS7027: Unreachable code detected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(176,29): error TS2304: Cannot find name 'm'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(176,32): error TS1005: ';' expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(176,35): error TS2304: Cannot find name 'm'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(166,31): error TS2681: A constructor cannot have a 'this' parameter. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(167,30): error TS2680: A 'this' parameter must be the first parameter. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(170,26): error TS1003: Identifier expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(170,30): error TS1005: ',' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(171,20): error TS2370: A rest parameter must be of an array type. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(171,23): error TS1003: Identifier expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(171,27): error TS1005: ',' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(172,23): error TS1005: ',' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(172,24): error TS1138: Parameter declaration expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(173,28): error TS1003: Identifier expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(173,32): error TS1005: ',' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(174,30): error TS1005: ',' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(174,32): error TS1138: Parameter declaration expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(174,39): error TS1005: ';' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(174,40): error TS1128: Declaration or statement expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(174,42): error TS2304: Cannot find name 'number'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(174,49): error TS1005: ';' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(177,1): error TS7027: Unreachable code detected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(177,29): error TS2304: Cannot find name 'm'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(177,32): error TS1005: ';' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(177,35): error TS2304: Cannot find name 'm'. -==== tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts (65 errors) ==== +==== tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts (66 errors) ==== class C { n: number; explicitThis(this: this, m: number): number { @@ -389,6 +390,9 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(176,35): e ~~~~~~~~~~~~~~~~~~~~~ !!! error TS2681: A constructor cannot have a 'this' parameter. } + var thisConstructorType: new (this: number) => number; + ~~~~~~~~~~~~ +!!! error TS2681: A constructor cannot have a 'this' parameter. function notFirst(a: number, this: C): number { return this.n; } ~~~~~~~ !!! error TS2680: A 'this' parameter must be the first parameter. diff --git a/tests/baselines/reference/thisTypeInFunctionsNegative.js b/tests/baselines/reference/thisTypeInFunctionsNegative.js index 1cfb38bb100c1..124a7c8801329 100644 --- a/tests/baselines/reference/thisTypeInFunctionsNegative.js +++ b/tests/baselines/reference/thisTypeInFunctionsNegative.js @@ -164,6 +164,7 @@ class ThisConstructor { interface ThisConstructorInterface { new(this: ThisConstructor, n: number); } +var thisConstructorType: new (this: number) => number; function notFirst(a: number, this: C): number { return this.n; } ///// parse errors ///// @@ -339,6 +340,7 @@ var ThisConstructor = (function () { }); return ThisConstructor; }()); +var thisConstructorType; function notFirst(a, this) { return this.n; } ///// parse errors ///// function modifiers(, C) { diff --git a/tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts b/tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts index 1b049aeec5046..597fe5a836ed6 100644 --- a/tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts +++ b/tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts @@ -163,6 +163,7 @@ class ThisConstructor { interface ThisConstructorInterface { new(this: ThisConstructor, n: number); } +var thisConstructorType: new (this: number) => number; function notFirst(a: number, this: C): number { return this.n; } ///// parse errors ///// From 921d5f83e9b8cee0765cbccc4dd749df3335d376 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 1 Apr 2016 16:13:57 -0700 Subject: [PATCH 40/41] Fix == typo and add object literal 'this' test --- src/compiler/checker.ts | 2 +- .../reference/thisTypeInObjectLiterals.js | 40 +++++++++ .../thisTypeInObjectLiterals.symbols | 73 ++++++++++++++++ .../reference/thisTypeInObjectLiterals.types | 83 +++++++++++++++++++ .../thisType/thisTypeInObjectLiterals.ts | 23 +++++ 5 files changed, 220 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8178025c7ae6b..a357a2e0f71cb 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4252,7 +4252,7 @@ namespace ts { const resolvedSymbol = resolveName(param, paramSymbol.name, SymbolFlags.Value, undefined, undefined); paramSymbol = resolvedSymbol; } - if (i == 0 && paramSymbol.name === "this") { + if (i === 0 && paramSymbol.name === "this") { hasThisParameter = true; thisType = param.type ? getTypeFromTypeNode(param.type) : unknownType; } diff --git a/tests/baselines/reference/thisTypeInObjectLiterals.js b/tests/baselines/reference/thisTypeInObjectLiterals.js index 78854bf2388b3..5af13a41af858 100644 --- a/tests/baselines/reference/thisTypeInObjectLiterals.js +++ b/tests/baselines/reference/thisTypeInObjectLiterals.js @@ -5,6 +5,29 @@ let o = { return this.d.length; } } +let mutuallyRecursive = { + a: 100, + start() { + return this.passthrough(this.a); + }, + passthrough(n: number) { + return this.sub1(n); + }, + sub1(n: number): number { + if (n > 0) { + return this.passthrough(n - 1); + } + return n; + } +} +var i: number = mutuallyRecursive.start(); +interface I { + a: number; + start(): number; + passthrough(n: number): number; + sub1(n: number): number; +} +var impl: I = mutuallyRecursive; //// [thisTypeInObjectLiterals.js] @@ -14,3 +37,20 @@ var o = { return this.d.length; } }; +var mutuallyRecursive = { + a: 100, + start: function () { + return this.passthrough(this.a); + }, + passthrough: function (n) { + return this.sub1(n); + }, + sub1: function (n) { + if (n > 0) { + return this.passthrough(n - 1); + } + return n; + } +}; +var i = mutuallyRecursive.start(); +var impl = mutuallyRecursive; diff --git a/tests/baselines/reference/thisTypeInObjectLiterals.symbols b/tests/baselines/reference/thisTypeInObjectLiterals.symbols index 6bea6d88c5830..9ae4a990d5b84 100644 --- a/tests/baselines/reference/thisTypeInObjectLiterals.symbols +++ b/tests/baselines/reference/thisTypeInObjectLiterals.symbols @@ -16,4 +16,77 @@ let o = { >length : Symbol(String.length, Decl(lib.d.ts, --, --)) } } +let mutuallyRecursive = { +>mutuallyRecursive : Symbol(mutuallyRecursive, Decl(thisTypeInObjectLiterals.ts, 6, 3)) + + a: 100, +>a : Symbol(a, Decl(thisTypeInObjectLiterals.ts, 6, 25)) + + start() { +>start : Symbol(start, Decl(thisTypeInObjectLiterals.ts, 7, 11)) + + return this.passthrough(this.a); +>this.passthrough : Symbol(passthrough, Decl(thisTypeInObjectLiterals.ts, 10, 6)) +>this : Symbol(, Decl(thisTypeInObjectLiterals.ts, 6, 23)) +>passthrough : Symbol(passthrough, Decl(thisTypeInObjectLiterals.ts, 10, 6)) +>this.a : Symbol(a, Decl(thisTypeInObjectLiterals.ts, 6, 25)) +>this : Symbol(, Decl(thisTypeInObjectLiterals.ts, 6, 23)) +>a : Symbol(a, Decl(thisTypeInObjectLiterals.ts, 6, 25)) + + }, + passthrough(n: number) { +>passthrough : Symbol(passthrough, Decl(thisTypeInObjectLiterals.ts, 10, 6)) +>n : Symbol(n, Decl(thisTypeInObjectLiterals.ts, 11, 16)) + + return this.sub1(n); +>this.sub1 : Symbol(sub1, Decl(thisTypeInObjectLiterals.ts, 13, 6)) +>this : Symbol(, Decl(thisTypeInObjectLiterals.ts, 6, 23)) +>sub1 : Symbol(sub1, Decl(thisTypeInObjectLiterals.ts, 13, 6)) +>n : Symbol(n, Decl(thisTypeInObjectLiterals.ts, 11, 16)) + + }, + sub1(n: number): number { +>sub1 : Symbol(sub1, Decl(thisTypeInObjectLiterals.ts, 13, 6)) +>n : Symbol(n, Decl(thisTypeInObjectLiterals.ts, 14, 9)) + + if (n > 0) { +>n : Symbol(n, Decl(thisTypeInObjectLiterals.ts, 14, 9)) + + return this.passthrough(n - 1); +>this.passthrough : Symbol(passthrough, Decl(thisTypeInObjectLiterals.ts, 10, 6)) +>this : Symbol(, Decl(thisTypeInObjectLiterals.ts, 6, 23)) +>passthrough : Symbol(passthrough, Decl(thisTypeInObjectLiterals.ts, 10, 6)) +>n : Symbol(n, Decl(thisTypeInObjectLiterals.ts, 14, 9)) + } + return n; +>n : Symbol(n, Decl(thisTypeInObjectLiterals.ts, 14, 9)) + } +} +var i: number = mutuallyRecursive.start(); +>i : Symbol(i, Decl(thisTypeInObjectLiterals.ts, 21, 3)) +>mutuallyRecursive.start : Symbol(start, Decl(thisTypeInObjectLiterals.ts, 7, 11)) +>mutuallyRecursive : Symbol(mutuallyRecursive, Decl(thisTypeInObjectLiterals.ts, 6, 3)) +>start : Symbol(start, Decl(thisTypeInObjectLiterals.ts, 7, 11)) + +interface I { +>I : Symbol(I, Decl(thisTypeInObjectLiterals.ts, 21, 42)) + + a: number; +>a : Symbol(I.a, Decl(thisTypeInObjectLiterals.ts, 22, 13)) + + start(): number; +>start : Symbol(I.start, Decl(thisTypeInObjectLiterals.ts, 23, 14)) + + passthrough(n: number): number; +>passthrough : Symbol(I.passthrough, Decl(thisTypeInObjectLiterals.ts, 24, 20)) +>n : Symbol(n, Decl(thisTypeInObjectLiterals.ts, 25, 16)) + + sub1(n: number): number; +>sub1 : Symbol(I.sub1, Decl(thisTypeInObjectLiterals.ts, 25, 35)) +>n : Symbol(n, Decl(thisTypeInObjectLiterals.ts, 26, 9)) +} +var impl: I = mutuallyRecursive; +>impl : Symbol(impl, Decl(thisTypeInObjectLiterals.ts, 28, 3)) +>I : Symbol(I, Decl(thisTypeInObjectLiterals.ts, 21, 42)) +>mutuallyRecursive : Symbol(mutuallyRecursive, Decl(thisTypeInObjectLiterals.ts, 6, 3)) diff --git a/tests/baselines/reference/thisTypeInObjectLiterals.types b/tests/baselines/reference/thisTypeInObjectLiterals.types index 824b0b00f4ca1..0b1642092198d 100644 --- a/tests/baselines/reference/thisTypeInObjectLiterals.types +++ b/tests/baselines/reference/thisTypeInObjectLiterals.types @@ -18,4 +18,87 @@ let o = { >length : number } } +let mutuallyRecursive = { +>mutuallyRecursive : { a: number; start(): number; passthrough(n: number): number; sub1(n: number): number; } +>{ a: 100, start() { return this.passthrough(this.a); }, passthrough(n: number) { return this.sub1(n); }, sub1(n: number): number { if (n > 0) { return this.passthrough(n - 1); } return n; }} : { a: number; start(): number; passthrough(n: number): number; sub1(n: number): number; } + + a: 100, +>a : number +>100 : number + + start() { +>start : () => number + + return this.passthrough(this.a); +>this.passthrough(this.a) : number +>this.passthrough : (n: number) => number +>this : { a: number; start(): number; passthrough(n: number): number; sub1(n: number): number; } +>passthrough : (n: number) => number +>this.a : number +>this : { a: number; start(): number; passthrough(n: number): number; sub1(n: number): number; } +>a : number + + }, + passthrough(n: number) { +>passthrough : (n: number) => number +>n : number + + return this.sub1(n); +>this.sub1(n) : number +>this.sub1 : (n: number) => number +>this : { a: number; start(): number; passthrough(n: number): number; sub1(n: number): number; } +>sub1 : (n: number) => number +>n : number + + }, + sub1(n: number): number { +>sub1 : (n: number) => number +>n : number + + if (n > 0) { +>n > 0 : boolean +>n : number +>0 : number + + return this.passthrough(n - 1); +>this.passthrough(n - 1) : number +>this.passthrough : (n: number) => number +>this : { a: number; start(): number; passthrough(n: number): number; sub1(n: number): number; } +>passthrough : (n: number) => number +>n - 1 : number +>n : number +>1 : number + } + return n; +>n : number + } +} +var i: number = mutuallyRecursive.start(); +>i : number +>mutuallyRecursive.start() : number +>mutuallyRecursive.start : () => number +>mutuallyRecursive : { a: number; start(): number; passthrough(n: number): number; sub1(n: number): number; } +>start : () => number + +interface I { +>I : I + + a: number; +>a : number + + start(): number; +>start : () => number + + passthrough(n: number): number; +>passthrough : (n: number) => number +>n : number + + sub1(n: number): number; +>sub1 : (n: number) => number +>n : number +} +var impl: I = mutuallyRecursive; +>impl : I +>I : I +>mutuallyRecursive : { a: number; start(): number; passthrough(n: number): number; sub1(n: number): number; } diff --git a/tests/cases/conformance/types/thisType/thisTypeInObjectLiterals.ts b/tests/cases/conformance/types/thisType/thisTypeInObjectLiterals.ts index 11c6b58d7104d..cfdb0883fed02 100644 --- a/tests/cases/conformance/types/thisType/thisTypeInObjectLiterals.ts +++ b/tests/cases/conformance/types/thisType/thisTypeInObjectLiterals.ts @@ -4,3 +4,26 @@ let o = { return this.d.length; } } +let mutuallyRecursive = { + a: 100, + start() { + return this.passthrough(this.a); + }, + passthrough(n: number) { + return this.sub1(n); + }, + sub1(n: number): number { + if (n > 0) { + return this.passthrough(n - 1); + } + return n; + } +} +var i: number = mutuallyRecursive.start(); +interface I { + a: number; + start(): number; + passthrough(n: number): number; + sub1(n: number): number; +} +var impl: I = mutuallyRecursive; From 6c735b5cbf889cc703ed6d415d0af972439ddbbf Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 7 Apr 2016 07:59:46 -0700 Subject: [PATCH 41/41] Add contextual typing test with `this` specified --- .../reference/thisTypeInFunctions.js | 7 + .../reference/thisTypeInFunctions.symbols | 257 +++++++++--------- .../reference/thisTypeInFunctions.types | 16 ++ .../types/thisType/thisTypeInFunctions.ts | 4 + 4 files changed, 162 insertions(+), 122 deletions(-) diff --git a/tests/baselines/reference/thisTypeInFunctions.js b/tests/baselines/reference/thisTypeInFunctions.js index 74eba32082b72..cfe1706ae99db 100644 --- a/tests/baselines/reference/thisTypeInFunctions.js +++ b/tests/baselines/reference/thisTypeInFunctions.js @@ -129,6 +129,10 @@ c.explicitC = function(m) { return this.n + m }; c.explicitProperty = function(m) { return this.n + m }; c.explicitThis = function(m) { return this.n + m }; +// this: contextual typing +c.explicitThis = function(this, m) { return this.n + m }; + +// this: superclass compatibility c.explicitC = function(this: B, m: number) { return this.n + m }; // this:void compatibility @@ -314,6 +318,9 @@ c.explicitThis = function (m) { 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; }; +// this: contextual typing +c.explicitThis = function (m) { return this.n + m; }; +// this: superclass compatibility c.explicitC = function (m) { return this.n + m; }; // this:void compatibility c.explicitVoid = function (n) { return n; }; diff --git a/tests/baselines/reference/thisTypeInFunctions.symbols b/tests/baselines/reference/thisTypeInFunctions.symbols index 0d7c82632063f..3d4c3f6ecc70f 100644 --- a/tests/baselines/reference/thisTypeInFunctions.symbols +++ b/tests/baselines/reference/thisTypeInFunctions.symbols @@ -560,163 +560,176 @@ c.explicitThis = function(m) { return this.n + m }; >n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 4, 9)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 128, 26)) +// this: contextual typing +c.explicitThis = function(this, m) { return this.n + m }; +>c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 65, 3)) +>explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 131, 26)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 131, 31)) +>this.n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 4, 9)) +>this : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) +>n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 4, 9)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 131, 31)) + +// this: superclass compatibility c.explicitC = function(this: B, m: number) { return this.n + m }; >c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 65, 3)) >explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 130, 23)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 134, 23)) >B : Symbol(B, Decl(thisTypeInFunctions.ts, 0, 0)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 130, 31)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 134, 31)) >this.n : Symbol(B.n, Decl(thisTypeInFunctions.ts, 1, 9)) >this : Symbol(B, Decl(thisTypeInFunctions.ts, 0, 0)) >n : Symbol(B.n, Decl(thisTypeInFunctions.ts, 1, 9)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 130, 31)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 134, 31)) // this:void compatibility c.explicitVoid = n => n; >c.explicitVoid : Symbol(C.explicitVoid, Decl(thisTypeInFunctions.ts, 14, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 65, 3)) >explicitVoid : Symbol(C.explicitVoid, Decl(thisTypeInFunctions.ts, 14, 5)) ->n : Symbol(n, Decl(thisTypeInFunctions.ts, 133, 16)) ->n : Symbol(n, Decl(thisTypeInFunctions.ts, 133, 16)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 137, 16)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 137, 16)) // class-based assignability class Base1 { ->Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 133, 24)) +>Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 137, 24)) x: number; ->x : Symbol(Base1.x, Decl(thisTypeInFunctions.ts, 136, 13)) +>x : Symbol(Base1.x, Decl(thisTypeInFunctions.ts, 140, 13)) public polymorphic(this: this): number { return this.x; } ->polymorphic : Symbol(Base1.polymorphic, Decl(thisTypeInFunctions.ts, 137, 14)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 138, 23)) ->this.x : Symbol(Base1.x, Decl(thisTypeInFunctions.ts, 136, 13)) ->this : Symbol(Base1, Decl(thisTypeInFunctions.ts, 133, 24)) ->x : Symbol(Base1.x, Decl(thisTypeInFunctions.ts, 136, 13)) +>polymorphic : Symbol(Base1.polymorphic, Decl(thisTypeInFunctions.ts, 141, 14)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 142, 23)) +>this.x : Symbol(Base1.x, Decl(thisTypeInFunctions.ts, 140, 13)) +>this : Symbol(Base1, Decl(thisTypeInFunctions.ts, 137, 24)) +>x : Symbol(Base1.x, Decl(thisTypeInFunctions.ts, 140, 13)) explicit(this: Base1): number { return this.x; } ->explicit : Symbol(Base1.explicit, Decl(thisTypeInFunctions.ts, 138, 61)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 139, 13)) ->Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 133, 24)) ->this.x : Symbol(Base1.x, Decl(thisTypeInFunctions.ts, 136, 13)) ->this : Symbol(Base1, Decl(thisTypeInFunctions.ts, 133, 24)) ->x : Symbol(Base1.x, Decl(thisTypeInFunctions.ts, 136, 13)) +>explicit : Symbol(Base1.explicit, Decl(thisTypeInFunctions.ts, 142, 61)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 143, 13)) +>Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 137, 24)) +>this.x : Symbol(Base1.x, Decl(thisTypeInFunctions.ts, 140, 13)) +>this : Symbol(Base1, Decl(thisTypeInFunctions.ts, 137, 24)) +>x : Symbol(Base1.x, Decl(thisTypeInFunctions.ts, 140, 13)) static explicitStatic(this: typeof Base1): number { return this.y; } ->explicitStatic : Symbol(Base1.explicitStatic, Decl(thisTypeInFunctions.ts, 139, 52)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 140, 26)) ->Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 133, 24)) ->this.y : Symbol(Base1.y, Decl(thisTypeInFunctions.ts, 140, 72)) ->this : Symbol(Base1, Decl(thisTypeInFunctions.ts, 133, 24)) ->y : Symbol(Base1.y, Decl(thisTypeInFunctions.ts, 140, 72)) +>explicitStatic : Symbol(Base1.explicitStatic, Decl(thisTypeInFunctions.ts, 143, 52)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 144, 26)) +>Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 137, 24)) +>this.y : Symbol(Base1.y, Decl(thisTypeInFunctions.ts, 144, 72)) +>this : Symbol(Base1, Decl(thisTypeInFunctions.ts, 137, 24)) +>y : Symbol(Base1.y, Decl(thisTypeInFunctions.ts, 144, 72)) static y: number; ->y : Symbol(Base1.y, Decl(thisTypeInFunctions.ts, 140, 72)) +>y : Symbol(Base1.y, Decl(thisTypeInFunctions.ts, 144, 72)) } class Derived1 extends Base1 { ->Derived1 : Symbol(Derived1, Decl(thisTypeInFunctions.ts, 142, 1)) ->Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 133, 24)) +>Derived1 : Symbol(Derived1, Decl(thisTypeInFunctions.ts, 146, 1)) +>Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 137, 24)) y: number ->y : Symbol(Derived1.y, Decl(thisTypeInFunctions.ts, 143, 30)) +>y : Symbol(Derived1.y, Decl(thisTypeInFunctions.ts, 147, 30)) } class Base2 { ->Base2 : Symbol(Base2, Decl(thisTypeInFunctions.ts, 145, 1)) +>Base2 : Symbol(Base2, Decl(thisTypeInFunctions.ts, 149, 1)) y: number ->y : Symbol(Base2.y, Decl(thisTypeInFunctions.ts, 146, 13)) +>y : Symbol(Base2.y, Decl(thisTypeInFunctions.ts, 150, 13)) polymorphic(this: this): number { return this.y; } ->polymorphic : Symbol(Base2.polymorphic, Decl(thisTypeInFunctions.ts, 147, 13)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 148, 16)) ->this.y : Symbol(Base2.y, Decl(thisTypeInFunctions.ts, 146, 13)) ->this : Symbol(Base2, Decl(thisTypeInFunctions.ts, 145, 1)) ->y : Symbol(Base2.y, Decl(thisTypeInFunctions.ts, 146, 13)) +>polymorphic : Symbol(Base2.polymorphic, Decl(thisTypeInFunctions.ts, 151, 13)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 152, 16)) +>this.y : Symbol(Base2.y, Decl(thisTypeInFunctions.ts, 150, 13)) +>this : Symbol(Base2, Decl(thisTypeInFunctions.ts, 149, 1)) +>y : Symbol(Base2.y, Decl(thisTypeInFunctions.ts, 150, 13)) explicit(this: Base1): number { return this.x; } ->explicit : Symbol(Base2.explicit, Decl(thisTypeInFunctions.ts, 148, 54)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 149, 13)) ->Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 133, 24)) ->this.x : Symbol(Base1.x, Decl(thisTypeInFunctions.ts, 136, 13)) ->this : Symbol(Base1, Decl(thisTypeInFunctions.ts, 133, 24)) ->x : Symbol(Base1.x, Decl(thisTypeInFunctions.ts, 136, 13)) +>explicit : Symbol(Base2.explicit, Decl(thisTypeInFunctions.ts, 152, 54)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 153, 13)) +>Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 137, 24)) +>this.x : Symbol(Base1.x, Decl(thisTypeInFunctions.ts, 140, 13)) +>this : Symbol(Base1, Decl(thisTypeInFunctions.ts, 137, 24)) +>x : Symbol(Base1.x, Decl(thisTypeInFunctions.ts, 140, 13)) } class Derived2 extends Base2 { ->Derived2 : Symbol(Derived2, Decl(thisTypeInFunctions.ts, 150, 1)) ->Base2 : Symbol(Base2, Decl(thisTypeInFunctions.ts, 145, 1)) +>Derived2 : Symbol(Derived2, Decl(thisTypeInFunctions.ts, 154, 1)) +>Base2 : Symbol(Base2, Decl(thisTypeInFunctions.ts, 149, 1)) x: number ->x : Symbol(Derived2.x, Decl(thisTypeInFunctions.ts, 151, 30)) +>x : Symbol(Derived2.x, Decl(thisTypeInFunctions.ts, 155, 30)) } let b1 = new Base1(); ->b1 : Symbol(b1, Decl(thisTypeInFunctions.ts, 154, 3)) ->Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 133, 24)) +>b1 : Symbol(b1, Decl(thisTypeInFunctions.ts, 158, 3)) +>Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 137, 24)) let b2 = new Base2(); ->b2 : Symbol(b2, Decl(thisTypeInFunctions.ts, 155, 3)) ->Base2 : Symbol(Base2, Decl(thisTypeInFunctions.ts, 145, 1)) +>b2 : Symbol(b2, Decl(thisTypeInFunctions.ts, 159, 3)) +>Base2 : Symbol(Base2, Decl(thisTypeInFunctions.ts, 149, 1)) let d1 = new Derived1(); ->d1 : Symbol(d1, Decl(thisTypeInFunctions.ts, 156, 3)) ->Derived1 : Symbol(Derived1, Decl(thisTypeInFunctions.ts, 142, 1)) +>d1 : Symbol(d1, Decl(thisTypeInFunctions.ts, 160, 3)) +>Derived1 : Symbol(Derived1, Decl(thisTypeInFunctions.ts, 146, 1)) let d2 = new Derived2(); ->d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 157, 3)) ->Derived2 : Symbol(Derived2, Decl(thisTypeInFunctions.ts, 150, 1)) +>d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 161, 3)) +>Derived2 : Symbol(Derived2, Decl(thisTypeInFunctions.ts, 154, 1)) d2.polymorphic = d1.polymorphic // ok, 'x' and 'y' in { x, y } ->d2.polymorphic : Symbol(Base2.polymorphic, Decl(thisTypeInFunctions.ts, 147, 13)) ->d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 157, 3)) ->polymorphic : Symbol(Base2.polymorphic, Decl(thisTypeInFunctions.ts, 147, 13)) ->d1.polymorphic : Symbol(Base1.polymorphic, Decl(thisTypeInFunctions.ts, 137, 14)) ->d1 : Symbol(d1, Decl(thisTypeInFunctions.ts, 156, 3)) ->polymorphic : Symbol(Base1.polymorphic, Decl(thisTypeInFunctions.ts, 137, 14)) +>d2.polymorphic : Symbol(Base2.polymorphic, Decl(thisTypeInFunctions.ts, 151, 13)) +>d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 161, 3)) +>polymorphic : Symbol(Base2.polymorphic, Decl(thisTypeInFunctions.ts, 151, 13)) +>d1.polymorphic : Symbol(Base1.polymorphic, Decl(thisTypeInFunctions.ts, 141, 14)) +>d1 : Symbol(d1, Decl(thisTypeInFunctions.ts, 160, 3)) +>polymorphic : Symbol(Base1.polymorphic, Decl(thisTypeInFunctions.ts, 141, 14)) d1.polymorphic = d2.polymorphic // ok, 'x' and 'y' in { x, y } ->d1.polymorphic : Symbol(Base1.polymorphic, Decl(thisTypeInFunctions.ts, 137, 14)) ->d1 : Symbol(d1, Decl(thisTypeInFunctions.ts, 156, 3)) ->polymorphic : Symbol(Base1.polymorphic, Decl(thisTypeInFunctions.ts, 137, 14)) ->d2.polymorphic : Symbol(Base2.polymorphic, Decl(thisTypeInFunctions.ts, 147, 13)) ->d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 157, 3)) ->polymorphic : Symbol(Base2.polymorphic, Decl(thisTypeInFunctions.ts, 147, 13)) +>d1.polymorphic : Symbol(Base1.polymorphic, Decl(thisTypeInFunctions.ts, 141, 14)) +>d1 : Symbol(d1, Decl(thisTypeInFunctions.ts, 160, 3)) +>polymorphic : Symbol(Base1.polymorphic, Decl(thisTypeInFunctions.ts, 141, 14)) +>d2.polymorphic : Symbol(Base2.polymorphic, Decl(thisTypeInFunctions.ts, 151, 13)) +>d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 161, 3)) +>polymorphic : Symbol(Base2.polymorphic, Decl(thisTypeInFunctions.ts, 151, 13)) // bivariance-allowed cases d1.polymorphic = b2.polymorphic // ok, 'y' in D: { x, y } ->d1.polymorphic : Symbol(Base1.polymorphic, Decl(thisTypeInFunctions.ts, 137, 14)) ->d1 : Symbol(d1, Decl(thisTypeInFunctions.ts, 156, 3)) ->polymorphic : Symbol(Base1.polymorphic, Decl(thisTypeInFunctions.ts, 137, 14)) ->b2.polymorphic : Symbol(Base2.polymorphic, Decl(thisTypeInFunctions.ts, 147, 13)) ->b2 : Symbol(b2, Decl(thisTypeInFunctions.ts, 155, 3)) ->polymorphic : Symbol(Base2.polymorphic, Decl(thisTypeInFunctions.ts, 147, 13)) +>d1.polymorphic : Symbol(Base1.polymorphic, Decl(thisTypeInFunctions.ts, 141, 14)) +>d1 : Symbol(d1, Decl(thisTypeInFunctions.ts, 160, 3)) +>polymorphic : Symbol(Base1.polymorphic, Decl(thisTypeInFunctions.ts, 141, 14)) +>b2.polymorphic : Symbol(Base2.polymorphic, Decl(thisTypeInFunctions.ts, 151, 13)) +>b2 : Symbol(b2, Decl(thisTypeInFunctions.ts, 159, 3)) +>polymorphic : Symbol(Base2.polymorphic, Decl(thisTypeInFunctions.ts, 151, 13)) d2.polymorphic = d1.explicit // ok, 'y' in { x, y } ->d2.polymorphic : Symbol(Base2.polymorphic, Decl(thisTypeInFunctions.ts, 147, 13)) ->d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 157, 3)) ->polymorphic : Symbol(Base2.polymorphic, Decl(thisTypeInFunctions.ts, 147, 13)) ->d1.explicit : Symbol(Base1.explicit, Decl(thisTypeInFunctions.ts, 138, 61)) ->d1 : Symbol(d1, Decl(thisTypeInFunctions.ts, 156, 3)) ->explicit : Symbol(Base1.explicit, Decl(thisTypeInFunctions.ts, 138, 61)) +>d2.polymorphic : Symbol(Base2.polymorphic, Decl(thisTypeInFunctions.ts, 151, 13)) +>d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 161, 3)) +>polymorphic : Symbol(Base2.polymorphic, Decl(thisTypeInFunctions.ts, 151, 13)) +>d1.explicit : Symbol(Base1.explicit, Decl(thisTypeInFunctions.ts, 142, 61)) +>d1 : Symbol(d1, Decl(thisTypeInFunctions.ts, 160, 3)) +>explicit : Symbol(Base1.explicit, Decl(thisTypeInFunctions.ts, 142, 61)) b1.polymorphic = d2.polymorphic // ok, 'x' and 'y' not in Base1: { x } ->b1.polymorphic : Symbol(Base1.polymorphic, Decl(thisTypeInFunctions.ts, 137, 14)) ->b1 : Symbol(b1, Decl(thisTypeInFunctions.ts, 154, 3)) ->polymorphic : Symbol(Base1.polymorphic, Decl(thisTypeInFunctions.ts, 137, 14)) ->d2.polymorphic : Symbol(Base2.polymorphic, Decl(thisTypeInFunctions.ts, 147, 13)) ->d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 157, 3)) ->polymorphic : Symbol(Base2.polymorphic, Decl(thisTypeInFunctions.ts, 147, 13)) +>b1.polymorphic : Symbol(Base1.polymorphic, Decl(thisTypeInFunctions.ts, 141, 14)) +>b1 : Symbol(b1, Decl(thisTypeInFunctions.ts, 158, 3)) +>polymorphic : Symbol(Base1.polymorphic, Decl(thisTypeInFunctions.ts, 141, 14)) +>d2.polymorphic : Symbol(Base2.polymorphic, Decl(thisTypeInFunctions.ts, 151, 13)) +>d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 161, 3)) +>polymorphic : Symbol(Base2.polymorphic, Decl(thisTypeInFunctions.ts, 151, 13)) b1.explicit = d2.polymorphic // ok, 'x' and 'y' not in Base1: { x } ->b1.explicit : Symbol(Base1.explicit, Decl(thisTypeInFunctions.ts, 138, 61)) ->b1 : Symbol(b1, Decl(thisTypeInFunctions.ts, 154, 3)) ->explicit : Symbol(Base1.explicit, Decl(thisTypeInFunctions.ts, 138, 61)) ->d2.polymorphic : Symbol(Base2.polymorphic, Decl(thisTypeInFunctions.ts, 147, 13)) ->d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 157, 3)) ->polymorphic : Symbol(Base2.polymorphic, Decl(thisTypeInFunctions.ts, 147, 13)) +>b1.explicit : Symbol(Base1.explicit, Decl(thisTypeInFunctions.ts, 142, 61)) +>b1 : Symbol(b1, Decl(thisTypeInFunctions.ts, 158, 3)) +>explicit : Symbol(Base1.explicit, Decl(thisTypeInFunctions.ts, 142, 61)) +>d2.polymorphic : Symbol(Base2.polymorphic, Decl(thisTypeInFunctions.ts, 151, 13)) +>d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 161, 3)) +>polymorphic : Symbol(Base2.polymorphic, Decl(thisTypeInFunctions.ts, 151, 13)) ////// use this-type for construction with new //// function InterfaceThis(this: I) { ->InterfaceThis : Symbol(InterfaceThis, Decl(thisTypeInFunctions.ts, 165, 28)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 168, 23)) +>InterfaceThis : Symbol(InterfaceThis, Decl(thisTypeInFunctions.ts, 169, 28)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 172, 23)) >I : Symbol(I, Decl(thisTypeInFunctions.ts, 19, 21)) this.a = 12; @@ -725,60 +738,60 @@ function InterfaceThis(this: I) { >a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 20, 13)) } function LiteralTypeThis(this: {x: string}) { ->LiteralTypeThis : Symbol(LiteralTypeThis, Decl(thisTypeInFunctions.ts, 170, 1)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 171, 25)) ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 171, 32)) +>LiteralTypeThis : Symbol(LiteralTypeThis, Decl(thisTypeInFunctions.ts, 174, 1)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 175, 25)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 175, 32)) this.x = "ok"; ->this.x : Symbol(x, Decl(thisTypeInFunctions.ts, 171, 32)) ->this : Symbol(, Decl(thisTypeInFunctions.ts, 171, 30)) ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 171, 32)) +>this.x : Symbol(x, Decl(thisTypeInFunctions.ts, 175, 32)) +>this : Symbol(, Decl(thisTypeInFunctions.ts, 175, 30)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 175, 32)) } function AnyThis(this: any) { ->AnyThis : Symbol(AnyThis, Decl(thisTypeInFunctions.ts, 173, 1)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 174, 17)) +>AnyThis : Symbol(AnyThis, Decl(thisTypeInFunctions.ts, 177, 1)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 178, 17)) this.x = "ok"; } let interfaceThis = new InterfaceThis(); ->interfaceThis : Symbol(interfaceThis, Decl(thisTypeInFunctions.ts, 177, 3)) ->InterfaceThis : Symbol(InterfaceThis, Decl(thisTypeInFunctions.ts, 165, 28)) +>interfaceThis : Symbol(interfaceThis, Decl(thisTypeInFunctions.ts, 181, 3)) +>InterfaceThis : Symbol(InterfaceThis, Decl(thisTypeInFunctions.ts, 169, 28)) let literalTypeThis = new LiteralTypeThis(); ->literalTypeThis : Symbol(literalTypeThis, Decl(thisTypeInFunctions.ts, 178, 3)) ->LiteralTypeThis : Symbol(LiteralTypeThis, Decl(thisTypeInFunctions.ts, 170, 1)) +>literalTypeThis : Symbol(literalTypeThis, Decl(thisTypeInFunctions.ts, 182, 3)) +>LiteralTypeThis : Symbol(LiteralTypeThis, Decl(thisTypeInFunctions.ts, 174, 1)) let anyThis = new AnyThis(); ->anyThis : Symbol(anyThis, Decl(thisTypeInFunctions.ts, 179, 3)) ->AnyThis : Symbol(AnyThis, Decl(thisTypeInFunctions.ts, 173, 1)) +>anyThis : Symbol(anyThis, Decl(thisTypeInFunctions.ts, 183, 3)) +>AnyThis : Symbol(AnyThis, Decl(thisTypeInFunctions.ts, 177, 1)) //// type parameter inference //// declare var f: { ->f : Symbol(f, Decl(thisTypeInFunctions.ts, 182, 11)) +>f : Symbol(f, Decl(thisTypeInFunctions.ts, 186, 11)) (this: void, x: number): number, ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 183, 5)) ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 183, 16)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 187, 5)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 187, 16)) call(this: (...argArray: any[]) => U, ...argArray: any[]): U; ->call : Symbol(call, Decl(thisTypeInFunctions.ts, 183, 36)) ->U : Symbol(U, Decl(thisTypeInFunctions.ts, 184, 9)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 184, 12)) ->argArray : Symbol(argArray, Decl(thisTypeInFunctions.ts, 184, 19)) ->U : Symbol(U, Decl(thisTypeInFunctions.ts, 184, 9)) ->argArray : Symbol(argArray, Decl(thisTypeInFunctions.ts, 184, 44)) ->U : Symbol(U, Decl(thisTypeInFunctions.ts, 184, 9)) +>call : Symbol(call, Decl(thisTypeInFunctions.ts, 187, 36)) +>U : Symbol(U, Decl(thisTypeInFunctions.ts, 188, 9)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 188, 12)) +>argArray : Symbol(argArray, Decl(thisTypeInFunctions.ts, 188, 19)) +>U : Symbol(U, Decl(thisTypeInFunctions.ts, 188, 9)) +>argArray : Symbol(argArray, Decl(thisTypeInFunctions.ts, 188, 44)) +>U : Symbol(U, Decl(thisTypeInFunctions.ts, 188, 9)) }; let n: number = f.call(12); ->n : Symbol(n, Decl(thisTypeInFunctions.ts, 186, 3)) ->f.call : Symbol(call, Decl(thisTypeInFunctions.ts, 183, 36)) ->f : Symbol(f, Decl(thisTypeInFunctions.ts, 182, 11)) ->call : Symbol(call, Decl(thisTypeInFunctions.ts, 183, 36)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 190, 3)) +>f.call : Symbol(call, Decl(thisTypeInFunctions.ts, 187, 36)) +>f : Symbol(f, Decl(thisTypeInFunctions.ts, 186, 11)) +>call : Symbol(call, Decl(thisTypeInFunctions.ts, 187, 36)) function missingTypeIsImplicitAny(this, a: number) { return this.anything + a; } ->missingTypeIsImplicitAny : Symbol(missingTypeIsImplicitAny, Decl(thisTypeInFunctions.ts, 186, 27)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 188, 34)) ->a : Symbol(a, Decl(thisTypeInFunctions.ts, 188, 39)) ->a : Symbol(a, Decl(thisTypeInFunctions.ts, 188, 39)) +>missingTypeIsImplicitAny : Symbol(missingTypeIsImplicitAny, Decl(thisTypeInFunctions.ts, 190, 27)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 192, 34)) +>a : Symbol(a, Decl(thisTypeInFunctions.ts, 192, 39)) +>a : Symbol(a, Decl(thisTypeInFunctions.ts, 192, 39)) diff --git a/tests/baselines/reference/thisTypeInFunctions.types b/tests/baselines/reference/thisTypeInFunctions.types index 24d3bf9f17865..ddef8544a540c 100644 --- a/tests/baselines/reference/thisTypeInFunctions.types +++ b/tests/baselines/reference/thisTypeInFunctions.types @@ -690,6 +690,22 @@ c.explicitThis = function(m) { return this.n + m }; >n : number >m : number +// this: contextual typing +c.explicitThis = function(this, m) { return this.n + m }; +>c.explicitThis = function(this, m) { return this.n + m } : (this: any, m: number) => number +>c.explicitThis : (this: C, m: number) => number +>c : C +>explicitThis : (this: C, m: number) => number +>function(this, m) { return this.n + m } : (this: any, m: number) => number +>this : C +>m : number +>this.n + m : number +>this.n : number +>this : C +>n : number +>m : number + +// this: superclass compatibility c.explicitC = function(this: B, m: number) { return this.n + m }; >c.explicitC = function(this: B, m: number) { return this.n + m } : (this: B, m: number) => number >c.explicitC : (this: C, m: number) => number diff --git a/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts b/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts index 80f5fce9a9774..481e1630092b5 100644 --- a/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts +++ b/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts @@ -128,6 +128,10 @@ c.explicitC = function(m) { return this.n + m }; c.explicitProperty = function(m) { return this.n + m }; c.explicitThis = function(m) { return this.n + m }; +// this: contextual typing +c.explicitThis = function(this, m) { return this.n + m }; + +// this: superclass compatibility c.explicitC = function(this: B, m: number) { return this.n + m }; // this:void compatibility