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

    If your package is written in TypeScript then the first approach is favored. Use the flag to generate declaration files. This way, your declarations and JavaScript will always be in sync.

    If your package is not written in TypeScript then the second is the preferred approach.

    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:

    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.

    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.

    1. json
      {
    2. "author": "Vandelay Industries",
    3. "version": "1.0.0",
    4. "main": "./lib/main.js",
    5. "types": "./lib/main.d.ts",
    6. "dependencies": {
    7. "browserify": "latest",
    8. "@types/browserify": "latest",
    9. "typescript": "next"
    10. }

    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.

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

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

    1. ts
      /// <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.

    When TypeScript opens a package.json file to figure out which files it needs to read, it first looks at a new field called typesVersions.

    This package.json tells TypeScript to check whether the current version of TypeScript is running. If it’s 3.1 or later, it figures out the path you’ve imported relative to the package, and reads from the package’s ts3.1 folder. That’s what that means - if you’re familiar with path mapping today, 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.

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

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

    1. json
      {
    2. "name": "package-name",
    3. "version": "1.0",
    4. "types": "./index.d.ts",
    5. "typesVersions": {
    6. ">=3.2": { "*": ["ts3.2/*"] },
    7. ">=3.1": { "*": ["ts3.1/*"] }
    8. }

    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.

    Publish to @types