Was this page helpful?

Library Structures

Broadly speaking, the way youstructure your declaration file depends on how the library is consumed.There are many ways of offering a library for consumption in JavaScript, and you’ll need to write your declaration file to match it.This guide covers how to identify common library patterns, and how to write declaration files which correspond to that pattern.

Each type of major library structuring pattern has a corresponding file in theTemplates section.You can start with these templates to help you get going faster.

Identifying Kinds of Libraries

First, we’ll review the kinds of libraries TypeScript declaration files can represent.We’ll briefly show how each kind of library isused, how it iswritten, and list some example libraries from the real world.

Identifying the structure of a library is the first step in writing its declaration file.We’ll give hints on how to identify structure both based on itsusage and itscode.Depending on the library’s documentation and organization, one might be easier than the other.We recommend using whichever is more comfortable to you.

What should you look for?

Question to ask yourself while looking at a library you are trying to type.

  1. How do you obtain the library?

    For example, can youonly get it through npm or only from a CDN?

  2. How would you import it?

    Does it add a global object? Does it userequire orimport/export statements?

Smaller samples for different types of libraries

Modular Libraries

Almost every modern Node.js library falls into the module family.These type of libraries only work in a JS environment with a module loader.For example,express only works in Node.js and must be loaded using the CommonJSrequire function.

ECMAScript 2015 (also known as ES2015, ECMAScript 6, and ES6), CommonJS, and RequireJS have similar notions ofimporting amodule.In JavaScript CommonJS (Node.js), for example, you would write

js
varfs =require("fs");

In TypeScript or ES6, theimport keyword serves the same purpose:

ts
import*asfsfrom"fs";

You’ll typically see modular libraries include one of these lines in their documentation:

js
varsomeLib =require("someLib");

or

js
define(..., ['someLib'],function(someLib) {
});

As with global modules, you might see these examples in the documentation ofa UMD module, so be sure to check the code or documentation.

Identifying a Module Library from Code

Modular libraries will typically have at least some of the following:

  • Unconditional calls torequire ordefine
  • Declarations likeimport * as a from 'b'; orexport c;
  • Assignments toexports ormodule.exports

They will rarely have:

  • Assignments to properties ofwindow orglobal

Templates For Modules

There are four templates available for modules,module.d.ts,module-class.d.ts,module-function.d.ts andmodule-plugin.d.ts.

You should first readmodule.d.ts for an overview on the way they all work.

Then use the templatemodule-function.d.ts if your module can becalled like a function:

js
constx =require("foo");
// Note: calling 'x' as a function
consty =x(42);

Use the templatemodule-class.d.ts if your module can beconstructed usingnew:

js
constx =require("bar");
// Note: using 'new' operator on the imported variable
consty =newx("hello");

If you have a module which when imported, makes changes to other modules use templatemodule-plugin.d.ts:

js
constjest =require("jest");
require("jest-matchers-files");

Global Libraries

Aglobal library is one that can be accessed from the global scope (i.e. without using any form ofimport).Many libraries simply expose one or more global variables for use.For example, if you were usingjQuery, the$ variable can be used by simply referring to it:

ts
$(()=> {
console.log("hello!");
});

You’ll usually see guidance in the documentation of a global library of how to use the library in an HTML script tag:

html
<scriptsrc="http://a.great.cdn.for/someLib.js"></script>

Today, most popular globally-accessible libraries are actually written as UMD libraries (see below).UMD library documentation is hard to distinguish from global library documentation.Before writing a global declaration file, make sure the library isn’t actually UMD.

Identifying a Global Library from Code

Global library code is usually extremely simple.A global “Hello, world” library might look like this:

js
functioncreateGreeting(s) {
return"Hello, " +s;
}

or like this:

js
// Web
window.createGreeting =function (s) {
return"Hello, " +s;
};
// Node
global.createGreeting =function (s) {
return"Hello, " +s;
};
// Potentially any runtime
globalThis.createGreeting =function (s) {
return"Hello, " +s;
};

When looking at the code of a global library, you’ll usually see:

  • Top-levelvar statements orfunction declarations
  • One or more assignments towindow.someName
  • Assumptions that DOM primitives likedocument orwindow exist

