diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index be751758126..9f10767fa1b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4174,6 +4174,11 @@ namespace ts { } function getWidenedTypeFromJSSpecialPropertyDeclarations(symbol: Symbol) { + // function/class/{} assignments are fresh declarations, not property assignments: + const specialDeclaration = getAssignedJavascriptInitializer(symbol.valueDeclaration); + if (specialDeclaration) { + return getWidenedLiteralType(checkExpressionCached(specialDeclaration)); + } const types: Type[] = []; let definedInConstructor = false; let definedInMethod = false; @@ -4367,18 +4372,6 @@ namespace ts { if (isInJavaScriptFile(declaration) && isJSDocPropertyLikeTag(declaration) && declaration.typeExpression) { return links.type = getTypeFromTypeNode(declaration.typeExpression.type); } - if (isInJavaScriptFile(declaration) && isDeclarationOfDefaultedJavascriptContainerExpression(declaration)) { - // !!! (probably out of place, probably not the right function to call) - return links.type = checkExpression(((declaration as VariableDeclaration).initializer as BinaryExpression).right); - } - if (isInJavaScriptFile(declaration) && isAssignmentOfDefaultedJavascriptContainerExpression(declaration.parent)) { - // !!! (probably out of place, probably not the right function to call) - return links.type = checkExpression(((declaration.parent as BinaryExpression).right as BinaryExpression).right); - } - // TODO: Not sure this is needed (probably, but I need to write a test case for it) - if (isInJavaScriptFile(declaration) && isAssignmentOfJavascriptContainerExpression(declaration)) { - return links.type = checkExpression((declaration.parent as BinaryExpression).right); - } // Handle variable, parameter or property if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) { return unknownType; @@ -4399,7 +4392,6 @@ namespace ts { || isIdentifier(declaration) || (isMethodDeclaration(declaration) && !isObjectLiteralMethod(declaration)) || isMethodSignature(declaration)) { - // TODO: Might need to add a case here? // Symbol is property of some kind that is merged with something - should use `getTypeOfFuncClassEnumModule` and not `getTypeOfVariableOrParameterOrProperty` if (symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.Enum | SymbolFlags.ValueModule)) { return getTypeOfFuncClassEnumModule(symbol); @@ -14120,7 +14112,8 @@ namespace ts { // expression has no contextual type, the right operand is contextually typed by the type of the left operand, // except for the special case of Javascript declarations of the form `namespace.prop = namespace.prop || {}` const type = getContextualType(binaryExpression); - return !type && node === right && !isDeclarationOfDefaultedJavascriptContainerExpression(binaryExpression.parent) && !isAssignmentOfDefaultedJavascriptContainerExpression(binaryExpression.parent) ? getTypeOfExpression(left, /*cache*/ true) : type; + return !type && node === right && !getDeclaredJavascriptInitializer(binaryExpression.parent) && !getAssignedJavascriptInitializer(binaryExpression) ? + getTypeOfExpression(left, /*cache*/ true) : type; case SyntaxKind.AmpersandAmpersandToken: case SyntaxKind.CommaToken: return node === right ? getContextualType(binaryExpression) : undefined; @@ -18994,7 +18987,7 @@ namespace ts { } function checkBinaryExpression(node: BinaryExpression, checkMode?: CheckMode) { - if (node.operatorToken.kind === SyntaxKind.BarBarToken && isInJavaScriptFile(node) && isAssignmentOfDefaultedJavascriptContainerExpression(node.parent)) { + if (node.operatorToken.kind === SyntaxKind.BarBarToken && isInJavaScriptFile(node) && getAssignedJavascriptInitializer(node)) { return checkExpression(node.right, checkMode); } return checkBinaryLikeExpression(node.left, node.operatorToken, node.right, checkMode, node); @@ -19352,10 +19345,11 @@ namespace ts { } function checkDeclarationInitializer(declaration: HasExpressionInitializer) { - const type = getTypeOfExpression(declaration.initializer, /*cache*/ true); + const initializer = isInJavaScriptFile(declaration) && getDeclaredJavascriptInitializer(declaration) || declaration.initializer; + const type = getTypeOfExpression(initializer, /*cache*/ true); return getCombinedNodeFlags(declaration) & NodeFlags.Const || (getCombinedModifierFlags(declaration) & ModifierFlags.Readonly && !isParameterPropertyDeclaration(declaration)) || - isTypeAssertion(declaration.initializer) ? type : getWidenedLiteralType(type); + isTypeAssertion(initializer) ? type : getWidenedLiteralType(type); } function isLiteralOfContextualType(candidateType: Type, contextualType: Type): boolean { @@ -21872,7 +21866,7 @@ namespace ts { // Node is the primary declaration of the symbol, just validate the initializer // Don't validate for-in initializer as it is already an error if (node.initializer && node.parent.parent.kind !== SyntaxKind.ForInStatement) { - const initializer = isInJavaScriptFile(node) && isDeclarationOfDefaultedJavascriptContainerExpression(node) ? (node.initializer as BinaryExpression).right : node.initializer; + const initializer = isInJavaScriptFile(node) && getDeclaredJavascriptInitializer(node) || node.initializer; checkTypeAssignableTo(checkExpressionCached(initializer), type, node, /*headMessage*/ undefined); checkParameterInitializer(node); } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 34a804f1528..1973108a76f 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1487,60 +1487,57 @@ namespace ts { } export function follow(symbol: Symbol) { - return symbol && isDeclarationOfJavascriptContainerExpression(symbol.valueDeclaration) ? (symbol.valueDeclaration as VariableDeclaration).initializer.symbol : - symbol && isDeclarationOfDefaultedJavascriptContainerExpression(symbol.valueDeclaration) ? ((symbol.valueDeclaration as VariableDeclaration).initializer as BinaryExpression).right.symbol : - symbol && symbol.valueDeclaration && isAssignmentOfDefaultedJavascriptContainerExpression(symbol.valueDeclaration.parent) ? (((symbol.valueDeclaration.parent as BinaryExpression).right as BinaryExpression).right as BinaryExpression).symbol : - symbol && isAssignmentOfJavascriptContainerExpression(symbol.valueDeclaration) ? ((symbol.valueDeclaration.parent as BinaryExpression).right as BinaryExpression).symbol : - symbol; + if (!symbol || !symbol.valueDeclaration) { + return symbol; + } + const declaration = symbol.valueDeclaration; + const e = getDeclaredJavascriptInitializer(declaration) || getAssignedJavascriptInitializer(declaration); + return e ? e.symbol : symbol; } /** * Returns true if the node is a variable declaration whose initializer is a function or class expression, or an empty object literal. * This function does not test if the node is in a JavaScript file or not. */ - export function isDeclarationOfJavascriptContainerExpression(node: Node): node is VariableDeclaration { - return node && - isVariableDeclaration(node) && - node.initializer && - isJavascriptContainerExpression(node.initializer); + export function getDeclaredJavascriptInitializer(node: Node) { + if (node && isVariableDeclaration(node) && node.initializer) { + return getJavascriptInitializer(node.initializer) || + isIdentifier(node.name) && getDefaultedJavascriptInitializer(node.name, node.initializer); + } } - function isJavascriptContainerExpression(e: Expression) { - return e.kind === SyntaxKind.FunctionExpression || - e.kind === SyntaxKind.ClassExpression || - isObjectLiteralExpression(e) && e.properties.length === 0; + export function getAssignedJavascriptInitializer(node: Node) { + return (isBinaryExpression(node) && node.operatorToken.kind === SyntaxKind.BarBarToken || isPropertyAccessExpression(node)) && + node.parent && isBinaryExpression(node.parent) && + node.parent.operatorToken.kind === SyntaxKind.EqualsToken && + (getJavascriptInitializer(node.parent.right) || getDefaultedJavascriptInitializer(node.parent.left as EntityNameExpression, node.parent.right)); } - export function isDeclarationOfDefaultedJavascriptContainerExpression(node: Node): node is VariableDeclaration { - return node && - isVariableDeclaration(node) && - node.initializer && - isBinaryExpression(node.initializer) && - isIdentifier(node.name) && - isSameName(node.name, node.initializer.left as EntityNameExpression) && - isJavascriptContainerExpression(node.initializer.right); + function getJavascriptInitializer(e: Expression) { + if(e.kind === SyntaxKind.FunctionExpression || + e.kind === SyntaxKind.ClassExpression || + isObjectLiteralExpression(e) && e.properties.length === 0) { + return e; + } } - export function isAssignmentOfJavascriptContainerExpression(node: Node) { - return node && - isPropertyAccessExpression(node) && - isBinaryExpression(node.parent) && - node.parent.right && - isJavascriptContainerExpression(node.parent.right); + function getDefaultedJavascriptInitializer(name: EntityNameExpression, initializer: Expression) { + const e = isBinaryExpression(initializer) && getJavascriptInitializer(initializer.right) + if (e && isSameEntityName(name, (initializer as BinaryExpression).left as EntityNameExpression)) { + return e; + } } - export function isAssignmentOfDefaultedJavascriptContainerExpression(node: Node) { - // or ... uh ... maybe not? usage is pretty inconvenient - // (changing what is the declaration might instead be the right answer) - return node && - isBinaryExpression(node) && - node.right && - isBinaryExpression(node.right) && - isSameName(node.left as EntityNameExpression, node.right.left as EntityNameExpression) && - isJavascriptContainerExpression(node.right.right); - } - - function isSameName(name: EntityNameExpression, initializer: EntityNameExpression): boolean { + /** + * Is the 'declared' name the same as the one in the initializer? + * @return true for identical entity names, as well as ones where the initializer is prefixed with + * 'window', 'self' or 'global'. For example: + * + * var my = my || {} + * var min = window.min || {} + * my.app = self.my.app || class { } + */ + function isSameEntityName(name: EntityNameExpression, initializer: EntityNameExpression): boolean { if (isIdentifier(name) && isIdentifier(initializer)) { return name.escapedText === initializer.escapedText; } @@ -1550,10 +1547,10 @@ namespace ts { (initializer.expression.escapedText === "window" as __String || initializer.expression.escapedText === "self" as __String || initializer.expression.escapedText === "global" as __String)) && - isSameName(name, initializer.name); + isSameEntityName(name, initializer.name); } if (isPropertyAccessExpression(name) && isPropertyAccessExpression(initializer)) { - return name.name.escapedText === initializer.name.escapedText && isSameName(name.expression, initializer.expression); + return name.name.escapedText === initializer.name.escapedText && isSameEntityName(name.expression, initializer.expression); } return false; } diff --git a/tests/baselines/reference/typeFromPropertyAssignment10.symbols b/tests/baselines/reference/typeFromPropertyAssignment10.symbols index 32430bfd5a1..55c3f1dfcef 100644 --- a/tests/baselines/reference/typeFromPropertyAssignment10.symbols +++ b/tests/baselines/reference/typeFromPropertyAssignment10.symbols @@ -13,11 +13,11 @@ Outer.app = Outer.app || {}; === tests/cases/conformance/salsa/someview.js === Outer.app.SomeView = (function () { ->Outer.app.SomeView : Symbol(app.SomeView, Decl(someview.js, 0, 0)) +>Outer.app.SomeView : Symbol(Outer.app.SomeView, Decl(someview.js, 0, 0)) >Outer.app : Symbol(app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) >Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(someview.js, 0, 0), Decl(application.js, 0, 0)) >app : Symbol(app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) ->SomeView : Symbol(app.SomeView, Decl(someview.js, 0, 0)) +>SomeView : Symbol(Outer.app.SomeView, Decl(someview.js, 0, 0)) var SomeView = function() { >SomeView : Symbol(SomeView, Decl(someview.js, 1, 7)) @@ -30,11 +30,11 @@ Outer.app.SomeView = (function () { })(); Outer.app.Inner = class { ->Outer.app.Inner : Symbol(app.Inner, Decl(someview.js, 5, 5)) +>Outer.app.Inner : Symbol(Outer.app.Inner, Decl(someview.js, 5, 5)) >Outer.app : Symbol(app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) >Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(someview.js, 0, 0), Decl(application.js, 0, 0)) >app : Symbol(app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) ->Inner : Symbol(app.Inner, Decl(someview.js, 5, 5)) +>Inner : Symbol(Outer.app.Inner, Decl(someview.js, 5, 5)) constructor() { /** @type {number} */ @@ -46,11 +46,11 @@ Outer.app.Inner = class { } var example = new Outer.app.Inner(); >example : Symbol(example, Decl(someview.js, 12, 3)) ->Outer.app.Inner : Symbol(app.Inner, Decl(someview.js, 5, 5)) +>Outer.app.Inner : Symbol(Outer.app.Inner, Decl(someview.js, 5, 5)) >Outer.app : Symbol(app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) >Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(someview.js, 0, 0), Decl(application.js, 0, 0)) >app : Symbol(app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) ->Inner : Symbol(app.Inner, Decl(someview.js, 5, 5)) +>Inner : Symbol(Outer.app.Inner, Decl(someview.js, 5, 5)) example.y; >example.y : Symbol((Anonymous class).y, Decl(someview.js, 7, 19)) @@ -59,11 +59,11 @@ example.y; /** @param {number} k */ Outer.app.statische = function (k) { ->Outer.app.statische : Symbol(app.statische, Decl(someview.js, 13, 10)) +>Outer.app.statische : Symbol(Outer.app.statische, Decl(someview.js, 13, 10)) >Outer.app : Symbol(app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) >Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(someview.js, 0, 0), Decl(application.js, 0, 0)) >app : Symbol(app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) ->statische : Symbol(app.statische, Decl(someview.js, 13, 10)) +>statische : Symbol(Outer.app.statische, Decl(someview.js, 13, 10)) >k : Symbol(k, Decl(someview.js, 15, 32)) return k ** k; @@ -90,11 +90,11 @@ Outer.app.Application = (function () { me.view = new Outer.app.SomeView(); >me : Symbol(me, Decl(application.js, 7, 11)) ->Outer.app.SomeView : Symbol(app.SomeView, Decl(someview.js, 0, 0)) +>Outer.app.SomeView : Symbol(Outer.app.SomeView, Decl(someview.js, 0, 0)) >Outer.app : Symbol(app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) >Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(someview.js, 0, 0), Decl(application.js, 0, 0)) >app : Symbol(app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) ->SomeView : Symbol(app.SomeView, Decl(someview.js, 0, 0)) +>SomeView : Symbol(Outer.app.SomeView, Decl(someview.js, 0, 0)) }; return Application; @@ -112,11 +112,11 @@ var app = new Outer.app.Application(); var inner = new Outer.app.Inner(); >inner : Symbol(inner, Decl(main.js, 1, 3)) ->Outer.app.Inner : Symbol(app.Inner, Decl(someview.js, 5, 5)) +>Outer.app.Inner : Symbol(Outer.app.Inner, Decl(someview.js, 5, 5)) >Outer.app : Symbol(app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) >Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(someview.js, 0, 0), Decl(application.js, 0, 0)) >app : Symbol(app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) ->Inner : Symbol(app.Inner, Decl(someview.js, 5, 5)) +>Inner : Symbol(Outer.app.Inner, Decl(someview.js, 5, 5)) inner.y; >inner.y : Symbol((Anonymous class).y, Decl(someview.js, 7, 19)) @@ -133,9 +133,9 @@ x.y; >y : Symbol((Anonymous class).y, Decl(someview.js, 7, 19)) Outer.app.statische(101); // Infinity, duh ->Outer.app.statische : Symbol(app.statische, Decl(someview.js, 13, 10)) +>Outer.app.statische : Symbol(Outer.app.statische, Decl(someview.js, 13, 10)) >Outer.app : Symbol(app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) >Outer : Symbol(Outer, Decl(module.js, 0, 3), Decl(someview.js, 0, 0), Decl(application.js, 0, 0)) >app : Symbol(app, Decl(module.js, 0, 24), Decl(someview.js, 0, 6), Decl(application.js, 0, 6)) ->statische : Symbol(app.statische, Decl(someview.js, 13, 10)) +>statische : Symbol(Outer.app.statische, Decl(someview.js, 13, 10)) diff --git a/tests/baselines/reference/typeFromPropertyAssignment9.symbols b/tests/baselines/reference/typeFromPropertyAssignment9.symbols index 282275b556c..a4211cdefe7 100644 --- a/tests/baselines/reference/typeFromPropertyAssignment9.symbols +++ b/tests/baselines/reference/typeFromPropertyAssignment9.symbols @@ -1,12 +1,12 @@ === tests/cases/conformance/salsa/a.js === var my = my || {}; ->my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 5, 14), Decl(a.js, 7, 34), Decl(a.js, 19, 1)) ->my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 5, 14), Decl(a.js, 7, 34), Decl(a.js, 19, 1)) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 5, 14), Decl(a.js, 7, 34), Decl(a.js, 12, 33) ... and 1 more) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 5, 14), Decl(a.js, 7, 34), Decl(a.js, 12, 33) ... and 1 more) /** @param {number} n */ my.method = function(n) { >my.method : Symbol(method, Decl(a.js, 0, 18)) ->my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 5, 14), Decl(a.js, 7, 34), Decl(a.js, 19, 1)) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 5, 14), Decl(a.js, 7, 34), Decl(a.js, 12, 33) ... and 1 more) >method : Symbol(method, Decl(a.js, 0, 18)) >n : Symbol(n, Decl(a.js, 2, 21)) @@ -15,28 +15,28 @@ my.method = function(n) { } my.number = 1; >my.number : Symbol(number, Decl(a.js, 4, 1)) ->my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 5, 14), Decl(a.js, 7, 34), Decl(a.js, 19, 1)) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 5, 14), Decl(a.js, 7, 34), Decl(a.js, 12, 33) ... and 1 more) >number : Symbol(number, Decl(a.js, 4, 1)) my.object = {}; >my.object : Symbol(object, Decl(a.js, 5, 14)) ->my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 5, 14), Decl(a.js, 7, 34), Decl(a.js, 19, 1)) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 5, 14), Decl(a.js, 7, 34), Decl(a.js, 12, 33) ... and 1 more) >object : Symbol(object, Decl(a.js, 5, 14)) my.predicate = my.predicate || {}; ->my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 20, 3)) ->my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 5, 14), Decl(a.js, 7, 34), Decl(a.js, 19, 1)) ->predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 20, 3)) ->my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 20, 3)) ->my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 5, 14), Decl(a.js, 7, 34), Decl(a.js, 19, 1)) ->predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 20, 3)) +>my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 23, 3)) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 5, 14), Decl(a.js, 7, 34), Decl(a.js, 12, 33) ... and 1 more) +>predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 23, 3)) +>my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 23, 3)) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 5, 14), Decl(a.js, 7, 34), Decl(a.js, 12, 33) ... and 1 more) +>predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 23, 3)) my.predicate.query = function () { ->my.predicate.query : Symbol(query, Decl(a.js, 7, 34)) ->my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 20, 3)) ->my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 5, 14), Decl(a.js, 7, 34), Decl(a.js, 19, 1)) ->predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 20, 3)) ->query : Symbol(query, Decl(a.js, 7, 34)) +>my.predicate.query : Symbol(query, Decl(a.js, 7, 34), Decl(a.js, 13, 13)) +>my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 23, 3)) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 5, 14), Decl(a.js, 7, 34), Decl(a.js, 12, 33) ... and 1 more) +>predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 23, 3)) +>query : Symbol(query, Decl(a.js, 7, 34), Decl(a.js, 13, 13)) var me = this; >me : Symbol(me, Decl(a.js, 9, 7)) @@ -48,74 +48,85 @@ my.predicate.query = function () { }; var q = new my.predicate.query(); >q : Symbol(q, Decl(a.js, 12, 3)) ->my.predicate.query : Symbol(query, Decl(a.js, 7, 34)) ->my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 20, 3)) ->my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 5, 14), Decl(a.js, 7, 34), Decl(a.js, 19, 1)) ->predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 20, 3)) ->query : Symbol(query, Decl(a.js, 7, 34)) +>my.predicate.query : Symbol(query, Decl(a.js, 7, 34), Decl(a.js, 13, 13)) +>my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 23, 3)) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 5, 14), Decl(a.js, 7, 34), Decl(a.js, 12, 33) ... and 1 more) +>predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 23, 3)) +>query : Symbol(query, Decl(a.js, 7, 34), Decl(a.js, 13, 13)) +my.predicate.query.another = function () { +>my.predicate.query.another : Symbol((Anonymous function).another, Decl(a.js, 12, 33)) +>my.predicate.query : Symbol(query, Decl(a.js, 7, 34), Decl(a.js, 13, 13)) +>my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 23, 3)) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 5, 14), Decl(a.js, 7, 34), Decl(a.js, 12, 33) ... and 1 more) +>predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 23, 3)) +>query : Symbol(query, Decl(a.js, 7, 34), Decl(a.js, 13, 13)) +>another : Symbol((Anonymous function).another, Decl(a.js, 12, 33)) + + return 1; +} my.predicate.query.result = 'none' ->my.predicate.query.result : Symbol((Anonymous function).result, Decl(a.js, 12, 33)) ->my.predicate.query : Symbol(query, Decl(a.js, 7, 34)) ->my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 20, 3)) ->my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 5, 14), Decl(a.js, 7, 34), Decl(a.js, 19, 1)) ->predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 20, 3)) ->query : Symbol(query, Decl(a.js, 7, 34)) ->result : Symbol((Anonymous function).result, Decl(a.js, 12, 33)) +>my.predicate.query.result : Symbol((Anonymous function).result, Decl(a.js, 15, 1)) +>my.predicate.query : Symbol(query, Decl(a.js, 7, 34), Decl(a.js, 13, 13)) +>my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 23, 3)) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 5, 14), Decl(a.js, 7, 34), Decl(a.js, 12, 33) ... and 1 more) +>predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 23, 3)) +>query : Symbol(query, Decl(a.js, 7, 34), Decl(a.js, 13, 13)) +>result : Symbol((Anonymous function).result, Decl(a.js, 15, 1)) /** @param {number} first * @param {number} second */ my.predicate.sort = my.predicate.sort || function (first, second) { ->my.predicate.sort : Symbol(sort, Decl(a.js, 13, 34)) ->my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 20, 3)) ->my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 5, 14), Decl(a.js, 7, 34), Decl(a.js, 19, 1)) ->predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 20, 3)) ->sort : Symbol(sort, Decl(a.js, 13, 34)) ->my.predicate.sort : Symbol(sort, Decl(a.js, 13, 34)) ->my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 20, 3)) ->my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 5, 14), Decl(a.js, 7, 34), Decl(a.js, 19, 1)) ->predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 20, 3)) ->sort : Symbol(sort, Decl(a.js, 13, 34)) ->first : Symbol(first, Decl(a.js, 17, 51)) ->second : Symbol(second, Decl(a.js, 17, 57)) +>my.predicate.sort : Symbol(sort, Decl(a.js, 16, 34)) +>my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 23, 3)) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 5, 14), Decl(a.js, 7, 34), Decl(a.js, 12, 33) ... and 1 more) +>predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 23, 3)) +>sort : Symbol(sort, Decl(a.js, 16, 34)) +>my.predicate.sort : Symbol(sort, Decl(a.js, 16, 34)) +>my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 23, 3)) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 5, 14), Decl(a.js, 7, 34), Decl(a.js, 12, 33) ... and 1 more) +>predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 23, 3)) +>sort : Symbol(sort, Decl(a.js, 16, 34)) +>first : Symbol(first, Decl(a.js, 20, 51)) +>second : Symbol(second, Decl(a.js, 20, 57)) return first > second ? first : second; ->first : Symbol(first, Decl(a.js, 17, 51)) ->second : Symbol(second, Decl(a.js, 17, 57)) ->first : Symbol(first, Decl(a.js, 17, 51)) ->second : Symbol(second, Decl(a.js, 17, 57)) +>first : Symbol(first, Decl(a.js, 20, 51)) +>second : Symbol(second, Decl(a.js, 20, 57)) +>first : Symbol(first, Decl(a.js, 20, 51)) +>second : Symbol(second, Decl(a.js, 20, 57)) } my.predicate.type = class { ->my.predicate.type : Symbol(type, Decl(a.js, 19, 1)) ->my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 20, 3)) ->my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 5, 14), Decl(a.js, 7, 34), Decl(a.js, 19, 1)) ->predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 20, 3)) ->type : Symbol(type, Decl(a.js, 19, 1)) +>my.predicate.type : Symbol(type, Decl(a.js, 22, 1)) +>my.predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 23, 3)) +>my : Symbol(my, Decl(a.js, 0, 3), Decl(a.js, 0, 18), Decl(a.js, 5, 14), Decl(a.js, 7, 34), Decl(a.js, 12, 33) ... and 1 more) +>predicate : Symbol(predicate, Decl(a.js, 6, 15), Decl(a.js, 8, 3), Decl(a.js, 13, 3), Decl(a.js, 23, 3)) +>type : Symbol(type, Decl(a.js, 22, 1)) m() { return 101; } ->m : Symbol((Anonymous class).m, Decl(a.js, 20, 27)) +>m : Symbol((Anonymous class).m, Decl(a.js, 23, 27)) } // global-ish prefixes var min = window.min || {}; ->min : Symbol(min, Decl(a.js, 26, 3)) +>min : Symbol(min, Decl(a.js, 29, 3)) min.nest = this.min.nest || function () { }; ->min.nest : Symbol(nest, Decl(a.js, 26, 27)) ->min : Symbol(min, Decl(a.js, 26, 3)) ->nest : Symbol(nest, Decl(a.js, 26, 27)) +>min.nest : Symbol(nest, Decl(a.js, 29, 27)) +>min : Symbol(min, Decl(a.js, 29, 3)) +>nest : Symbol(nest, Decl(a.js, 29, 27)) min.nest.other = self.min.nest.other || class { }; ->min.nest.other : Symbol((Anonymous function).other, Decl(a.js, 27, 44)) ->min.nest : Symbol(nest, Decl(a.js, 26, 27)) ->min : Symbol(min, Decl(a.js, 26, 3)) ->nest : Symbol(nest, Decl(a.js, 26, 27)) ->other : Symbol((Anonymous function).other, Decl(a.js, 27, 44)) +>min.nest.other : Symbol((Anonymous function).other, Decl(a.js, 30, 44)) +>min.nest : Symbol(nest, Decl(a.js, 29, 27)) +>min : Symbol(min, Decl(a.js, 29, 3)) +>nest : Symbol(nest, Decl(a.js, 29, 27)) +>other : Symbol((Anonymous function).other, Decl(a.js, 30, 44)) min.property = global.min.property || {}; ->min.property : Symbol(property, Decl(a.js, 28, 50)) ->min : Symbol(min, Decl(a.js, 26, 3)) ->property : Symbol(property, Decl(a.js, 28, 50)) +>min.property : Symbol(property, Decl(a.js, 31, 50)) +>min : Symbol(min, Decl(a.js, 29, 3)) +>property : Symbol(property, Decl(a.js, 31, 50)) diff --git a/tests/baselines/reference/typeFromPropertyAssignment9.types b/tests/baselines/reference/typeFromPropertyAssignment9.types index 6bdcbf36778..bd1740fa6e1 100644 --- a/tests/baselines/reference/typeFromPropertyAssignment9.types +++ b/tests/baselines/reference/typeFromPropertyAssignment9.types @@ -1,15 +1,15 @@ === tests/cases/conformance/salsa/a.js === var my = my || {}; ->my : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; } ->my || {} : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; } ->my : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; } ->{} : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; } +>my : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; } +>my || {} : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; } +>my : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; } +>{} : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; } /** @param {number} n */ my.method = function(n) { >my.method = function(n) { return n + 1;} : (n: number) => number >my.method : (n: number) => number ->my : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; } +>my : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; } >method : (n: number) => number >function(n) { return n + 1;} : (n: number) => number >n : number @@ -22,45 +22,45 @@ my.method = function(n) { my.number = 1; >my.number = 1 : 1 >my.number : number ->my : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; } +>my : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; } >number : number >1 : 1 my.object = {}; >my.object = {} : { [x: string]: any; } >my.object : { [x: string]: any; } ->my : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; } +>my : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; } >object : { [x: string]: any; } >{} : { [x: string]: any; } my.predicate = my.predicate || {}; ->my.predicate = my.predicate || {} : { [x: string]: any; query: { (): void; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); } ->my.predicate : { [x: string]: any; query: { (): void; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); } ->my : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; } ->predicate : { [x: string]: any; query: { (): void; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); } ->my.predicate || {} : { [x: string]: any; query: { (): void; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); } ->my.predicate : { [x: string]: any; query: { (): void; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); } ->my : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; } ->predicate : { [x: string]: any; query: { (): void; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); } ->{} : { [x: string]: any; query: { (): void; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); } +>my.predicate = my.predicate || {} : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); } +>my.predicate : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); } +>my : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; } +>predicate : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); } +>my.predicate || {} : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); } +>my.predicate : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); } +>my : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; } +>predicate : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); } +>{} : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); } my.predicate.query = function () { ->my.predicate.query = function () { var me = this; me.property = false;} : { (): void; result: string; } ->my.predicate.query : { (): void; result: string; } ->my.predicate : { [x: string]: any; query: { (): void; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); } ->my : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; } ->predicate : { [x: string]: any; query: { (): void; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); } ->query : { (): void; result: string; } ->function () { var me = this; me.property = false;} : { (): void; result: string; } +>my.predicate.query = function () { var me = this; me.property = false;} : { (): void; another: () => number; result: string; } +>my.predicate.query : { (): void; another: () => number; result: string; } +>my.predicate : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); } +>my : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; } +>predicate : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); } +>query : { (): void; another: () => number; result: string; } +>function () { var me = this; me.property = false;} : { (): void; another: () => number; result: string; } var me = this; ->me : { [x: string]: any; query: { (): void; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); } ->this : { [x: string]: any; query: { (): void; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); } +>me : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); } +>this : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); } me.property = false; >me.property = false : false >me.property : any ->me : { [x: string]: any; query: { (): void; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); } +>me : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); } >property : any >false : false @@ -68,20 +68,34 @@ my.predicate.query = function () { var q = new my.predicate.query(); >q : any >new my.predicate.query() : any ->my.predicate.query : { (): void; result: string; } ->my.predicate : { [x: string]: any; query: { (): void; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); } ->my : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; } ->predicate : { [x: string]: any; query: { (): void; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); } ->query : { (): void; result: string; } +>my.predicate.query : { (): void; another: () => number; result: string; } +>my.predicate : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); } +>my : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; } +>predicate : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); } +>query : { (): void; another: () => number; result: string; } +my.predicate.query.another = function () { +>my.predicate.query.another = function () { return 1;} : () => number +>my.predicate.query.another : () => number +>my.predicate.query : { (): void; another: () => number; result: string; } +>my.predicate : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); } +>my : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; } +>predicate : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); } +>query : { (): void; another: () => number; result: string; } +>another : () => number +>function () { return 1;} : () => number + + return 1; +>1 : 1 +} my.predicate.query.result = 'none' >my.predicate.query.result = 'none' : "none" >my.predicate.query.result : string ->my.predicate.query : { (): void; result: string; } ->my.predicate : { [x: string]: any; query: { (): void; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); } ->my : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; } ->predicate : { [x: string]: any; query: { (): void; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); } ->query : { (): void; result: string; } +>my.predicate.query : { (): void; another: () => number; result: string; } +>my.predicate : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); } +>my : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; } +>predicate : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); } +>query : { (): void; another: () => number; result: string; } >result : string >'none' : "none" @@ -91,15 +105,15 @@ my.predicate.query.result = 'none' my.predicate.sort = my.predicate.sort || function (first, second) { >my.predicate.sort = my.predicate.sort || function (first, second) { return first > second ? first : second;} : (first: number, second: number) => number >my.predicate.sort : (first: number, second: number) => number ->my.predicate : { [x: string]: any; query: { (): void; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); } ->my : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; } ->predicate : { [x: string]: any; query: { (): void; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); } +>my.predicate : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); } +>my : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; } +>predicate : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); } >sort : (first: number, second: number) => number >my.predicate.sort || function (first, second) { return first > second ? first : second;} : (first: number, second: number) => number >my.predicate.sort : (first: number, second: number) => number ->my.predicate : { [x: string]: any; query: { (): void; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); } ->my : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; } ->predicate : { [x: string]: any; query: { (): void; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); } +>my.predicate : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); } +>my : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; } +>predicate : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); } >sort : (first: number, second: number) => number >function (first, second) { return first > second ? first : second;} : (first: number, second: number) => number >first : number @@ -116,9 +130,9 @@ my.predicate.sort = my.predicate.sort || function (first, second) { my.predicate.type = class { >my.predicate.type = class { m() { return 101; }} : typeof (Anonymous class) >my.predicate.type : typeof (Anonymous class) ->my.predicate : { [x: string]: any; query: { (): void; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); } ->my : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; } ->predicate : { [x: string]: any; query: { (): void; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); } +>my.predicate : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); } +>my : { [x: string]: any; method: (n: number) => number; number: number; object: { [x: string]: any; }; predicate: { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); }; } +>predicate : { [x: string]: any; query: { (): void; another: () => number; result: string; }; sort: (first: number, second: number) => number; type: typeof (Anonymous class); } >type : typeof (Anonymous class) >class { m() { return 101; }} : typeof (Anonymous class) diff --git a/tests/cases/conformance/salsa/typeFromPropertyAssignment9.ts b/tests/cases/conformance/salsa/typeFromPropertyAssignment9.ts index 5340225a47f..cdb2a0e2af3 100644 --- a/tests/cases/conformance/salsa/typeFromPropertyAssignment9.ts +++ b/tests/cases/conformance/salsa/typeFromPropertyAssignment9.ts @@ -17,6 +17,9 @@ my.predicate.query = function () { me.property = false; }; var q = new my.predicate.query(); +my.predicate.query.another = function () { + return 1; +} my.predicate.query.result = 'none' /** @param {number} first * @param {number} second