TypeScript declarations
The build can ship a .d.ts next to your .node binary so JavaScript users get full IntelliSense and type checking. There are three modes, controlled by the .dts field of .npm:
Hand-written (.file)
Recommended for libraries published to npm. A hand-written .d.ts gives you the full TypeScript surface: overloads, conditional types, branded types, JSDoc comments, and the freedom to keep your public API stable independent of internal Zig refactors.
The build copies this file as-is to index.d.ts next to the .node binary, and into the published npm package. You write what your users should see; the bridge does not interfere.
Auto-generated (.auto)
The build runs a comptime walk of your module and emits a .d.ts from the Zig signatures. Useful for prototypes, internal addons, or as a starting point that you check into src/index.d.ts and then edit.
What you get:
- Every
pub fnbecomes a method. - Every
pub const(with a JS-mappable value) becomes a typed property. - Nested namespaces become nested objects.
- Argument and return types come from the Zig signatures.
- Errors, optionals, enums, and structs are translated.
What is intentionally unknown:
napi.Valbecomesunknown. There is no JS type to infer from a passthrough.napi.Callbackbecomes(...args: unknown[]) => unknown.
These are escape hatches by design. Tighten the Zig signature and the generated type tightens with it. For example, []f64 generates number[] instead of unknown[].
A common workflow: start with .auto, run napikit build, copy the generated file out of zig-out/lib/<name>.d.ts into src/index.d.ts, edit it to taste, and switch the build to .{ .file = ... }.
None (.none)
No .d.ts is emitted. JavaScript users get no autocomplete or type checking for the addon. This is the default.
For a release package, .none also omits the types field and the index.d.ts entry from files. If the package previously used .auto or .{ .file = ... }, the next full napikit build --release removes the stale build-owned npm/<name>/index.d.ts and its managed manifest entry. Other files and user-managed manifest fields are preserved.
Rule of thumb
If your addon will be installed by other people, hand-write your .d.ts. If it is internal, .auto is fine.
Calling the generator yourself
The generator is also exposed as a public API: napi.dts.generate(Module) returns the comptime .d.ts string for Module. The build option .auto uses this internally; you do not normally call it directly.