docs: function exportDeclarations() {
  
      var docs = getJSONDocs();
      var sugarjs = getDeclaredNamespace('sugarjs');
  
      var extendedInterfaces = [], nativeNames = [];
  
      function getNamespaceTypesMerged(num, suffixVal, join, supplementary) {
        var types = nativeNames.concat(supplementary || []);
        var indent = ' '.repeat(num);
        return types.map(function(type) {
          var suffix = typeof suffixVal === 'function' ? suffixVal(type) : suffixVal;
          return type + suffix;
        }).join(' ' + join + '\n' + indent);
      }
  
      function getChainableNameExternal(type) {
        return '.Chainable' + getChainableBaseGenerics(type, CHAINABLE_RAW_TYPE, 'any');
      }
  
      function writeDeclarations(filename, declarations) {
        declarations = compact(declarations);
        var hasNoDeclarations = declarations.every(function(dec) {
          return /^\/\//.test(dec);
        });
        if (hasNoDeclarations) {
          return;
        }
        writeFile(path.join(basePath || '', filename), compact(declarations).join('\n\n'));
      }
  
      sugarjs.interfaces.push(getLocaleInterface(docs.namespaces));
  
      // Sort namespaces for Sugar to come before SugarNamespace
      // as it has ExtendOptions which are defined first.
      docs.namespaces.sort(collateNamespaces);
  
      docs.namespaces.forEach(function(namespace) {
  
        function addExtras(module) {
          addCallbackTypes(module);
          addOptionsInterfaces(module);
        }
  
        function addCallbackTypes(module) {
  
          // If the param has multiple types, then move callbacks into the
          // module as named types. Only do this if there are multiple
          // types, otherwise the callback signature can be inlined into
          // the method declaration.
          function getAlternateTypes(method) {
            var types = [];
  
            function process(arr) {
              if (arr) {
                arr.forEach(function(obj) {
                  if (obj.type) {
                    var split = obj.type.split('|');
                    if (split.length > 1) {
                      types = types.concat(split);
                    }
                  }
                });
              }
            }
  
            process(method.params);
            process(method.options);
  
            return types;
          }
  
          function addModuleCallbackType(method, callback) {
            var typeExists = module.types.some(function(t) {
              return t.name === callback.name;
            });
            if (!typeExists) {
              var signature = getCallbackSignature(callback, method, namespace);
              if (method.generics) {
                moduleCallbackGenerics[namespace.name + ':' + callback.name] = method.generics;
              }
              module.types.push({
                name: callback.name,
                generics: getGenericSource(callback.generics),
                type: signature
              });
            }
          }
  
          namespace.methods.forEach(function(method) {
            if (!method.callbacks || methodIsBlacklisted(namespace.name, method)) {
              return;
            }
            getAlternateTypes(method).forEach(function(type) {
              if (type.match(/Fn$/)) {
                var callback = findMethodCallbackByName(method, type);
                addModuleCallbackType(method, callback);
              }
            });
          });
  
        }
  
        function addOptionsInterfaces(module) {
          namespace.methods.forEach(function(method) {
            if (!method.options || methodIsBlacklisted(namespace.name, method)) {
              return;
            }
  
            var params = method.params;
            (method.signatures || []).forEach(function(signature) {
              params = params.concat(signature);
            })
  
            var optionsParam = params.find(function(param) {
              return param.type.match(/Options$/);
            });
  
            var optionsGenerics = [];
  
            var src = method.options.map(function(option) {
              var types = option.type.split('|');
              types = types.map(function(type) {
                if (type.match(/Fn$/)) {
                  var callback = findMethodCallbackByName(method, type);
                  if (types.length === 1 && type.match(/Fn$/)) {
                    // Inline a callback delcaration
                    type = getCallbackSignature(callback, method, namespace);
                  } else {
                    // Refer to callback externally
                    type += getGenericSource(moduleCallbackGenerics[namespace.name + ':' + callback.name]);
                  }
                  optionsGenerics = optionsGenerics.concat(callback.generics);
                }
                return type;
              });
              return option.name + (option.required ? '' : '?') + ': ' + types.join('|') + ';';
            }).join('\n');
  
            // Store references to the namespaces that option interfaces exist in
            // so that we can reference them externally later.
            if (!namespace.name.match(/^Sugar/)) {
              optionInterfaceNamespaces[optionsParam.type] = namespace.name;
            }
  
            moduleOptionsGenerics[namespace.name + ':' + optionsParam.type] = optionsGenerics;
            var name = optionsParam.type + getGenericSource(optionsGenerics);
            module.interfaces.push(getInterfaceSource(name, src));
          });
        }
  
        function getCallbackSignature(callback, method, namespace) {
          var genericsLength = method.generic && method.generics.length || 0, gen;
          var params = getParams(callback.params, method, namespace);
          var returns = callback.returns ? getType(callback.returns, method) : 'void';
          // Slightly convoluted way of getting generics for the callback by
          // subtracting method generics from what they were previously.
          callback.generics = method.generics.slice(genericsLength);
          return '(' + params + ') => ' + returns;
        }
  
        function findMethodCallbackByName(method, name) {
          return method.callbacks.find(function(callback) {
            return callback.name === name;
          });
        }
  
  
        // Exclude polyfills
        namespace.methods = namespace.methods.filter(function(method) {
          return !method.module.match(/ES[5-7]/);
        });
  
        // Unpack sets like "[unit]FromNow"
        namespace.methods = unpackMethodSets(namespace.methods);
  
        if (namespace.name === 'Sugar') {
          addExtras(sugarjs);
          sugarjs.interfaces.push(getSugarInterface(namespace, docs.namespaces));
        } else if (namespace.name === 'SugarNamespace') {
          // The generic "SugarNamespace" interface is required for the
          // "createNamespace" method that needs to return an as-yet undefined
          // type. For existing namespaces, the methods here will instead be
          // mixed into each individual interface. This is required, as each
          // namespace returns a reference to itself, and so (it would appear)
          // cannot use extend.
          addExtras(sugarjs);
          sugarjs.interfaces.push(getSugarNamespaceInterface(namespace));
        } else if (namespace.name === 'Range') {
          sugarjs.interfaces.push(getRangeInterface(namespace));
        } else {
          var module = getDeclaredNamespace(namespace.name);
          addExtras(module);
          module.interfaces.push(getConstructorInterface(namespace, module));
          module.interfaces.push(getChainableBaseInterface(namespace));
  
  
          // Export extended interfaces unless opting out.
          if (args['extended-mode'] !== false) {
            extendedInterfaces.push(getExtendedConstructorInterface(namespace));
  
            // Note: due to Typescript quirkiness about incompatible interfaces,
            // Object.prototype mode cannot be supported here for now.
            if (namespace.name !== 'Object') {
              extendedInterfaces.push(getExtendedInstanceInterface(namespace));
            }
          }
  
          sugarjs.namespaces.push(getDeclaredNamespaceSource(module));
          nativeNames.push(namespace.name);
        }
  
      });
  
      var wrappedGeneric = getGenericSource(CHAINABLE_RAW_TYPE);
      sugarjs.types.push({
        name: 'SugarDefaultChainable' + wrappedGeneric,
        type: getNamespaceTypesMerged(39, getChainableNameExternal, '&'),
      });
  
      sugarjs.types.push({
        name: 'NativeConstructor',
        type: getNamespaceTypesMerged(25, 'Constructor', '|', ['Boolean', 'Error']),
      });
  
  
      var baseDeclarations = [];
      baseDeclarations.push(TS_LICENSE);
      baseDeclarations.push(getDeclaredNamespaceSource(sugarjs, true));
      baseDeclarations.push(getDeclaredModuleSource());
      baseDeclarations.push('declare var Sugar: sugarjs.Sugar;');
  
      var extendedDeclarations = [];
      extendedDeclarations.push(TS_EXTENDED_LICENSE);
      extendedDeclarations.push('/// <reference path="sugar.d.ts" />');
      extendedDeclarations.push(getInterfaceBlocks(extendedInterfaces));
  
      writeDeclarations('sugar.d.ts', baseDeclarations);
      writeDeclarations('sugar-extended.d.ts', extendedDeclarations);
    }