On this page
API docs vs. ts-defold-types
How the JSDoc that @defold-typescript/types emits compares with the incumbent
hand-and-script-maintained thinknathan/ts-defold-types.
Both surfaces derive from the same Defold reference docs, so symbol coverage
is parity by construction; this page records where @defold-typescript/types'
emitted documentation is strictly cleaner, and the one place ts-defold-types is
arguably cleaner.
The comparison is backed by a machine check, packages/types/test/api-doc-parity.test.ts,
which parses a pinned snapshot of the ts-defold-types index.d.ts and the
@defold-typescript/types generated/*.d.ts with one shared extractor and fails
if @defold-typescript/types documents less than ts-defold-types does for
any shared symbol. It compares documentation, not type fidelity (branded vs. flat
types are out of scope here).
Dimension comparison
| Dimension | ts-defold-types | @defold-typescript/types |
|---|---|---|
| Description coverage | Most functions/constants carry a summary | Same source, same coverage; every shared symbol documents at least as well |
| Namespace hover | Module namespaces are not consistently documented | Generated namespaces use Defold module metadata; (synthesized) marks fallback prose only when the ref-doc has no module summary |
@param style |
@param <name> <desc> (no separator) |
@param <name> - <desc> (dash-separated, the JSDoc convention editors render as a definition list) |
| Description markup | Raw ref-doc text | htmlToDocText converts HTML to Markdown: <code>→`code`, <ul><li>→- bullets, <a>→link text, entities decoded |
Multi-line @param/@returns |
Continuation lines escape the * grid |
Every continuation line carries * (see the well-formedness gate) |
@returns |
One flat @returns even for multi-value returns |
One @returns for single returns; multi-value returns are typed as a LuaMultiReturn tuple that names every value (see exceptions) |
@example |
@example <prose> then a fenced block |
@example then a fenced ```lua block on its own lines |
| Constant types | const X: number |
Branded: number & { readonly __brand: "ns.X" } — distinct constants stay nominally distinct |
Description markup, concretely
ts-defold-types:
* @param options A table with the following fields: <ul><li><code>count</code> ...
@defold-typescript/types:
* @param options - A table with the following fields:
* - `count` ...
Well-formedness
A multi-line @param doc (a ref-doc <li> list becomes embedded newlines) is
re-prefixed line by line so it stays inside the JSDoc * grid. The permanent
guard for this is the self-contained packages/types/test/doc-comment-wellformed.test.ts
gate over the committed generated/*.d.ts — it does not depend on the pinned
fixture below.
Coverage-test result
Against the pinned snapshot (Defold stable 1.12.4):
- 791 shared symbols — for every one, the
@defold-typescript/typesdocs are a superset: ifts-defold-typeshas a description, a@param, a@returns, or an@example,@defold-typescript/typesdoes too. - 106
ts-defold-types-only symbols — reported as coverage notes, not failures. These are surface-shape differences, not dropped docs: top-level globals (pprint,hash, …) and modules the@defold-typescript/typessurface structures differently (b2d.body.*,bit.*, somesocketoverloads). They live elsewhere or under a different namespace path in the@defold-typescript/typessplit, branded/versioned surface.
Multi-return functions
For 9 functions whose Lua API returns several values (e.g.
gui.get_type, gui.new_texture, buffer.get_metadata,
collectionproxy.set_collection, sound.get_rms, window.get_size),
ts-defold-types collapses the return to one @returns line. @defold-typescript/types
instead types the return as a LuaMultiReturn<[…]> tuple, so each returned value
is named in the type itself rather than in prose. The coverage test treats these
as documented-by-type, not as a @returns regression.
Lua standard library reference category
The /api reference browser surfaces the Defold-engine namespaces plus a
separate Lua standard library category for the pure-Lua / LuaJIT surfaces
Defold documents (base, bit, math, os, string, table,
coroutine, debug, io, package). Their TypeScript types come from the
lua-types dependency the lua-stdlib-globals goal adopted
(lua-types/special/jit-only.d.ts for bit, lua-types/core/global.d.ts for
the base globals, lua-types/core/debug.d.ts and lua-types/core/io.d.ts for
debug/io, and lua-types/core/modules.d.ts for package) and are wired
into every script kind via the
LUA_STDLIB_REFERENCES triple-slash directives in regen.ts — @defold-typescript/types
does not re-emit them as generated namespaces (a duplicate declare namespace bit would collide, and the base globals are top-level globals, not a
base.* namespace). The category is docs-only: a dedicated
LUA_STDLIB_MANIFEST vendors the same ref-doc JSON SYNC_MANIFEST carries,
but the docs-site is the only consumer; regen.ts / MODULE_MANIFEST never
read it, so no generated/<ns>.d.ts is produced. The topbar's "Lua standard
library" link leads to /api/base; the per-namespace page leads with a
lua-types provenance note.
Where ts-defold-types is arguably cleaner
One deliberate trade-off runs the other way. The @defold-typescript/types
@example block extracts the ref-doc examples field verbatim into a single
```lua fence — including the example's leading prose sentence (e.g.
"How to create and initialize a buffer"), which then sits inside the code
fence and is not valid Lua. ts-defold-types keeps the fence pure by putting that
prose on the @example line itself.
This is the documented slice-4 decision: the ref-doc ships the prose and the code
as one examples HTML blob, and splitting prose from code reliably is brittle, so
@defold-typescript/types keeps the sample intact and accepts a prose line inside
the fence. Hover still renders the sample; the prose reads as a leading comment.
Reversing this is explicitly out of scope for the parity work.
Which surface fits your project
Both surfaces cover the same symbols, so this comes down to which documentation shape you want in your editor:
- Reach for
@defold-typescript/typesif you want Markdown-rendered hovers, dash-style@params that editors lay out as a definition list, multi-line docs that stay aligned to the JSDoc grid, multi-value returns typed as a namedLuaMultiReturntuple, and branded constants that stay nominally distinct. - Reach for
ts-defold-typesif its one doc-quality edge matters to you: a pure@examplefence with the prose kept out on the@exampleline.
This is your call, not a verdict — pick the trade-off that reads best for how you work.