I published two Javascript libraries on npm and users have asked for TypeScript type definitions for both of them. I don't use TypeScript myself and I have no plans to rewrite those libraries in TypeScript, but I'd still like to add the type definition files if only for better IntelliSense code completion. I'm looking for some advice with this.
I started with reading the docs of the DefinitelyTyped project and the documentation on publishing a declaration file for an npm package. Both sources state that "publishing to the @types organization on npm" is the preferred approach for projects not written in TypeScript.
Why is that preferred over publishing type definitions alongside the library itself via the types
field in package.json
? I really don't see the point in involving a third party in this. It seems like updating the type definitions and versioning them is just more complicated this way.
From DefinitelyTyped:
If you are the library author and your package is written in TypeScript, bundle the autogenerated declaration files in your package instead of publishing to Definitely Typed.
From typescriptlang.org:
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, or
- publishing to the @types organization on npm.
If your package is written in TypeScript then the first approach is favored. Use the --declaration 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.
Both seem to say:
if (isAuthor && lang === "typescript")
bundle();
else
publishOnDefinitelyTyped();
Declaration files, if you're not familiar, are just files that describe the shape of an existing JavaScript codebase to TypeScript. By using declaration files (also called . d. ts files), you can avoid misusing libraries and get things like completions in your editor.
With TypeScript 3.7, TypeScript added support for generating . d. ts files from JavaScript using JSDoc syntax. This set up means you can own the editor experience of TypeScript-powered editors without porting your project to TypeScript, or having to maintain .
TypeScript includes declaration files for all of the standardized built-in APIs available in JavaScript runtimes. This includes things like methods and properties of built-in types like string or function , top-level names like Math and Object , and their associated types.
Type declaration publishing guides seem a bit outdated and sparse in several areas.
I'll try to compare both scenarios in detail.
In general, package bundled types are more convenient thanks to streamlined dependency management.
limited ways to opt-out from using package bundled types
Involves cases when the consumer needs to modify or substitute type declarations.
The process can be considerably problematic in projects with opinionated build setups, due to the already limited configuration options.
Having types bundled with package means that there are in fact two API contracts published each time a version is released.
Example:
Let's assume a library which aims to conform to semver versioning.
The options for next version are:
A. 2.X.X -> violates semver rules for type declarations
B. 3.0.0 -> violates semver rules for the actual code
It's likely that there are numerous variations of such scenario.
types have no impact on the package's release cycle
DT repo comes with two extra traits:
First tool can be incorporated into another package repo with minor effort. I'm not sure if the analysis can be replicated in one's own repository, but it contains a lot of valuable data.
non-standard way of supporting past releases
type release schedule constrained by DT review and release cycles
Assuming that the DefinitelyTyped PR creator is the @types package owner, it usually takes between one to two days before the PR is merged. Additionally, there's a minor delay before types-publisher updates PR related @types npm package.
Additional review process is involved in cases when the PR is author's first contribution to a given package.
using external dependencies
TypeScript handbook says:
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.
Judging by the amount of redundant utility types, these are hardly respected.
The author of type declarations is allowed to use adjacent DT repository types. Depending on packages from beyond this list requires them to be on types-publisher whitelist.
New packages can be whitelisted by submitting a PR to types-publisher. It took over two weeks for my PR to be merged. I don't know if that's usual since I had submitted a single PR.
DT repo volume
I have no cross-IDE comparison or experience, but as far as JetBrains IDEs are concerned, the memory footprint of fully indexed DT repo project made the IDE unusable.
Disabling recompilation on changes helps to some extent. The frustrating IDE experience can be worked around by removing DT repo contents that are not relevant to the package of interest.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With