code: public static TypeDeclarationNode functionType(
        Node returnType, LinkedHashMap<String, TypeDeclarationNode> requiredParams,
        LinkedHashMap<String, TypeDeclarationNode> optionalParams,
        String restName, TypeDeclarationNode restType) {
      TypeDeclarationNode node = new TypeDeclarationNode(Token.FUNCTION_TYPE, returnType);
      checkNotNull(requiredParams);
      checkNotNull(optionalParams);
  
      for (Map.Entry<String, TypeDeclarationNode> param : requiredParams.entrySet()) {
        Node name = IR.name(param.getKey());
        node.addChildToBack(maybeAddType(name, param.getValue()));
      }
  
      for (Map.Entry<String, TypeDeclarationNode> param : optionalParams.entrySet()) {
        Node name = IR.name(param.getKey());
        name.putBooleanProp(Node.OPT_ES6_TYPED, true);
        node.addChildToBack(maybeAddType(name, param.getValue()));
      }
  
      if (restName != null) {
        Node rest = new Node(Token.REST, IR.name(restName));
        node.addChildToBack(maybeAddType(rest, restType));
      }
      return node;
    }
docs: Represents a function type.
  Closure has syntax like {@code {function(string, boolean):number}}
  Closure doesn't include parameter names. If the parameter types are unnamed,
  arbitrary names can be substituted, eg. p1, p2, etc.
  
  <p>Example:
  <pre>
  FUNCTION_TYPE
  NUMBER_TYPE
  STRING_KEY p1 [declared_type_expr: STRING_TYPE]
  STRING_KEY p2 [declared_type_expr: BOOLEAN_TYPE]
  </pre>
  @param returnType the type returned by the function, possibly ANY_TYPE
  @param requiredParams the names and types of the required parameters.
  @param optionalParams the names and types of the optional parameters.
  @param restName the name of the rest parameter, if any.
  @param restType the type of the rest parameter, if any.