diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6d21a9b5e3ffc..a357a2e0f71cb 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, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false); - const unknownSignature = createSignature(undefined, undefined, emptyArray, unknownType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false); + const anySignature = createSignature(undefined, undefined, undefined, emptyArray, anyType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false); + const unknownSignature = createSignature(undefined, undefined, undefined, emptyArray, unknownType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false); const enumNumberIndexInfo = createIndexInfo(stringType, /*isReadonly*/ true); @@ -2299,10 +2299,16 @@ 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); + 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) { + if (i > 0 || thisType) { writePunctuation(writer, SyntaxKind.CommaToken); writeSpace(writer); } @@ -2358,7 +2364,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); } @@ -2798,7 +2804,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 strictNullChecks && declaration.questionToken ? addNullableKind(type, TypeFlags.Undefined) : type; } @@ -3656,12 +3664,13 @@ namespace ts { resolveObjectTypeMembers(type, source, typeParameters, typeArguments); } - function createSignature(declaration: SignatureDeclaration, typeParameters: TypeParameter[], parameters: Symbol[], + function createSignature(declaration: SignatureDeclaration, typeParameters: TypeParameter[], thisType: Type, parameters: Symbol[], resolvedReturnType: Type, typePredicate: TypePredicate, 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.typePredicate = typePredicate; sig.minArgumentCount = minArgumentCount; @@ -3671,7 +3680,7 @@ namespace ts { } function cloneSignature(sig: Signature): Signature { - return createSignature(sig.declaration, sig.typeParameters, sig.parameters, sig.resolvedReturnType, + return createSignature(sig.declaration, sig.typeParameters, sig.thisType, sig.parameters, sig.resolvedReturnType, sig.typePredicate, sig.minArgumentCount, sig.hasRestParameter, sig.hasStringLiterals); } @@ -3679,7 +3688,7 @@ namespace ts { const baseConstructorType = getBaseConstructorTypeOfClass(classType); const baseSignatures = getSignaturesOfType(baseConstructorType, SignatureKind.Construct); if (baseSignatures.length === 0) { - return [createSignature(undefined, classType.localTypeParameters, emptyArray, classType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false)]; + return [createSignature(undefined, classType.localTypeParameters, undefined, emptyArray, classType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false)]; } const baseTypeNode = getBaseTypeNodeOfClass(classType); const typeArguments = map(baseTypeNode.typeArguments, getTypeFromTypeNode); @@ -3716,9 +3725,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; } } @@ -3732,7 +3741,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; } } @@ -3741,7 +3750,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; } @@ -3762,13 +3771,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; @@ -4222,6 +4234,8 @@ namespace ts { const parameters: Symbol[] = []; let hasStringLiterals = false; let minArgumentCount = -1; + let thisType: Type = undefined; + let hasThisParameter: boolean; const isJSConstructSignature = isJSDocConstructSignature(declaration); let returnType: Type = undefined; let typePredicate: TypePredicate = undefined; @@ -4238,7 +4252,13 @@ namespace ts { const resolvedSymbol = resolveName(param, paramSymbol.name, SymbolFlags.Value, undefined, undefined); paramSymbol = resolvedSymbol; } - parameters.push(paramSymbol); + if (i === 0 && paramSymbol.name === "this") { + hasThisParameter = true; + thisType = param.type ? getTypeFromTypeNode(param.type) : unknownType; + } + else { + parameters.push(paramSymbol); + } if (param.type && param.type.kind === SyntaxKind.StringLiteralType) { hasStringLiterals = true; @@ -4246,7 +4266,7 @@ namespace ts { if (param.initializer || param.questionToken || param.dotDotDotToken) { if (minArgumentCount < 0) { - minArgumentCount = i; + minArgumentCount = i - (hasThisParameter ? 1 : 0); } } else { @@ -4256,7 +4276,7 @@ namespace ts { } if (minArgumentCount < 0) { - minArgumentCount = declaration.parameters.length; + minArgumentCount = declaration.parameters.length - (hasThisParameter ? 1 : 0); } if (isJSConstructSignature) { @@ -4292,7 +4312,7 @@ namespace ts { } } - links.resolvedSignature = createSignature(declaration, typeParameters, parameters, returnType, typePredicate, minArgumentCount, hasRestParameter(declaration), hasStringLiterals); + links.resolvedSignature = createSignature(declaration, typeParameters, thisType, parameters, returnType, typePredicate, minArgumentCount, hasRestParameter(declaration), hasStringLiterals); } return links.resolvedSignature; } @@ -4984,7 +5004,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)) { @@ -5190,6 +5210,7 @@ namespace ts { freshTypePredicate = cloneTypePredicate(signature.typePredicate, mapper); } const result = createSignature(signature.declaration, freshTypeParameters, + signature.thisType && instantiateType(signature.thisType, mapper), instantiateList(signature.parameters, mapper, instantiateSymbol), instantiateType(signature.resolvedReturnType, mapper), freshTypePredicate, @@ -5358,7 +5379,9 @@ namespace ts { } function isContextSensitiveFunctionLikeDeclaration(node: FunctionLikeDeclaration) { - return !node.typeParameters && node.parameters.length && !forEach(node.parameters, p => p.type); + const areAllParametersUntyped = !forEach(node.parameters, p => p.type); + const isNullaryArrow = node.kind === SyntaxKind.ArrowFunction && !node.parameters.length; + return !node.typeParameters && areAllParametersUntyped && !isNullaryArrow; } function getTypeWithoutSignatures(type: Type): Type { @@ -5451,6 +5474,18 @@ namespace ts { target = getErasedSignature(target); let result = Ternary.True; + 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.The_this_types_of_each_signature_are_incompatible); + } + return Ternary.False; + } + result &= related; + } const sourceMax = getNumNonRestParameters(source); const targetMax = getNumNonRestParameters(target); @@ -6207,7 +6242,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; } @@ -6429,7 +6464,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; @@ -6450,6 +6485,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) : getTypeOfParameter(source.parameters[i]); @@ -6786,29 +6828,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++) { - const s = i < sourceMax ? getTypeOfParameter(source.parameters[i]) : getRestTypeOfSignature(source); - const t = i < targetMax ? getTypeOfParameter(target.parameters[i]) : getRestTypeOfSignature(target); - callback(s, t); + callback(getTypeAtPosition(source, i), getTypeAtPosition(target, i)); } } @@ -8040,7 +8076,24 @@ namespace ts { if (needToCaptureLexicalThis) { captureLexicalThis(node, container); } - + if (isFunctionLike(container)) { + const type = getContextuallyTypedThisType(container); + if (type) { + return type; + } + const signature = getSignatureFromDeclaration(container); + 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; @@ -8070,6 +8123,10 @@ namespace ts { } } + 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); + } return anyType; } @@ -8287,6 +8344,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; @@ -8696,7 +8766,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; } @@ -10066,6 +10136,12 @@ namespace ts { context.failedTypeParameterIndex = undefined; } + if (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 // wildcards for all context sensitive function expressions. const argCount = getEffectiveArgumentCount(node, args, signature); @@ -10139,6 +10215,20 @@ namespace ts { } function checkApplicableSignature(node: CallLikeExpression, args: Expression[], signature: Signature, relation: Map, excludeArgument: boolean[], reportErrors: boolean) { + + if (signature.thisType && signature.thisType !== voidType && node.kind !== SyntaxKind.NewExpression) { + // 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.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; + } + } + 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); @@ -10158,7 +10248,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; } @@ -10168,6 +10257,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. * @@ -10825,13 +10929,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 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); 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; } @@ -12305,6 +12412,17 @@ 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) { + error(node, Diagnostics.A_this_parameter_must_be_the_first_parameter); + } + 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) { + 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 // not allowed in a rest parameter, we already have an error from checkGrammarParameterList. diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 8d13b49ace5e4..b9796fd829fe8 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -122,6 +122,11 @@ namespace ts { type: "boolean", description: Diagnostics.Raise_error_on_expressions_and_declarations_with_an_implied_any_type, }, + { + name: "noImplicitThis", + type: "boolean", + description: Diagnostics.Raise_error_on_this_expressions_with_an_implied_any_type, + }, { name: "noLib", type: "boolean", diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 8fefa92b140e1..6134f1e82b2d4 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1879,6 +1879,34 @@ "category": "Error", "code": 2678 }, + "A function that is called with the 'new' keyword cannot have a 'this' type that is 'void'.": { + "category": "Error", + "code": 2679 + }, + "A 'this' parameter must be the first parameter.": { + "category": "Error", + "code": 2680 + }, + "A constructor cannot have a 'this' parameter.": { + "category": "Error", + "code": 2681 + }, + "A setter cannot have a 'this' parameter.": { + "category": "Error", + "code": 2682 + }, + "'this' implicitly has type 'any' because it does not have a type annotation.": { + "category": "Error", + "code": 2683 + }, + "The 'this' context of type '{0}' is not assignable to method's 'this' of type '{1}'.": { + "category": "Error", + "code": 2684 + }, + "The 'this' types of each signature are incompatible.": { + "category": "Error", + "code": 2685 + }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", "code": 4000 @@ -2632,7 +2660,10 @@ "category": "Error", "code": 6114 }, - + "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/src/compiler/emitter.ts b/src/compiler/emitter.ts index 469530bb6be31..7f35f809570a7 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -4630,8 +4630,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(); diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index b7c011631ee18..5119358d8d049 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -2010,7 +2010,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) { @@ -2022,15 +2022,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' @@ -2068,11 +2072,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(); @@ -2473,7 +2477,7 @@ namespace ts { // Skip modifiers parseModifiers(); } - if (isIdentifier()) { + if (isIdentifier() || token === SyntaxKind.ThisKeyword) { nextToken(); return true; } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 3bc3d1ad6a178..01c841fb8fe21 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1778,7 +1778,7 @@ namespace ts { buildTypeParameterDisplay(tp: TypeParameter, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; buildTypePredicateDisplay(predicate: TypePredicate, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; buildTypeParameterDisplayFromSymbol(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: 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; } @@ -2280,6 +2280,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 */ @@ -2424,6 +2425,7 @@ namespace ts { noEmitOnError?: boolean; noErrorTruncation?: boolean; noImplicitAny?: boolean; + noImplicitThis?: boolean; noLib?: boolean; noResolve?: boolean; out?: string; diff --git a/src/harness/loggedIO.ts b/src/harness/loggedIO.ts index 2c4d019d45b55..f38c29c29463a 100644 --- a/src/harness/loggedIO.ts +++ b/src/harness/loggedIO.ts @@ -237,8 +237,8 @@ namespace Playback { ), 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(underlying.writeFile(path, contents), recordLog.filesWritten, { path, contents, bom: false }), + (path: string, contents: string) => noOpReplay("writeFile")); wrapper.exit = (exitCode) => { if (recordLog !== undefined) { diff --git a/src/lib/es5.d.ts b/src/lib/es5.d.ts index 65f4fbabf6b7b..dd3043454d5e8 100644 --- a/src/lib/es5.d.ts +++ b/src/lib/es5.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[]): (this: void, ...argArray: any[]) => U; + bind(this: Function, thisArg: any, ...argArray: any[]): any; prototype: any; readonly length: number; diff --git a/src/services/services.ts b/src/services/services.ts index a634b2baf1a49..3aa07fe4e410a 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -741,6 +741,7 @@ namespace ts { declaration: SignatureDeclaration; typeParameters: TypeParameter[]; parameters: Symbol[]; + thisType: Type; resolvedReturnType: Type; minArgumentCount: number; hasRestParameter: boolean; @@ -4109,6 +4110,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; @@ -4171,6 +4175,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 @@ -4181,7 +4186,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; @@ -4292,7 +4297,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) @@ -4434,11 +4439,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 e1e493b26340e..9e8a2f14ed8c0 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 { 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 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/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/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/contextualTyping24.errors.txt b/tests/baselines/reference/contextualTyping24.errors.txt index f4205f243590c..ea97305062518 100644 --- a/tests/baselines/reference/contextualTyping24.errors.txt +++ b/tests/baselines/reference/contextualTyping24.errors.txt @@ -1,11 +1,11 @@ -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 '{ (): number; (i: number): number; }' is not assignable to type '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: 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 '{ (): number; (i: number): number; }' is not assignable to type 'string'. \ No newline at end of file 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/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..d3597ad2507b5 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: Type '{ m(): this is Foo; }' cannot be converted to type 'Foo'. + 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: 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; } } \ No newline at end of file diff --git a/tests/baselines/reference/declarationEmitThisPredicatesWithPrivateName02.errors.txt b/tests/baselines/reference/declarationEmitThisPredicatesWithPrivateName02.errors.txt index 86c0f478133c3..7a4716a92e082 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: Type '{ m(): this is Foo; }' cannot be converted to type 'Foo'. + 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: 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; } } \ 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/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/looseThisTypeInFunctions.errors.txt b/tests/baselines/reference/looseThisTypeInFunctions.errors.txt new file mode 100644 index 0000000000000..b7a36b99ad441 --- /dev/null +++ b/tests/baselines/reference/looseThisTypeInFunctions.errors.txt @@ -0,0 +1,66 @@ +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'. + 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: 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'. + + +==== tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts (4 errors) ==== + interface I { + n: number; + 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 '(this: void, m: number) => number'. +!!! error TS2322: The 'this' types of each signature are incompatible. +!!! error TS2322: Type 'void' is not assignable to type 'C'. + let o = { + 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' + ~~~~~~ +!!! 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 + ~~~~~ +!!! 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 + 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 + ~~~~~~ +!!! 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 new file mode 100644 index 0000000000000..3b172877e0e8f --- /dev/null +++ b/tests/baselines/reference/looseThisTypeInFunctions.js @@ -0,0 +1,92 @@ +//// [looseThisTypeInFunctions.ts] +interface I { + n: number; + 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 = { + 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; +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; +i.explicitThis = function(m) { + return this.n.length; // error, this.n: number +} + +//// [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 = { + 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; +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; +i.explicitThis = function (m) { + return this.n.length; // error, this.n: number +}; diff --git a/tests/baselines/reference/noImplicitThisFunctions.errors.txt b/tests/baselines/reference/noImplicitThisFunctions.errors.txt new file mode 100644 index 0000000000000..5f66ac3553fac --- /dev/null +++ b/tests/baselines/reference/noImplicitThisFunctions.errors.txt @@ -0,0 +1,28 @@ +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) ==== + + 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 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 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/noImplicitThisFunctions.js b/tests/baselines/reference/noImplicitThisFunctions.js new file mode 100644 index 0000000000000..80ceccbe75176 --- /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; +} + +// error: `this` is `window`, but is still of type `any` +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; +} +// error: `this` is `window`, but is still of type `any` +var f4 = function (b) { return _this.c + b; }; 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/baselines/reference/thisInObjectLiterals.errors.txt b/tests/baselines/reference/thisInObjectLiterals.errors.txt index 73300d86d74f1..b0b1c63a34a91 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; @@ -14,10 +15,12 @@ tests/cases/conformance/expressions/thisKeyword/thisInObjectLiterals.ts(7,13): e } } - //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; + ~~~~~~~ +!!! error TS2339: Property 'spaaace' does not exist on type '{ f(): any; }'. } }; var obj: { f: () => any; }; 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; diff --git a/tests/baselines/reference/thisTypeInFunctions.js b/tests/baselines/reference/thisTypeInFunctions.js new file mode 100644 index 0000000000000..cfe1706ae99db --- /dev/null +++ b/tests/baselines/reference/thisTypeInFunctions.js @@ -0,0 +1,382 @@ +//// [thisTypeInFunctions.ts] +// body checking +class B { + n: number; +} +class C { + n: number; + explicitThis(this: this, 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 { } +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; +} +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 this.m + n + 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; + }, +} +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; }; +// 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); +d.explicitC(12); +d.explicitProperty(12); +d.explicitThis(12); +let reconstructed: { + n: number, + explicitThis(this: C, m: number): number, // note: this: this is not allowed in an object literal type. + 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 +}; +reconstructed.explicitThis(10); +reconstructed.explicitProperty(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; +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) { 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 +c.explicitVoid = n => n; + +// class-based assignability +class Base1 { + x: number; + public polymorphic(this: this): number { return this.x; } + explicit(this: Base1): number { return this.x; } + static explicitStatic(this: typeof Base1): number { return this.y; } + static y: number; +} +class Derived1 extends Base1 { + y: number +} +class Base2 { + y: number + polymorphic(this: this): 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.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.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) { + 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 this.anything + 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 B = (function () { + function B() { + } + return B; +}()); +var C = (function () { + function C() { + } + C.prototype.explicitThis = 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)); +function explicitStructural(x) { + return x + this.y; +} +function justThis() { + return this.y; +} +function implicitThis(n) { + return this.m + n + 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; + } +}; +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; }; +// 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); +d.explicitC(12); +d.explicitProperty(12); +d.explicitThis(12); +var reconstructed = { + n: 12, + explicitThis: c.explicitThis, + explicitC: c.explicitC, + explicitProperty: c.explicitProperty, + explicitVoid: c.explicitVoid +}; +reconstructed.explicitThis(10); +reconstructed.explicitProperty(11); +var explicitVoid = reconstructed.explicitVoid; +explicitVoid(12); +// 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; }; +// 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; }; +// class-based assignability +var Base1 = (function () { + function Base1() { + } + Base1.prototype.polymorphic = function () { return this.x; }; + Base1.prototype.explicit = function () { return this.x; }; + 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.polymorphic = 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.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.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; +} +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 this.anything + a; } diff --git a/tests/baselines/reference/thisTypeInFunctions.symbols b/tests/baselines/reference/thisTypeInFunctions.symbols new file mode 100644 index 0000000000000..3d4c3f6ecc70f --- /dev/null +++ b/tests/baselines/reference/thisTypeInFunctions.symbols @@ -0,0 +1,797 @@ +=== tests/cases/conformance/types/thisType/thisTypeInFunctions.ts === +// body checking +class B { +>B : Symbol(B, Decl(thisTypeInFunctions.ts, 0, 0)) + + n: number; +>n : Symbol(B.n, Decl(thisTypeInFunctions.ts, 1, 9)) +} +class C { +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) + + n: number; +>n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 4, 9)) + + explicitThis(this: this, m: number): number { +>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(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, 6, 28)) + } + explicitC(this: C, m: number): number { +>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(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, 9, 22)) + } + explicitProperty(this: {n: number}, m: number): number { +>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)) + + 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(C.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, 3, 1)) + +interface I { +>I : Symbol(I, Decl(thisTypeInFunctions.ts, 19, 21)) + + a: number; +>a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 20, 13)) + + explicitVoid1(this: void): number; +>explicitVoid1 : Symbol(I.explicitVoid1, Decl(thisTypeInFunctions.ts, 21, 14)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 22, 18)) + + explicitVoid2(this: void): number; +>explicitVoid2 : Symbol(I.explicitVoid2, Decl(thisTypeInFunctions.ts, 22, 38)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 23, 18)) + + explicitStructural(this: {a: number}): number; +>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(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(I.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, 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, 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, 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, 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, 33, 1)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 34, 22)) + + return this.m + n + 12; +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 34, 22)) +} +let impl: I = { +>impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 37, 3)) +>I : Symbol(I, Decl(thisTypeInFunctions.ts, 19, 21)) + + a: 12, +>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, 38, 10)) + + explicitVoid1() { return 12; }, +>explicitVoid1 : Symbol(explicitVoid1, Decl(thisTypeInFunctions.ts, 39, 32)) + + explicitStructural() { +>explicitStructural : Symbol(explicitStructural, Decl(thisTypeInFunctions.ts, 40, 35)) + + return this.a; +>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, 43, 6)) + + return this.a; +>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, 46, 6)) + + return this.a; +>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.explicitVoid1 = function () { return 12; }; +>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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 33, 1)) + +implicitAnyOk.f(12); +>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, 65, 3)) +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) + +let d = new D(); +>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, 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, 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, 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, 65, 3)) +>explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) + +d.explicitC(12); +>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, 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, 66, 3)) +>explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) + +let reconstructed: { +>reconstructed : Symbol(reconstructed, Decl(thisTypeInFunctions.ts, 74, 3)) + + n: number, +>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, 75, 14)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 76, 17)) +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 76, 25)) + + explicitC(this: C, m: number): number, +>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, 77, 22)) + + explicitProperty: (this: {n : number}, m: number) => number, +>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, 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, 80, 5)) + + explicitThis: c.explicitThis, +>explicitThis : Symbol(explicitThis, Decl(thisTypeInFunctions.ts, 81, 10)) +>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)) + + explicitC: c.explicitC, +>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, 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, 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, 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)) + +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, 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, 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, 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, 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, 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, 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, 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, 102, 3)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 102, 24)) +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 102, 32)) + +let explicitPropertyFunction: (this: {n: number}, m: number) => number; +>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, 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, 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, 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, 105, 31)) + +c.explicitProperty = explicitPropertyFunction; +>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, 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, 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, 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, 65, 3)) +>explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) +>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, 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, 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, 65, 3)) +>explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) +>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, 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, 65, 3)) +>explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) +>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, 65, 3)) +>explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 123, 26)) +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) +>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, 123, 34)) + +// this:any compatibility +c.explicitC = function(m) { 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)) +>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, 126, 23)) + +c.explicitProperty = function(m) { return this.n + m }; +>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, 65, 3)) +>explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) +>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, 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, 134, 23)) +>B : Symbol(B, Decl(thisTypeInFunctions.ts, 0, 0)) +>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, 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, 137, 16)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 137, 16)) + +// class-based assignability +class Base1 { +>Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 137, 24)) + + x: number; +>x : Symbol(Base1.x, Decl(thisTypeInFunctions.ts, 140, 13)) + + public polymorphic(this: this): number { return this.x; } +>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, 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, 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, 144, 72)) +} +class Derived1 extends Base1 { +>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, 147, 30)) +} +class Base2 { +>Base2 : Symbol(Base2, Decl(thisTypeInFunctions.ts, 149, 1)) + + y: number +>y : Symbol(Base2.y, Decl(thisTypeInFunctions.ts, 150, 13)) + + polymorphic(this: this): number { return this.y; } +>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, 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, 154, 1)) +>Base2 : Symbol(Base2, Decl(thisTypeInFunctions.ts, 149, 1)) + + x: number +>x : Symbol(Derived2.x, Decl(thisTypeInFunctions.ts, 155, 30)) +} +let b1 = new Base1(); +>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, 159, 3)) +>Base2 : Symbol(Base2, Decl(thisTypeInFunctions.ts, 149, 1)) + +let d1 = new Derived1(); +>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, 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, 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, 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, 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, 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, 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, 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, 169, 28)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 172, 23)) +>I : Symbol(I, Decl(thisTypeInFunctions.ts, 19, 21)) + + this.a = 12; +>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, 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, 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, 177, 1)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 178, 17)) + + this.x = "ok"; +} +let interfaceThis = new InterfaceThis(); +>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, 182, 3)) +>LiteralTypeThis : Symbol(LiteralTypeThis, Decl(thisTypeInFunctions.ts, 174, 1)) + +let anyThis = new AnyThis(); +>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, 186, 11)) + + (this: void, x: number): number, +>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, 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, 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, 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 new file mode 100644 index 0000000000000..ddef8544a540c --- /dev/null +++ b/tests/baselines/reference/thisTypeInFunctions.types @@ -0,0 +1,963 @@ +=== tests/cases/conformance/types/thisType/thisTypeInFunctions.ts === +// body checking +class B { +>B : B + + n: number; +>n : number +} +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 + } + 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 : (this: void, 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 + +interface I { +>I : I + + a: number; +>a : number + + explicitVoid1(this: void): number; +>explicitVoid1 : (this: void) => number +>this : void + + explicitVoid2(this: void): number; +>explicitVoid2 : (this: void) => 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 +} +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 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; },} : { a: number; explicitVoid2: () => any; explicitVoid1(): number; explicitStructural(): number; explicitInterface(): number; explicitThis(): number; } + + 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 : () => number + + return this.a; +>this.a : number +>this : { a: number; } +>a : number + + }, + explicitInterface() { +>explicitInterface : () => number + + return this.a; +>this.a : number +>this : I +>a : number + + }, + explicitThis() { +>explicitThis : () => number + + return this.a; +>this.a : number +>this : I +>a : number + + }, +} +impl.explicitVoid1 = function () { return 12; }; +>impl.explicitVoid1 = function () { return 12; } : () => number +>impl.explicitVoid1 : (this: void) => number +>impl : I +>explicitVoid1 : (this: void) => number +>function () { return 12; } : () => number +>12 : number + +impl.explicitVoid2 = () => 12; +>impl.explicitVoid2 = () => 12 : () => number +>impl.explicitVoid2 : (this: void) => number +>impl : I +>explicitVoid2 : (this: void) => number +>() => 12 : () => number +>12 : number + +impl.explicitStructural = function() { return this.a; }; +>impl.explicitStructural = function() { return this.a; } : () => number +>impl.explicitStructural : (this: { a: number; }) => number +>impl : I +>explicitStructural : (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; } : () => number +>impl.explicitInterface : (this: I) => number +>impl : I +>explicitInterface : (this: I) => number +>function() { return this.a; } : () => 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; } : () => number +>impl.explicitThis : (this: I) => number +>impl : I +>explicitThis : (this: I) => number +>function () { return this.a; } : () => number +>this.a : number +>this : I +>a : number + +// 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 + +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 + +let reconstructed: { +>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 + + 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 + + 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 : (this: void, m: number) => number +>this : void +>m : 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 +>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 + + 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 : (this: void, m: number) => number +>c.explicitVoid : (this: void, m: number) => number +>c : C +>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; 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 + +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 +>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; } : (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 : (this: void, 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 : (this: void, 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; 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 +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) { return this.n + m }; +>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 } : (m: number) => number +>m : number +>this.n + m : number +>this.n : number +>this : C +>n : number +>m : number + +c.explicitProperty = function(m) { return this.n + m }; +>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 } : (m: number) => number +>m : number +>this.n + m : number +>this.n : number +>this : { n: number; } +>n : number +>m : number + +c.explicitThis = function(m) { return this.n + m }; +>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 } : (m: number) => number +>m : number +>this.n + m : number +>this.n : number +>this : C +>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 +>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 : (this: void, m: number) => number +>c : C +>explicitVoid : (this: void, m: number) => number +>n => n : (n: number) => number +>n : number +>n : number + +// class-based assignability +class Base1 { +>Base1 : Base1 + + x: number; +>x : number + + public polymorphic(this: this): number { return this.x; } +>polymorphic : (this: this) => number +>this : this +>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 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 + + polymorphic(this: this): number { return this.y; } +>polymorphic : (this: this) => number +>this : this +>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.polymorphic = d1.polymorphic // ok, 'x' and 'y' in { x, y } +>d2.polymorphic = d1.polymorphic : (this: Derived1) => number +>d2.polymorphic : (this: Derived2) => number +>d2 : Derived2 +>polymorphic : (this: Derived2) => number +>d1.polymorphic : (this: Derived1) => number +>d1 : Derived1 +>polymorphic : (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 +>polymorphic : (this: Derived1) => number +>d2.polymorphic : (this: Derived2) => number +>d2 : Derived2 +>polymorphic : (this: Derived2) => number + +// bivariance-allowed cases +d1.polymorphic = b2.polymorphic // ok, 'y' in D: { x, y } +>d1.polymorphic = b2.polymorphic : (this: Base2) => number +>d1.polymorphic : (this: Derived1) => number +>d1 : Derived1 +>polymorphic : (this: Derived1) => number +>b2.polymorphic : (this: Base2) => number +>b2 : Base2 +>polymorphic : (this: Base2) => number + +d2.polymorphic = d1.explicit // ok, 'y' in { x, y } +>d2.polymorphic = d1.explicit : (this: Base1) => number +>d2.polymorphic : (this: Derived2) => number +>d2 : Derived2 +>polymorphic : (this: Derived2) => number +>d1.explicit : (this: Base1) => number +>d1 : Derived1 +>explicit : (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 +>polymorphic : (this: Base1) => number +>d2.polymorphic : (this: Derived2) => number +>d2 : Derived2 +>polymorphic : (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.polymorphic : (this: Derived2) => number +>d2 : Derived2 +>polymorphic : (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 : (this: any) => void +>this : any + + this.x = "ok"; +>this.x = "ok" : string +>this.x : any +>this : any +>x : any +>"ok" : string +} +let interfaceThis = new InterfaceThis(); +>interfaceThis : any +>new InterfaceThis() : any +>InterfaceThis : (this: I) => void + +let literalTypeThis = new LiteralTypeThis(); +>literalTypeThis : any +>new LiteralTypeThis() : any +>LiteralTypeThis : (this: { x: string; }) => void + +let anyThis = new AnyThis(); +>anyThis : any +>new AnyThis() : any +>AnyThis : (this: any) => void + +//// type parameter inference //// +declare var f: { +>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: (...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 : { (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 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 new file mode 100644 index 0000000000000..017550dcecd9d --- /dev/null +++ b/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt @@ -0,0 +1,447 @@ +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: 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; }'. + 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(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(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(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: 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: 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'. +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'. + 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'. + 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'. + 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'. + 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'. + 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'. + 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'. + 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'. + 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'. + 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'. + 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'. + 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'. + 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'. +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,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 (66 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; + } + } + 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 + } + 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; + }, + } + let implExplicitStructural = impl.explicitStructural; + implExplicitStructural(); // error, no 'a' in 'void' + ~~~~~~~~~~~~~~~~~~~~~~~~ +!!! 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: 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; + } + 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'. + } + 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 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: 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(); + 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 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: The 'this' types of each signature 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. + 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 + };; + + // 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: 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: 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: 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: 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: 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: 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: 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; + ~~~~~~~~~~~~~~ +!!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'. + c.explicitVoid = d.explicitD; + ~~~~~~~~~~~~~~ +!!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: void, m: number) => number'. +!!! 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: The 'this' types of each signature are incompatible. +!!! error TS2322: Type 'void' is not assignable to type 'D'. + + /// class-based polymorphic assignability (with inheritance!) /// + + class Base1 { + x: number + public polymorphic(this: this): number { return this.x; } + explicit(this: Base1): number { return this.x; } + 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 + polymorphic(this: this): 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.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: 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: 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 } + ~~~~~~~~~~~ +!!! error TS2322: Type '(this: Base2) => number' is not assignable to type '(this: Base1) => number'. + + ////// use this-type for construction with new //// + function VoidThis(this: void) { + + } + let voidThis = new VoidThis(); + ~~~~~~~~~~~~~~ +!!! 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 TS2681: A constructor cannot have a 'this' parameter. + } + set p(this: void) { + ~~~~~~~~~~ +!!! error TS2682: A setter cannot have a 'this' parameter. + } + } + interface ThisConstructorInterface { + new(this: ThisConstructor, n: number); + ~~~~~~~~~~~~~~~~~~~~~ +!!! 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. + + ///// parse errors ///// + function modifiers(async this: C): number { return this.n; } + ~~~~ +!!! error TS1003: Identifier expected. + ~ +!!! error TS1005: ',' expected. + 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. + function optional(this?: C): number { return this.n; } + ~ +!!! error TS1005: ',' expected. + ~ +!!! error TS1138: Parameter declaration expected. + function decorated(@deco() this: C): number { return this.n; } + ~~~~ +!!! error TS1003: Identifier expected. + ~ +!!! error TS1005: ',' expected. + 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..124a7c8801329 --- /dev/null +++ b/tests/baselines/reference/thisTypeInFunctionsNegative.js @@ -0,0 +1,363 @@ +//// [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; + } +} +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 +} +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; + }, +} +let implExplicitStructural = impl.explicitStructural; +implExplicitStructural(); // error, no 'a' in 'void' +let implExplicitInterface = impl.explicitInterface; +implExplicitInterface(); // 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; +} +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 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. + 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 +};; + +// 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.explicitD; +c.explicitC = d.explicitThis; +c.explicitThis = d.explicitD; +c.explicitThis = d.explicitThis; +c.explicitProperty = d.explicitD; +c.explicitThis = d.explicitThis; +c.explicitVoid = d.explicitD; +c.explicitVoid = d.explicitThis; + +/// class-based polymorphic assignability (with inheritance!) /// + +class Base1 { + x: number + public polymorphic(this: this): number { return this.x; } + explicit(this: Base1): number { return this.x; } + static explicitStatic(this: typeof Base1): number { return this.x; } +} +class Derived1 extends Base1 { + y: number +} +class Base2 { + y: number + polymorphic(this: this): 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.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(this: void) { + +} +let voidThis = new VoidThis(); + +///// syntax-ish errors ///// +class ThisConstructor { + constructor(this: ThisConstructor, private n: number) { + } + set p(this: void) { + } +} +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 ///// +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; + }; + 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; + } +}; +var implExplicitStructural = impl.explicitStructural; +implExplicitStructural(); // error, no 'a' in 'void' +var implExplicitInterface = impl.explicitInterface; +implExplicitInterface(); // 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; +} +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 specifiedToVoid = explicitStructural; +var reconstructed = { + n: 12, + explicitThis: c.explicitThis, + 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.explicitD; +c.explicitC = d.explicitThis; +c.explicitThis = d.explicitD; +c.explicitThis = d.explicitThis; +c.explicitProperty = d.explicitD; +c.explicitThis = d.explicitThis; +c.explicitVoid = d.explicitD; +c.explicitVoid = d.explicitThis; +/// class-based polymorphic assignability (with inheritance!) /// +var Base1 = (function () { + function Base1() { + } + Base1.prototype.polymorphic = function () { return this.x; }; + Base1.prototype.explicit = 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.polymorphic = 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.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() { +} +var voidThis = new VoidThis(); +///// syntax-ish errors ///// +var ThisConstructor = (function () { + function ThisConstructor(n) { + this.n = n; + } + Object.defineProperty(ThisConstructor.prototype, "p", { + set: function () { + }, + enumerable: true, + configurable: true + }); + return ThisConstructor; +}()); +var thisConstructorType; +function notFirst(a, this) { return this.n; } +///// parse errors ///// +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/baselines/reference/thisTypeInObjectLiterals.js b/tests/baselines/reference/thisTypeInObjectLiterals.js new file mode 100644 index 0000000000000..5af13a41af858 --- /dev/null +++ b/tests/baselines/reference/thisTypeInObjectLiterals.js @@ -0,0 +1,56 @@ +//// [thisTypeInObjectLiterals.ts] +let o = { + d: "bar", + m() { + 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] +var o = { + d: "bar", + m: function () { + 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 new file mode 100644 index 0000000000000..9ae4a990d5b84 --- /dev/null +++ b/tests/baselines/reference/thisTypeInObjectLiterals.symbols @@ -0,0 +1,92 @@ +=== 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, --, --)) + } +} +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 new file mode 100644 index 0000000000000..0b1642092198d --- /dev/null +++ b/tests/baselines/reference/thisTypeInObjectLiterals.types @@ -0,0 +1,104 @@ +=== 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 + } +} +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/baselines/reference/throwInEnclosingStatements.symbols b/tests/baselines/reference/throwInEnclosingStatements.symbols index 63ed9dde5784a..858b6484e53b5 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/baselines/reference/unionThisTypeInFunctions.js b/tests/baselines/reference/unionThisTypeInFunctions.js new file mode 100644 index 0000000000000..0d4b535ff8b62 --- /dev/null +++ b/tests/baselines/reference/unionThisTypeInFunctions.js @@ -0,0 +1,18 @@ +//// [unionThisTypeInFunctions.ts] +interface Real { + method(this: this, n: number): void; + data: string; +} +interface Fake { + method(this: this, 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..eada12317504b --- /dev/null +++ b/tests/baselines/reference/unionThisTypeInFunctions.symbols @@ -0,0 +1,35 @@ +=== tests/cases/conformance/types/thisType/unionThisTypeInFunctions.ts === +interface Real { +>Real : Symbol(Real, Decl(unionThisTypeInFunctions.ts, 0, 0)) + + method(this: this, n: number): void; +>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(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(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(Fake.data, Decl(unionThisTypeInFunctions.ts, 5, 40)) +} +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..3c5181166b636 --- /dev/null +++ b/tests/baselines/reference/unionThisTypeInFunctions.types @@ -0,0 +1,37 @@ +=== tests/cases/conformance/types/thisType/unionThisTypeInFunctions.ts === +interface Real { +>Real : Real + + method(this: this, n: number): void; +>method : (this: this, n: number) => void +>this : this +>n : number + + data: string; +>data : string +} +interface Fake { +>Fake : Fake + + 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 : (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/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/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/compiler/noImplicitThisFunctions.ts b/tests/cases/compiler/noImplicitThisFunctions.ts new file mode 100644 index 0000000000000..45f0e5a1eb9ea --- /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; +} + +// error: `this` is `window`, but is still of type `any` +let f4: (b: number) => number = b => this.c + b; 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; diff --git a/tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts b/tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts new file mode 100644 index 0000000000000..b151961e324e1 --- /dev/null +++ b/tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts @@ -0,0 +1,47 @@ +interface I { + n: number; + 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 = { + 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; +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; +i.explicitThis = function(m) { + return this.n.length; // error, this.n: 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 new file mode 100644 index 0000000000000..481e1630092b5 --- /dev/null +++ b/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts @@ -0,0 +1,193 @@ +// body checking +class B { + n: number; +} +class C { + n: number; + explicitThis(this: this, 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 { } +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; +} +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 this.m + n + 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; + }, +} +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; }; +// 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); +d.explicitC(12); +d.explicitProperty(12); +d.explicitThis(12); +let reconstructed: { + n: number, + explicitThis(this: C, m: number): number, // note: this: this is not allowed in an object literal type. + 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 +}; +reconstructed.explicitThis(10); +reconstructed.explicitProperty(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; +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) { 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 +c.explicitVoid = n => n; + +// class-based assignability +class Base1 { + x: number; + public polymorphic(this: this): number { return this.x; } + explicit(this: Base1): number { return this.x; } + static explicitStatic(this: typeof Base1): number { return this.y; } + static y: number; +} +class Derived1 extends Base1 { + y: number +} +class Base2 { + y: number + polymorphic(this: this): 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.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.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) { + 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 this.anything + a; } diff --git a/tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts b/tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts new file mode 100644 index 0000000000000..597fe5a836ed6 --- /dev/null +++ b/tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts @@ -0,0 +1,177 @@ +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; + } +} +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 +} +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; + }, +} +let implExplicitStructural = impl.explicitStructural; +implExplicitStructural(); // error, no 'a' in 'void' +let implExplicitInterface = impl.explicitInterface; +implExplicitInterface(); // 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; +} +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 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. + 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 +};; + +// 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.explicitD; +c.explicitC = d.explicitThis; +c.explicitThis = d.explicitD; +c.explicitThis = d.explicitThis; +c.explicitProperty = d.explicitD; +c.explicitThis = d.explicitThis; +c.explicitVoid = d.explicitD; +c.explicitVoid = d.explicitThis; + +/// class-based polymorphic assignability (with inheritance!) /// + +class Base1 { + x: number + public polymorphic(this: this): number { return this.x; } + explicit(this: Base1): number { return this.x; } + static explicitStatic(this: typeof Base1): number { return this.x; } +} +class Derived1 extends Base1 { + y: number +} +class Base2 { + y: number + polymorphic(this: this): 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.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(this: void) { + +} +let voidThis = new VoidThis(); + +///// syntax-ish errors ///// +class ThisConstructor { + constructor(this: ThisConstructor, private n: number) { + } + set p(this: void) { + } +} +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 ///// +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/conformance/types/thisType/thisTypeInObjectLiterals.ts b/tests/cases/conformance/types/thisType/thisTypeInObjectLiterals.ts new file mode 100644 index 0000000000000..cfdb0883fed02 --- /dev/null +++ b/tests/cases/conformance/types/thisType/thisTypeInObjectLiterals.ts @@ -0,0 +1,29 @@ +let o = { + d: "bar", + m() { + 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; diff --git a/tests/cases/conformance/types/thisType/unionThisTypeInFunctions.ts b/tests/cases/conformance/types/thisType/unionThisTypeInFunctions.ts new file mode 100644 index 0000000000000..4f74058cc487d --- /dev/null +++ b/tests/cases/conformance/types/thisType/unionThisTypeInFunctions.ts @@ -0,0 +1,11 @@ +interface Real { + method(this: this, n: number): void; + data: string; +} +interface Fake { + method(this: this, n: number): void; + data: number; +} +function test(r: Real | Fake) { + r.method(12); +} 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/memberListOnExplicitThis.ts b/tests/cases/fourslash/memberListOnExplicitThis.ts new file mode 100644 index 0000000000000..b776a7c06417e --- /dev/null +++ b/tests/cases/fourslash/memberListOnExplicitThis.ts @@ -0,0 +1,29 @@ +/// + +////interface Restricted { +//// n: number; +////} +////class C1 implements Restricted { +//// n: number; +//// m: number; +//// f(this: this) {this./*1*/} // test on 'this.' +//// g(this: Restricted) {this./*2*/} +////} +////function f(this: void) {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'); + diff --git a/tests/cases/fourslash/quickInfoOnThis.ts b/tests/cases/fourslash/quickInfoOnThis.ts index c4eecfca5d5df..91083d41e6b7c 100644 --- a/tests/cases/fourslash/quickInfoOnThis.ts +++ b/tests/cases/fourslash/quickInfoOnThis.ts @@ -1,15 +1,95 @@ /// - -////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 explicitThis(this: this) { +//// wrapper( +//// function explicitVoid(this: void) { +//// 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 explicitThis(this: this) { +//// console.log(th/*7*/is); +//// } +//// public explicitClass(this: Bar) { +//// console.log(thi/*8*/s); +//// } +////} +//// +////function implicitAny(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); +////} +//// +////interface ContextualInterface { +//// m: number; +//// method(this: this, n: number); +////} +////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(); +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('any'); +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'); + +verify.quickInfoIs('(parameter) this: {\n n: number;\n}'); +goTo.marker('15'); +verify.quickInfoIs('this: {\n n: number;\n}'); + +goTo.marker('16'); +verify.quickInfoIs('this: ContextualInterface'); +goTo.marker('17'); +verify.quickInfoIs('(parameter) this: void'); 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"); 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'); diff --git a/tests/cases/unittests/cachingInServerLSHost.ts b/tests/cases/unittests/cachingInServerLSHost.ts index 2b6e24e5770c9..58bcd76e2465f 100644 --- a/tests/cases/unittests/cachingInServerLSHost.ts +++ b/tests/cases/unittests/cachingInServerLSHost.ts @@ -129,7 +129,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); @@ -153,7 +153,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"`; @@ -198,7 +198,7 @@ module ts { fileExistsCalledForBar = fileName.indexOf("/bar.") !== -1; } - return originalFileExists(fileName); + return originalFileExists.call(serverHost, fileName); }; let { project, rootScriptInfo } = createProject(root.name, serverHost);