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:
- bundling with your npm package
- 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 via
declaration
.
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 your package.json
file as well. Set the
types
property to point to your bundled declaration file. For example:
{
"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 with types
, and could be
used as well.
Also note that if your main declaration file is named index.d.ts
and
lives at the root of the package (next to index.js
) you do not need to
mark the types
property, though it is advisable to do so.
Dependencies #
All dependencies are managed by npm. Make sure all the declaration
packages you depend on are marked appropriately in the "dependencies"
section in your package.json
. For example, imagine we authored a
package that used Browserify and TypeScript.
{
"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 the browserify
and typescript
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 our
browserify-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 used devDependencies
.
Red flags #
/// <reference path="..." />
#
Don’t use /// <reference path="..." />
in your declaration files.
/// <reference path="../typescript/lib/typescriptServices.d.ts" />
....
Do use /// <reference types="..." />
instead.
/// <reference types="typescript" />
....
Make sure to revisit the Consuming 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 with typesVersions
#
When TypeScript opens a package.json
file to figure out which files it
needs to read, it first looks at a field called typesVersions
.
Folder redirects (using *
)
#
A package.json
with a typesVersions
field might look like this:
{
"name": "package-name",
"version": "1.0.0",
"types": "./index.d.ts",
"typesVersions": {
">=3.1": { "*": ["ts3.1/*"] }
}
}
This package.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’s
ts3.1
folder.
That’s what that { "*": ["ts3.1/*"] }
means - if you’re familiar with
path 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 from
package-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 in typesVersions
get matched, TypeScript falls back
to the types
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:
{
"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
.
Matching behavior #
The way that TypeScript decides on whether a version of the compiler & language matches is by using Node’s semver 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",
"types": "./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",
"types": "./index.d.ts",
"typesVersions": {
// NOTE: this doesn't work!
">=3.1": { "*": ["ts3.1/*"] },
">=3.2": { "*": ["ts3.2/*"] }
}
}
Publish to #
Packages under the @types organization are published automatically from DefinitelyTyped using the types-publisher tool. To get your declarations published as an @types package, please submit a pull request to DefinitelyTyped. You can find more details in the contribution guidelines page.
::: _attribution
© 2012-2023 Microsoft
Licensed under the Apache License, Version 2.0.
https://www.typescriptlang.org/docs/handbook/declaration-files/publishing.html{._attribution-link}
:::