tezvyn:

Shipping TypeScript Types in package.json

AI-drafted, machine-checkedSource: typescriptlang.orgintermediate

The `types` field in `package.json` tells TypeScript where to find your package's type definitions. Use it when publishing a library to enable autocompletion for users. The footgun is putting type dependencies in `devDependencies` instead of `dependencies`.

WHY IT EXISTS JavaScript packages use the main field in package.json to tell runtimes like Node.js where the entry-point file is. When TypeScript became popular, it needed a similar, parallel mechanism to find the type definitions for a package, enabling editor autocompletion and type-checking across project boundaries.

THE MENTAL MODEL Think of package.json as a package's public interface. The main field says, "Here's my entry point for runtime execution." The types field adds, "And here's my corresponding type declaration file for compile-time analysis and editor support." They are parallel pointers for two different consumers: the JavaScript runtime and the TypeScript compiler.

HOW IT WORKS In your package.json, you add a types property (or its older synonym, typings). Its value is a path to your main declaration file, which typically ends in .d.ts. When another project imports your package, the TypeScript compiler looks at this field to find and load your types, making them available for type checking. If your package is consumed, its own type dependencies must be available, which leads to a common mistake.

WHEN TO USE IT Use the types field whenever you publish an npm package written in TypeScript, or a JavaScript package for which you are providing your own type definitions. This is the standard for bundling types with your code, making your package immediately useful in a TypeScript environment.

WHEN NOT TO USE IT If your package is a pure application not intended for use as a library, or if it's an older JavaScript project whose types are exclusively managed by the community on DefinitelyTyped (@types/some-package), you would not include this field. The presence of the types field signals that you are the authority for your package's types.

ONE CANONICAL EXAMPLE A library's package.json might look like this: { "name": "my-awesome-lib", "main": "./dist/index.js", "types": "./dist/index.d.ts" }. A consumer of this library gets runtime code from index.js, but their editor and the TypeScript compiler get type information from index.d.ts. If my-awesome-lib's types depend on @types/node, it must list that in its dependencies, not devDependencies, so the consumer's compiler can find it.

Read the original → typescriptlang.org

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.