Type definitions are descriptions of the API of a module. It lets you describe the available functions, the shape of the expected inputs and what are the returned values. The type system is very rich and allows you to express complex contracts.
The goal of this post is to explain why you should use type definitions.
Type definitions were created by Typescript. Typescript lets you embed the type definitions in your source code and check them automatically, but you can write them yourself or generate them. You can have type definitions even if your project does not use Typescript.
Other initiatives to provide types to the web exist, notably Flow. I am advocating for Typescript's type definitions as the main format because it has some more advanced features and an order of magnitude larger ecosystem. It brings the usual benefits: fast development, better tooling support, more documentation, etc.
This is the number one benefit in my opinion. Writing type definitions means that you have to write down your public API in a formal format. It helps to ensure that the documentation is complete and states all the assumptions clearly. This nicely complement any textual documentation that may have some ambiguities.
Keeping type definitions as close to the source as possible makes it easier to ensure that they are up to date. Consumer using these types for type checking can help quickly raise issues when an inconsistency between the documentation and the behavior is spotted.
This is important with regard to Semver. Semver ties code and documentation together. A patch is a change that does not modify the public API, a feature increases the API surface and a breaking change, well, breaks the public API. Having type definitions means that you can know how a change affects your API.
This stricter approach to documentation benefits the most to popular projects.
By providing type definitions for your module, you enable consumers to better check their code when interacting with your module. It also enables them to leverage this information while refactoring code: the tools are aware of the legal transformations.
Major IDEs such as Visual Studio Code, Intellij IDEA and Webstorm use type definitions to improve their intellisense. A library with types enables code completion, quick documentation or auto imports.
This benefits to all consumers: the consumers don't need Typescript to get better intellisense.
Type definitions help new maintainers to get familiar with a code base and be more confident with their changes. I recently worked on refactoring some libraries: by first writing type definitions and only then doing the changes, I was confident that my refactoring did not break anything.
In fact, types benefit greatly to consumers so many tend to help maintaining them when using a library. Even if the type definitions are only maintained by external contributors they should be hosted on library's repo. This is the natural place where contributors look at to send improvements. This is one of the reasons why it is recommended to keep the definitions with the code.
If the main repo can't host the types itself, there exist a community-maintained project called DefinitelyTyped. It's nice to have but in my experience it is painful to contribute to because of its large size (for example, you can't easily track issues for a lib you're interested in). It also requires users to install a separate package for the types, harming for example intellisense for JS consumers.
The more the ecosystem is typed, the more value it is possible to extract. It has led many popular libraries to move to support their own type definitions. Some examples include Gulp, Chai, Chalk or Squel.
On a larger scale, Typescript's type definitions are also generated by other languages. The most prominent of them is Rust: it has first class support to generate type definitions when compiling Wasm modules.
If you want to get started, the best place is Declaration Files Introduction.
There's also a high chance that you are reading this post because I sent you a PR to add types. I've been using Typescript from 2015 and wrote dozen of definition files for a wide range of libraries: I'd be happy to give some help to you too.