Typings
Brief: typings generation commands (Godot classes, scene typings, addons, project classes) and the structure of the generated typings tree.
Typings folder layout
Section titled “Typings folder layout”Typings are stored in a flat typings/ folder (no version subdirectories):
typings/ index.d.ts # Entry point (references globals/, classes/) globals/ # Static stubs that ship with the package (NOT regenerated from Godot docs) globals.d.ts # noLib stubs (Boolean, Number, RegExp, …) used when consumers set "noLib": true gd-helpers.d.ts # gd namespace types (signal, getset, dict, as, is, typeof, eval, match, ops) + int/float/bool/String casts + StringName/NodePath constructors + Promise deprecation overlay godot-class-registry.json # Class hierarchy JSON classes/ # Per-class .d.ts filesThe generate-gdscript-global-typings command outputs the generated classes/, godot-class-registry.json to --output-dir. It also copies the bundled static globals/ folder and index.d.ts from the installed package’s typings/ into --output-dir (skipped when --output-dir is the package’s own bundled folder, e.g. when re-running yarn generate:godot-typings in the source tree).
Value types (Vector2, Color, etc.), Dictionary, and Callable use call syntax constructors (no new). Dictionary and Callable constructors and static methods are generated from Godot XML docs via a shared generateConstructorInterface() utility.
Global enums
Section titled “Global enums”Godot’s global enums keep their GDScript spelling. Undotted ones are plain const enums (Key.KEY_A); a dotted one becomes a namespace, so Variant.Type reads the same in TypeScript as it does in GDScript:
let kind: Variant.Type = gd.typeof(value);if (kind === Variant.Type.TYPE_INT) { ... }A global function whose Godot name is a TypeScript keyword gets no declaration of its own — typeof is the only one, and it lives on the gd namespace as gd.typeof.
Nullable reference types
Section titled “Nullable reference types”Generated typings distinguish between value types and reference types for nullability:
- Reference types (Node, Material, Texture2D, etc.) — properties and method return types are generated as
T | null, matching GDScript semantics where these can benullat runtime. - Value types (Vector2, Color, int, float, Rect2, Transform2D, etc.) — remain non-nullable, since GDScript always initializes them to a default value.
A type is classified as a value type if its Godot XML documentation includes a copy constructor (a constructor with a single parameter of its own type). This is derived automatically from the parsed XML docs at generation time — no hardcoded type lists.
Overrides: Files in typings-overrides/ can restore non-null return types for specific members where null is never returned in practice. For example, typings-overrides/node.d.ts overrides get_tree(): SceneTree, get_viewport(): Viewport, and get_window(): Window as non-null.
tstogd generate-typings
Section titled “tstogd generate-typings”Both
tstogd convertandtstogd watchrun this automatically on every conversion, so you normally never call it directly. Use it standalone only to regenerate typings without converting (CI, scripted builds, or after editing scenes outside a running watcher).
Generates scene typings — per-file .d.ts declarations that provide typed get_node(), get_parent(), get_child(), and group methods based on your .tscn scene structure.
tstogd generate-typingsThis generates in your typingsDir:
.tscn.d.ts— Tree type structure for each scene (node types, parent/child relationships, flat paths).gd.d.ts— Module augmentation per script with typedget_node()overloads. A script is keyed by theres://path of the.gdthatconvertwrites undergdDir, the path your scenes attach._resources.d.ts— BundledGodotResourcesentries for all asset files_index.d.ts— Empty global interfaces (GodotScripts,GodotSceneTrees,GodotScenes,GodotResources,GodotGroups,GodotConnections), the sixkeyofaliases (GodotResourceName,GodotSceneName,GodotSceneTreeName,GodotScriptName,GodotGroupName,GodotConnectionSceneName), and autoload singleton declarations
Global project key-union types
Section titled “Global project key-union types”Each of the six project-wide interfaces gets a parallel Godot<X>Name alias defined as keyof Godot<X>s. The aliases live in _index.d.ts inside declare global, so they’re available without an import.
| Alias | Equivalent to | What its values look like |
|---|---|---|
GodotResourceName |
keyof GodotResources |
"res://Player.tscn", "res://Enemy.gd", "res://icon.png", … |
GodotSceneName |
keyof GodotScenes |
"res://Player.tscn", "res://Level.tscn", … |
GodotSceneTreeName |
keyof GodotSceneTrees |
Same set as GodotSceneName — pick this one if you want the tree type, not the root node |
GodotScriptName |
keyof GodotScripts |
"res://Player.gd", "res://Enemy.gd", … |
GodotGroupName |
keyof GodotGroups |
"enemies", "entities", … (group identifiers from .tscn) |
GodotConnectionSceneName |
keyof GodotConnections |
Scene paths that have [connection] entries |
keyof is resolved lazily, so each alias picks up new entries as more .tscn.d.ts / .gd.d.ts / _resources.d.ts files merge into the underlying interfaces. Typos in resource paths or group names become compile-time errors, and IDEs autocomplete the literal union as you type.
class AssetRegistry extends Node { cache: Dictionary<GodotResourceName, Resource> = {};
preload_asset(path: GodotResourceName) { if (!this.cache.has(path)) this.cache.set(path, load(path)); return this.cache.get(path); }
pick_random_group(group: GodotGroupName): Node | null { const nodes = this.get_tree().get_nodes_in_group(group); return nodes.size() > 0 ? nodes[0] : null; }}For the typed lookup itself (turning a path into its resource type, a group name into its node-union, a script path into its class), index the interface directly:
const player_class: GodotScripts["res://Player.gd"] = Player; // typeof Playerconst level_tree: GodotSceneTrees["res://Level.tscn"] = /* ... */; // tree typeconst enemies: GodotGroups["enemies"]["res://Level.tscn"] = /* ... */;uid:// paths
Section titled “uid:// paths”Each GodotResources entry is also keyed by the resource’s Godot UID, so load("uid://…"), preload("uid://…"), and change_scene_to_file("uid://…") resolve to the exact same type as their res:// form:
const player = preload('uid://test_player_scene'); // PackedScene<…>, same as preload("res://Player.tscn")UIDs are read from Godot’s own metadata — the .tscn/.tres header, the .gd.uid sidecar (scripts/shaders), or the .import sidecar (imported assets) — so a uid:// key only appears once Godot has imported the project and written that metadata. Resources without a UID still resolve normally through their res:// path.
Scene typings features
Section titled “Scene typings features”-
Typed
get_node(): autocomplete for node paths, returns exact node typesTypeScript let sprite: Sprite2D = this.get_node('Sprite2D');let label: Label = this.get_node('UI/ScoreLabel'); -
Typed
get_node_or_null(): same asget_node()but always includes| null -
NodePathvalues:get_node,get_node_or_nullandhas_nodealso accept aNodePath, as Godot’s own signatures do. A path held in a variable carries no literal to look up, so the result is untyped (Node | null). -
Absolute
/root/paths: type-inferred from the root scene treeTypeScript let player: Player = this.get_node('/root/Level/Player'); -
Unique name nodes (
%Name): accessible from any node in the sceneTypeScript let health: ProgressBar = this.get_node('%HealthBar'); -
Typed
get_parent(): resolves to parent scene’s script class -
Typed
get_child(idx): resolves to child node type by index -
Instanced scene support: instanced scene nodes carry their full tree, enabling deep path traversal
-
Scene inheritance (
__node_extends): extended scenes inherit base scene paths lazily -
Group typing:
get_nodes_in_group()returns typed arrays based on which nodes are in each groupTypeScript let enemies: Array<Player | Enemy> =this.get_tree().get_nodes_in_group('entities'); -
Autoload scenes: scene autoloads typed as tree nodes with
get_node()supportTypeScript let bar: ProgressBar = UIManager.get_node('HealthBar'); -
Static fields on instances: class static members (enums, etc.) accessible on instances via
StaticProps -
Non-Node scripts excluded: scripts that don’t extend Node (e.g.
extends Resource) skip tree navigation typings (ScriptTree,get_nodeoverrides,__Treesinterface) since they have no scene tree context
tstogd generate-addon-typings
Section titled “tstogd generate-addon-typings”Generate TypeScript typings for GDScript addon files in addons/. Converts each .gd file to .ts (via GD-to-TS), then generates .gd.d.ts scene typings with global class declarations, GodotScripts/GodotResources entries, and namespace enums.
tstogd generate-addon-typingsOptions:
-o, --output <path>— Output directory for generated typings--root-dir <dir>— Root directory (default:.)
Output structure preserves the addon directory layout:
ts/_typings/ addons/MyAddon/ my_script.ts ← converted from GDScript my_script.gd.d.ts ← typings (global class, GodotScripts, enums)This command is automatically called by initial-convert-gd-to-ts and watch (on first run). It can also be run standalone.
tstogd generate-gdscript-global-typings
Section titled “tstogd generate-gdscript-global-typings”Most users never run this. The package already ships pre-generated typings for the supported stock Godot version (
typings/classes/+godot-class-registry.json). You only need this command if you’re on a different engine version, a fork, or one with extra C++ modules / GDExtension classes — and want the engine-class typings to match your build exactly.
Generate the bundled Godot engine class typings and class registry from Godot’s XML class docs. The Godot version is auto-detected from version.py next to the docs (or vendor/godot/version.py).
Point --godot-source at a Godot source tree and it reads the whole class reference, from the same three places Godot’s own documentation build does: doc/classes/ for the core, every modules/<module>/doc_classes/, and every platform/<platform>/doc_classes/ (the editor’s export platforms). The modules matter — RegEx, the CSG nodes, GridMap, MultiplayerSpawner, FastNoiseLite, the Ogg and MP3 streams and more are documented there, not in doc/classes/.
--docs-dir takes extra XML directories for a layout --godot-source doesn’t describe. It is variadic, so place it last on the command line — it consumes every following positional value until the next flag. Later dirs override earlier ones for same-named classes.
Options:
--godot-source <dir>— A Godot source tree; readsdoc/classes/, everymodules/*/doc_classes/and everyplatform/*/doc_classes/.--docs-dir <dirs...>— Extra Godot XML class documentation directories. One of the two options is required.--output-dir <dir>— Root typings output directory (default:typings).--override-dir <dir>— User override directory for.d.tsfiles andnon-nullable.json(combined with bundled defaults).--no-default-overrides— Disable the bundled default overrides.
Using it for a custom Godot build
Section titled “Using it for a custom Godot build”The Godot source tree contains the class XML you need under doc/classes/ (core) and modules/<name>/doc_classes/ (per-module / custom classes) — --godot-source reads both, including custom modules you placed under modules/. A module built from outside the tree (SCons custom_modules=) is not there: add its doc_classes/ with --docs-dir. Generate typings into a folder you control, then point both tsconfig.json and tstogd.json at it.
1. Generate the typings from your Godot’s docs. Pick an output directory outside node_modules (so it survives reinstalls), e.g. _godot-typings/:
tstogd generate-gdscript-global-typings \ --output-dir _godot-typings \ --godot-source /path/to/your-godotThis writes _godot-typings/classes/, _godot-typings/godot-class-registry.json, and copies the static globals/ + index.d.ts into it — a complete, self-contained typings tree.
2. Point tsconfig.json at the custom typings instead of the bundled package ones. Replace the node_modules/typescript-to-gdscript/typings entry in include with your folder:
{ "compilerOptions": { "noLib": true, "strict": true, "noEmit": true, "types": [], }, "include": [ "_godot-typings", // ← your generated engine typings (was node_modules/typescript-to-gdscript/typings) "src/**/*.ts", "src/_typings/**/*.d.ts", ],}3. Point tstogd.json at the same folder via godotTypingsDir:
{ "tsDir": "src", "gdDir": "scripts", "typingsDir": "src/_typings", "godotTypingsDir": "_godot-typings"}godotTypingsDir (resolved relative to the directory containing tstogd.json) is what generate-typings writes into the /// <reference path="…" /> line at the top of the generated _index.d.ts, so your IDE eagerly indexes your custom engine classes for autocomplete. It defaults to the bundled package typings when unset.
Conversion registry (GD → TS only). The godot-class-registry.json the converter uses for this.-resolution, operator detection, and nullable classification is separate from the typings tree — it is not read from godotTypingsDir. If you’re migrating GDScript with custom classes, pass your generated registry explicitly:
tstogd initial-convert-gd-to-ts --registry _godot-typings/godot-class-registry.json(generate-typings and convert always use the bundled registry; only initial-convert-gd-to-ts accepts --registry.)
Re-run step 1 whenever you rebuild Godot with new/changed classes.
Keep
_godot-typings/in version control (or a build step) so teammates and CI get the same engine surface. The bundled package typings remain the default whenevergodotTypingsDiris unset.
Custom override files
Section titled “Custom override files”Godot’s XML docs don’t capture everything TypeScript wants — some methods are documented as returning a base class when they always return a concrete one, some return values are never actually null, and some methods deserve extra overloads or generics. The generator applies a layer of overrides on top of the raw XML to fix these. The package ships a default set — browse typings-overrides/ as a working reference — and you can supply your own via --override-dir, useful for custom-module classes, project-specific refinements, or correcting an engine signature you know better than the docs.
tstogd generate-gdscript-global-typings \ --output-dir _godot-typings \ --override-dir my-overrides \ --godot-source /path/to/your-godotYour directory is combined with the bundled defaults (defaults loaded first, your dir second). Pass --no-default-overrides to drop the bundled set entirely and use only yours. Conflicts resolve by declaration name: if both you and the bundled set override the same class X, your declaration of X replaces the bundled one as a whole (re-list any bundled members you still want). Classes you don’t touch keep their bundled overrides. An override directory can contain two kinds of files:
1. .d.ts member overrides
Section titled “1. .d.ts member overrides”Each .d.ts file declares one or more interface X { … } / declare class X { … } blocks. The declaration name (not the filename) is the key — the members you list are applied on top of the class X generated from the XML. A member you declare replaces the generated one; a member that doesn’t exist yet is added; multiple signatures for the same name become overloads. Members of X you don’t mention keep their XML-generated form.
// my-overrides/resource.d.tsdeclare class Resource { // `duplicate()` is documented as returning Resource; refine to `this` // so subclasses keep their own type. duplicate(deep?: boolean): this;}// my-overrides/node.d.ts — add a generic so the result type is precisedeclare class Node { get_parent<N extends Node = Node>(): N;}This is exactly how the bundled defaults work — see typings-overrides/ for real examples: array.d.ts, dictionary.d.ts, node.d.ts, packed-scene.d.ts, and more. A special _globals.d.ts overrides global functions (the @GlobalScope free functions like load, preload, str) the same way.
2. non-nullable.json — opt members out of T | null
Section titled “2. non-nullable.json — opt members out of T | null”By default every reference-typed return is widened to T | null (see Nullable reference types). When a method never returns null in practice, list it in non-nullable.json to keep its return type strict. The format is ClassName → [methodName, …]:
{ "Node": ["get_tree", "get_viewport", "get_window"], "SceneTree": ["create_timer", "create_tween", "root"], "MyCustomSingleton": ["get_instance"]}With the entry above, node.get_tree() is typed SceneTree instead of SceneTree | null. Your non-nullable.json merges with the bundled one per class: a class you list replaces the bundled member list for that class (so re-list the bundled members if you’re extending an already-covered class like Node), while classes you omit keep their bundled entries. See the bundled typings-overrides/non-nullable.json for the full default set.
Both file kinds are optional and independent — an override dir can have just
.d.tsfiles, justnon-nullable.json, or both. After generating, pointtsconfig.json+tstogd.jsonat the output folder as shown above.
