Exporting types
is hard when you have multiple entrypoints. If the consumer's TypeScript configuration supports node16
, the types
condition should work splendidly. If not, there's a couple ways around it.
1. Map export path to actual files
If you have an export like my-lib/subpath
, make sure you have a /subpath.d.ts
file. Likewise for my-lib/really/deep/subpath
, create a /really/deep/subpath.d.ts
file.
2. Declare module
If your package has an ambient file, you can use declare module
to achieve the same without needing to create new files. The downside though is that all types are in a single file, and the user needs to understand how ambient types work.
declare module 'my-lib/subpath' {
export const hello: string
}
Because it's an ambient file, you will need the user to do /// <reference types="my-lib" />
in their own ambient file.
// src/global.d.ts (common names: env, ambient)
/// <reference types="my-lib" />`
It's not recommended to add to compilerOptions.types
as that overrides types
search. (TODO: needs more explanation)
Ambient files must also be script files, not module files. https://www.typescriptlang.org/docs/handbook/modules.html
In TypeScript, just as in ECMAScript 2015, any file containing a top-level import or export is considered a module. Conversely, a file without any top-level import or export declarations is treated as a script whose contents are available in the global scope (and therefore to modules as well).
Ideally we want to make sure types
work in either node16
or not, and we give a hint on the first approach. The second approach is valid and publint needs to check patterns like these to not incorrectly give the hint.