Youwon’t see:

  • Checks for, or usage of, module loaders likerequire ordefine
  • CommonJS/Node.js-style imports of the formvar fs = require("fs");
  • Calls todefine(...)
  • Documentation describing how torequire or import the library

Examples of Global Libraries

Because it’s usually easy to turn a global library into a UMD library, very few popular libraries are still written in the global style.However, libraries that are small and require the DOM (or haveno dependencies) may still be global.

Global Library Template

The template fileglobal.d.ts defines an example librarymyLib.Be sure to read the“Preventing Name Conflicts” footnote.

UMD

AUMD module is one that caneither be used as module (through an import), or as a global (when run in an environment without a module loader).Many popular libraries, such asMoment.js, are written this way.For example, in Node.js or using RequireJS, you would write:

ts
importmoment =require("moment");
console.log(moment.format());

whereas in a vanilla browser environment you would write:

js
console.log(moment.format());

Identifying a UMD library

UMD modules check for the existence of a module loader environment.This is an easy-to-spot pattern that looks something like this:

js
(function (root,factory) {
if (typeofdefine ==="function" &&define.amd) {
define(["libName"],factory);
}elseif (typeofmodule ==="object" &&module.exports) {
module.exports =factory(require("libName"));
}else {
root.returnExports =factory(root.libName);
}
}(this,function (b) {

If you see tests fortypeof define,typeof window, ortypeof module in the code of a library, especially at the top of the file, it’s almost always a UMD library.

Documentation for UMD libraries will also often demonstrate a “Using in Node.js” example showingrequire,and a “Using in the browser” example showing using a<script> tag to load the script.

Examples of UMD libraries

Most popular libraries are now available as UMD packages.Examples includejQuery,Moment.js,lodash, and many more.

Template

Use themodule-plugin.d.ts template.

Consuming Dependencies

There are several kinds of dependencies your library might have.This section shows how to import them into the declaration file.

Dependencies on Global Libraries

If your library depends on a global library, use a/// <reference types="..." /> directive:

ts
///<referencetypes="someLib"/>
functiongetThing():someLib.thing;

Dependencies on Modules

If your library depends on a module, use animport statement:

ts
import*asmomentfrom"moment";
functiongetThing():moment;

Dependencies on UMD libraries

From a Global Library

If your global library depends on a UMD module, use a/// <reference types directive:

ts
///<referencetypes="moment"/>
functiongetThing():moment;

From a Module or UMD Library

If your module or UMD library depends on a UMD library, use animport statement:

ts
import*assomeLibfrom"someLib";

Donot use a/// <reference directive to declare a dependency to a UMD library!

Footnotes

Preventing Name Conflicts

Note that it’s possible to define many types in the global scope when writing a global declaration file.We strongly discourage this as it leads to possible unresolvable name conflicts when many declaration files are in a project.

A simple rule to follow is to only declare typesnamespaced by whatever global variable the library defines.For example, if the library defines the global value ‘cats’, you should write

ts
declarenamespacecats {
interfaceKittySettings {}
}

Butnot

ts
// at top-level
interfaceCatsKittySettings {}

This guidance also ensures that the library can be transitioned to UMD without breaking declaration file users.

The Impact of ES6 on Module Call Signatures

Many popular libraries, such as Express, expose themselves as a callable function when imported.For example, the typical Express usage looks like this:

ts
importexp =require("express");
varapp =exp();

In ES6-compliant module loaders, the top-level object (here imported asexp) can only have properties;the top-level module object cannever be callable.

The most common solution here is to define adefault export for a callable/constructable object;module loaders commonly detect this situation automatically and replace the top-level object with thedefault export.TypeScript can handle this for you, if you have"esModuleInterop": true in your tsconfig.json.

The TypeScript docs are an open source project. Help us improve these pagesby sending a Pull Request

Contributors to this page:
MHMohamed Hegazy  (57)
OTOrta Therox  (17)
DRDaniel Rose  (3)
Llilichao  (1)
MFMartin Fischer  (1)
12+

Last updated: Nov 25, 2025