docs: function getRealNodeSymbol(checker, node) {
      const getPropertySymbolsFromContextualType = ts.getPropertySymbolsFromContextualType;
      const getContainingObjectLiteralElement = ts.getContainingObjectLiteralElement;
      const getNameFromPropertyName = ts.getNameFromPropertyName;
      // Go to the original declaration for cases:
      //
      //   (1) when the aliased symbol was declared in the location(parent).
      //   (2) when the aliased symbol is originating from an import.
      //
      function shouldSkipAlias(node, declaration) {
          if (node.kind !== ts.SyntaxKind.Identifier) {
              return false;
          }
          if (node.parent === declaration) {
              return true;
          }
          switch (declaration.kind) {
              case ts.SyntaxKind.ImportClause:
              case ts.SyntaxKind.ImportEqualsDeclaration:
                  return true;
              case ts.SyntaxKind.ImportSpecifier:
                  return declaration.parent.kind === ts.SyntaxKind.NamedImports;
              default:
                  return false;
          }
      }
      if (!ts.isShorthandPropertyAssignment(node)) {
          if (node.getChildCount() !== 0) {
              return [null, null];
          }
      }
      const { parent } = node;
      let symbol = checker.getSymbolAtLocation(node);
      let importNode = null;
      // If this is an alias, and the request came at the declaration location
      // get the aliased symbol instead. This allows for goto def on an import e.g.
      //   import {A, B} from "mod";
      // to jump to the implementation directly.
      if (symbol && symbol.flags & ts.SymbolFlags.Alias && shouldSkipAlias(node, symbol.declarations[0])) {
          const aliased = checker.getAliasedSymbol(symbol);
          if (aliased.declarations) {
              // We should mark the import as visited
              importNode = symbol.declarations[0];
              symbol = aliased;
          }
      }
      if (symbol) {
          // Because name in short-hand property assignment has two different meanings: property name and property value,
          // using go-to-definition at such position should go to the variable declaration of the property value rather than
          // go to the declaration of the property name (in this case stay at the same position). However, if go-to-definition
          // is performed at the location of property access, we would like to go to definition of the property in the short-hand
          // assignment. This case and others are handled by the following code.
          if (node.parent.kind === ts.SyntaxKind.ShorthandPropertyAssignment) {
              symbol = checker.getShorthandAssignmentValueSymbol(symbol.valueDeclaration);
          }
          // If the node is the name of a BindingElement within an ObjectBindingPattern instead of just returning the
          // declaration the symbol (which is itself), we should try to get to the original type of the ObjectBindingPattern
          // and return the property declaration for the referenced property.
          // For example:
          //      import('./foo').then(({ b/*goto*/ar }) => undefined); => should get use to the declaration in file "./foo"
          //
          //      function bar<T>(onfulfilled: (value: T) => void) { //....}
          //      interface Test {
          //          pr/*destination*/op1: number
          //      }
          //      bar<Test>(({pr/*goto*/op1})=>{});
          if (ts.isPropertyName(node) && ts.isBindingElement(parent) && ts.isObjectBindingPattern(parent.parent) &&
              (node === (parent.propertyName || parent.name))) {
              const name = getNameFromPropertyName(node);
              const type = checker.getTypeAtLocation(parent.parent);
              if (name && type) {
                  if (type.isUnion()) {
                      const prop = type.types[0].getProperty(name);
                      if (prop) {
                          symbol = prop;
                      }
                  }
                  else {
                      const prop = type.getProperty(name);
                      if (prop) {
                          symbol = prop;
                      }
                  }
              }
          }
          // If the current location we want to find its definition is in an object literal, try to get the contextual type for the
          // object literal, lookup the property symbol in the contextual type, and use this for goto-definition.
          // For example
          //      interface Props{
          //          /*first*/prop1: number
          //          prop2: boolean
          //      }
          //      function Foo(arg: Props) {}
          //      Foo( { pr/*1*/op1: 10, prop2: false })
          const element = getContainingObjectLiteralElement(node);
          if (element) {
              const contextualType = element && checker.getContextualType(element.parent);
              if (contextualType) {
                  const propertySymbols = getPropertySymbolsFromContextualType(element, checker, contextualType, /*unionSymbolOk*/ false);
                  if (propertySymbols) {
                      symbol = propertySymbols[0];
                  }
              }
          }
      }
      if (symbol && symbol.declarations) {
          return [symbol, importNode];
      }
      return [null, null];
  }