Was this page helpful?

Publishing

Now that you have authored a declaration file following the steps of this guide, it is time to publish it to npm.There are two main ways you can publish your declaration files to npm:

  1. bundling with your npm package
  2. publishing to the@types organization on npm.

If your types are generated by your source code, publish the types with your source code. Both TypeScript and JavaScript projects can generate types viadeclaration.

Otherwise, we recommend submitting the types to DefinitelyTyped, which will publish them to the@types organization on npm.

Including declarations in your npm package

If your package has a main.js file, you will need to indicate the main declaration file in yourpackage.json file as well.Set thetypes property to point to your bundled declaration file.For example:

json
{
"name":"awesome",
"author":"Vandelay Industries",
"version":"1.0.0",
"main":"./lib/main.js",
"types":"./lib/main.d.ts"
}

Note that the"typings" field is synonymous withtypes, and could be used as well.

Dependencies

All dependencies are managed by npm.Make sure all the declaration packages you depend on are marked appropriately in the"dependencies" section in yourpackage.json.For example, imagine we authored a package that used Browserify and TypeScript.

json
{
"name":"browserify-typescript-extension",
"author":"Vandelay Industries",
"version":"1.0.0",
"main":"./lib/main.js",
"types":"./lib/main.d.ts",
"dependencies": {
"browserify":"latest",
"@types/browserify":"latest",
"typescript":"next"
}
}

Here, our package depends on thebrowserify andtypescript packages.browserify does not bundle its declaration files with its npm packages, so we needed to depend on@types/browserify for its declarations.typescript, on the other hand, packages its declaration files, so there was no need for any additional dependencies.

Our package exposes declarations from each of those, so any user of ourbrowserify-typescript-extension package needs to have these dependencies as well.For that reason, we used"dependencies" and not"devDependencies", because otherwise our consumers would have needed to manually install those packages.If we had just written a command line application and not expected our package to be used as a library, we might have useddevDependencies.

Red flags

/// <reference path="..." />

Don’t use/// <reference path="..." /> in your declaration files.

ts
///<referencepath="../typescript/lib/typescriptServices.d.ts"/>
....

Do use/// <reference types="..." /> instead.

ts
///<referencetypes="typescript"/>
....

Make sure to revisit theConsuming dependencies section for more information.

Packaging dependent declarations

If your type definitions depend on another package:

  • Don’t combine it with yours, keep each in their own file.
  • Don’t copy the declarations in your package either.
  • Do depend on the npm type declaration package if it doesn’t package its declaration files.

Version selection withtypesVersions

When TypeScript opens apackage.json file to figure out which files it needs to read, it first looks at a field calledtypesVersions.

Folder redirects (using*)

Apackage.json with atypesVersions field might look like this:

json
{
"name":"package-name",
"version":"1.0.0",
"types":"./index.d.ts",
"typesVersions": {
">=3.1": {"*": ["ts3.1/*"] }
}
}

Thispackage.json tells TypeScript to first check the current version of TypeScript.If it’s 3.1 or later, TypeScript figures out the path you’ve imported relative to the package, and reads from the package’sts3.1 folder.

That’s what that{ "*": ["ts3.1/*"] } means - if you’re familiar withpath mapping, it works exactly like that.

In the above example, if we’re importing from"package-name", TypeScript will try to resolve from[...]/node_modules/package-name/ts3.1/index.d.ts (and other relevant paths) when running in TypeScript 3.1.If we import frompackage-name/foo, we’ll try to look for[...]/node_modules/package-name/ts3.1/foo.d.ts and[...]/node_modules/package-name/ts3.1/foo/index.d.ts.

What if we’re not running in TypeScript 3.1 in this example?Well, if none of the fields intypesVersions get matched, TypeScript falls back to thetypes field, so here TypeScript 3.0 and earlier will be redirected to[...]/node_modules/package-name/index.d.ts.

File redirects

When you want to only change the resolution for a single file at a time, you can tell TypeScript the file to resolve differently by passing in the exact filenames:

json
{
"name":"package-name",
"version":"1.0.0",
"types":"./index.d.ts",
"typesVersions": {
"<4.0": {"index.d.ts": ["index.v3.d.ts"] }
}
}

On TypeScript 4.0 and above, an import for"package-name" would resolve to./index.d.ts and for 3.9 and below"./index.v3.d.ts.

Note that redirections only affect theexternal API of a package; import resolution within a project is not affected bytypesVersions. For example, ad.ts file in the previous example containingimport * as foo from "./index" will still map toindex.d.ts, notindex.v3.d.ts, whereas another package importingimport * as foo from "package-name"will getindex.v3.d.ts.

Matching behavior

The way that TypeScript decides on whether a version of the compiler & language matches is by using Node’ssemver ranges.

Multiple fields

typesVersions can support multiple fields where each field name is specified by the range to match on.

{
"name":"package-name",
"version":"1.0",
"":"./index.d.ts",
"typesVersions": {
">=3.2": {"*": ["ts3.2/*"] },
">=3.1": {"*": ["ts3.1/*"] }
}
}

Since ranges have the potential to overlap, determining which redirect applies is order-specific.That means in the above example, even though both the>=3.2 and the>=3.1 matchers support TypeScript 3.2 and above, reversing the order could have different behavior, so the above sample would not be equivalent to the following.

{
"name":"package-name",
"version":"1.0",
"":"./index.d.ts",
"typesVersions": {
// NOTE: this doesn't work!
">=3.1": {"*": ["ts3.1/*"] },
">=3.2": {"*": ["ts3.2/*"] }
}
}

Publish to@types

Packages under the@types organization are published automatically fromDefinitelyTyped using thetypes-publisher tool.To get your declarations published as an @types package, please submit a pull request toDefinitelyTyped.You can find more details in thecontribution guidelines page.

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

Contributors to this page:
MHMohamed Hegazy  (55)
OTOrta Therox  (21)
MBMateusz Burzyński  (2)
RVRauno Viskus  (2)
RCRyan Cavanaugh  (2)
19+

Last updated: Jul 07, 2025