On this page
Typing native extensions
Defold native extensions ship their own Lua API alongside the engine's. When a
project depends on an extension, defold-typescript resolve reads that
extension's .script_api docs and generates an ambient TypeScript namespace for
it — the same fan-out the built-in engine namespaces (go, vmath, …) go
through, applied to whatever extensions your project actually declares. The
generated surface lands in a project-local, gitignored .defold-types/ package,
so extension functions gain autocomplete and tsc coverage with no import.
Declaring an extension
Extensions are declared in game.project under [dependencies], one archive
URL per numbered key — the same INI surface the Defold editor's Fetch
Libraries writes:
[project]
title = My Game
[dependencies]
dependencies#0 = https://github.com/defold/extension-iap/archive/main.zip
dependencies#1 = https://github.com/some/asset-pack/archive/main.zip
resolve reads every dependencies#N URL under [project]. A game.project
with no [project] section is an error; a [project] with no dependencies#N
keys reports no extension dependencies declared and exits cleanly.
Materializing the types: resolve
The resolve command reads every dependencies#N URL, downloads
and caches each archive, and emits one ambient namespace per .script_api doc
into .defold-types/extensions/, wiring it into tsconfig.json:
bunx @defold-typescript/cli resolve
Run it once after declaring a dependency, and re-run it (or leave
watch running, which re-resolves on every game.project save)
whenever you edit [dependencies]. See Resolve for the full
behavior, the --frozen lockfile mode, version pinning, and the cache location.
Consuming the generated namespace
Each emitted namespace is ambient, so you call it with no import — exactly like the engine namespaces:
// iap is ambient — resolved through the .defold-types/extensions surface.
iap.set_listener((self, transaction, error) => {
// transaction and error are typed from the extension's .script_api
});
tsc picks the surface up through the "extensions" entry in
compilerOptions.types.
For the command itself — --frozen, version pinning, drift detection, and the
cache location — see Resolve.