function getContextualType(node) {
            if (isInsideWithStatementBody(node)) {
                // We cannot answer semantic questions within a with block, do not proceed any further
                return undefined;
            }
            if (node.contextualType) {
                return node.contextualType;
            }
            var parent = node.parent;
            switch (parent.kind) {
                case 211 /* VariableDeclaration */:
                case 138 /* Parameter */:
                case 141 /* PropertyDeclaration */:
                case 140 /* PropertySignature */:
                case 163 /* BindingElement */:
                    return getContextualTypeForInitializerExpression(node);
                case 174 /* ArrowFunction */:
                case 204 /* ReturnStatement */:
                    return getContextualTypeForReturnExpression(node);
                case 184 /* YieldExpression */:
                    return getContextualTypeForYieldOperand(parent);
                case 168 /* CallExpression */:
                case 169 /* NewExpression */:
                    return getContextualTypeForArgument(parent, node);
                case 171 /* TypeAssertionExpression */:
                case 189 /* AsExpression */:
                    return getTypeFromTypeNode(parent.type);
                case 181 /* BinaryExpression */:
                    return getContextualTypeForBinaryOperand(node);
                case 245 /* PropertyAssignment */:
                    return getContextualTypeForObjectLiteralElement(parent);
                case 164 /* ArrayLiteralExpression */:
                    return getContextualTypeForElementExpression(node);
                case 182 /* ConditionalExpression */:
                    return getContextualTypeForConditionalOperand(node);
                case 190 /* TemplateSpan */:
                    ts.Debug.assert(parent.parent.kind === 183 /* TemplateExpression */);
                    return getContextualTypeForSubstitutionExpression(parent.parent, node);
                case 172 /* ParenthesizedExpression */:
                    return getContextualType(parent);
                case 240 /* JsxExpression */:
                case 239 /* JsxSpreadAttribute */:
                    return getContextualTypeForJsxExpression(parent);
            }
            return undefined;
        }
Woah! Do you really want to use this function?

Unless you're trying to get the *non-apparent* type for a
value-literal type or you're authoring relevant portions of this algorithm,
you probably meant to use 'getApparentTypeOfContextualType'.
Otherwise this may not be very useful.

In cases where you *are* working on this function, you should understand
when it is appropriate to use 'getContextualType' and 'getApparentTypeOfContetxualType'.

  - Use 'getContextualType' when you are simply going to propagate the result to the expression.
  - Use 'getApparentTypeOfContextualType' when you're going to need the members of the type.

@param node the expression whose contextual type will be returned.
@returns the contextual type of an expression.