IDE Integration
Brief: hook up your editor — the TypeScript language service plugin for live diagnostics, and
tstogd open-editorfor Godot’s external-editor integration.
TypeScript Language Service Plugin
Section titled “TypeScript Language Service Plugin”typescript-to-gdscript ships a TypeScript language service plugin that runs inside your IDE’s tsserver and surfaces converter + Godot diagnostics as real TypeScript squiggles — including on unsaved buffer contents.
Converter diagnostics surfaced
Section titled “Converter diagnostics surfaced”- Conversion errors — unsupported TS features;
.gdis NOT emitted:varkeyword (useletorconst)undefinedkeyword as a value (usenull)- Optional chaining (
?.), nullish coalescing (??,??=) - Spread operator (
...), destructuring yield,for...in- Multiple classes per file
- Top-level statements outside classes
- Type errors —
.gdis still emitted, but the plugin reports them inline:undefinedin function parameter type annotations- Argument that may be
undefined ||/&&used as a non-boolean valuex in ywhereyis a value-type primitive (Vector2, Color, Transform2D, etc.), an array (Array<T>,T[], a tuple,Packed*Array), a number, or a boolean — only a dictionary keepsin’s meaning; on an array use.has(value)- Call returning
Promise<T>used as a value withoutawait(assigned, passed as argument, returned, etc.) — GDScript has no Promise; an unawaited coroutine resolves to aGDScriptFunctionStateat runtime
- Godot validation errors (when Godot is available on
PATH) — type mismatches, unknown functions/methods, parse errors in the generated GDScript. These fire asynchronously ~300–500ms after the converter diagnostics and are merged into the IDE’s diagnostic list via an internal tsserver refresh.
Godot validation is enabled automatically when the Godot executable is found on the system (resolved via resolveGodotPath()). To disable it, set disableGodotLint: true in tstogd.json. Source maps are always generated for error remapping.
Enable it
Section titled “Enable it”Add to your project’s tsconfig.json (added automatically on tstogd init):
{ "compilerOptions": { "plugins": [{ "name": "typescript-to-gdscript/ts-plugin" }] }}Plugin options
Section titled “Plugin options”| Option | Type | Description |
|---|---|---|
debug |
boolean |
Emit verbose [tstogd-plugin] TRACE lines to the tsserver log. Off by default. |
debugLog |
string |
File path. When set, plugin log + trace lines are appended there in addition to the tsserver log — easier than fishing trace lines out of tsserver.log. |
disableGodotLint |
boolean |
Per-editor override for tstogd.json’s disableGodotLint. Set true to skip the async Godot pass in the IDE only; set false to force-enable it. |
Example — silence the Godot pass in the IDE without changing project-wide config:
{ "compilerOptions": { "plugins": [ { "name": "typescript-to-gdscript/ts-plugin", "disableGodotLint": true } ] }}Tell the IDE to use the workspace’s TypeScript — plugins only load through tsserver spawned by the workspace typescript package, not the IDE’s bundled one:
- WebStorm: Settings → Languages & Frameworks → TypeScript — set “TypeScript” to
node_modules/typescript(typically auto-detected), ensure “TypeScript Language Service” is ON, then restart the TS service (File → Invalidate Caches → Just Restart is the blunt way). - VS Code: Open any
.tsfile, Command Palette →TypeScript: Select TypeScript Version...→Use Workspace Version.
Verify: the plugin logs [tstogd-plugin] plugin loaded on startup. WebStorm → Help → Show Log in Explorer/Finder → idea.log; VS Code → Output panel → TypeScript.
What it does
Section titled “What it does”-
Inline diagnostics on the current buffer. On every
getSemanticDiagnosticsquery, the plugin runsconvertTsToGdin-process using tsserver’s ownts.Program(no fork, no IPC — just reuses the warm program + type checker). Converter diagnostics (conversion errors, type-errors,||/&&as value,Promiseas value, etc.) appear asts.Diagnostics withsource: 'tstogd'and codes in the90000–90099range. -
Noise filtering. A few TypeScript diagnostics cannot mean anything in this dialect. The plugin silently drops these for all in-scope files so you never see them in the IDE:
TS2434/TS2435— “Namespace must precede the class declaration”TS2449— “Class used before its declaration”
The first three come from the
export namespace Foo { ... }+export class Foomerge that expresses enums and inner classes here.TS2377— “Constructors for derived classes must contain a ‘super’ call”TS17009— “‘super’ must be called before accessing ‘this’”
These two exist because a JavaScript object doesn’t exist until the base constructor has run. Nothing here runs as JavaScript, and GDScript’s
_inithas no such rule —selfis live throughout, and the parent_initruns only if you call it. Sosuper()is optional in a constructor; write it when you mean to run the parent’s_init, leave it out when you don’t. Seesupercalls.Nothing else is filtered. In particular
noFallthroughCasesInSwitch(TS7029) is left alone: it fires on every case in this dialect, but it’s a setting you chose, and the plugin doesn’t overrule your compiler options. Turn it off — seeswitch→match. -
Godot validation in the background. After conversion, the plugin kicks off
validateGdFilesasynchronously against the cache-folder.gdmirror. When Godot finishes (~300–500ms later), the plugin merges its diagnostics and callsrefreshDiagnostics()on the project — your IDE updates without you doing anything. -
Cancellation. Typing another character while Godot is still running aborts the stale validation (both the subprocess and the superseded result) — no stale squiggles from a version you’ve already moved past.
-
Persistent-cache write-through. Every live conversion updates the shared
ProjectCache(keyed by buffer hash). When you save,tstogd watch(ortstogd convert --use-cache) detects that the cache already holds the right bytes and promotes them with a singlerename()— no double conversion.
Plugin diagnostic codes
Section titled “Plugin diagnostic codes”| Code | Meaning |
|---|---|
90000 |
converter error / warning / info |
90001 |
converter type-error |
All plugin-originated diagnostics have source: 'tstogd', so you can filter them in IDE settings if needed.
tstogd open-editor
Section titled “tstogd open-editor”Open a GDScript file in an external editor as the corresponding TypeScript file. Designed for Godot’s external text editor integration - when you double-click a script in Godot, it opens the .ts source instead of the generated .gd file.
tstogd open-editor -f {file} -l {line} -c {col} -p {project} -e "code --goto {tsFile}:{tsLine}:{tsCol}"Options:
-f, --file <path>– GDScript file path (absolute orres://)-e, --editor-cmd <cmd>– Editor command template. Placeholders:{tsFile},{tsLine},{tsCol}(plus any Godot placeholders like{line},{col})-l, --line <n>– GDScript line number (from Godot, default:1)-c, --col <n>– GDScript column number (from Godot, default:1)-p, --project <dir>– Godot project directory (wheretstogd.jsonis)
How it works:
- Loads
tstogd.jsonfrom the project directory - Maps the
.gdfile to.tsfile usinggdDir->tsDirpath mapping - Remaps GD line:col to TS line:col using cached source maps (
{tsLine},{tsCol}) - Replaces
{tsFile},{tsLine},{tsCol}in the editor command - Spawns the editor process
Godot configuration
Section titled “Godot configuration”In Godot, go to Editor Settings → Text Editor → External and configure:
- Use External Editor:
On - Exec Path:
tstogd(ornpx tstogd, or full path to the binary) - Exec Flags:
open-editor -f "{file}" -l {line} -c {col} -p "{project}" -e "code --goto {tsFile}:{tsLine}:{tsCol}"
Note: Use double quotes around
{file}and{project}to handle paths with spaces.
Also enable Editor Settings → Text Editor → Behavior → Auto Reload Scripts on External Change. When you edit TypeScript files and the converter regenerates the .gd output, Godot needs to pick up the changes without manually refocusing or reopening each script. With this option enabled, Godot automatically reloads any .gd file that was modified on disk, so your changes take effect immediately when you switch back to the editor.
Debug with external editor
Section titled “Debug with external editor”Godot has a separate toggle for whether runtime errors (stack traces in the Debugger panel) open in the external editor vs the built-in script editor. The “Use External Editor” setting in Editor Settings → Text Editor → External only controls double-click-to-open from the FileSystem dock — it does not cover debugger stack-frame clicks.
To also route debugger errors to your external editor, switch to the Script tab at the top of the Godot editor and look for the option there — the Script workspace has its own menu bar. From godotengine/godot#65554:
if you select the Script tab, that has its own menu bar, where you can find the option as described.
If the toggle is off, clicking a stack frame silently does nothing — tstogd open-editor is never invoked, so you won’t see the editor open and there’ll be no entry in the debug log. See related Godot issues: #65554, #84294, #95198.
Editor command examples
Section titled “Editor command examples”| Editor | -e flag |
|---|---|
| VS Code | -e "code --goto {tsFile}:{tsLine}:{tsCol}" |
| Rider | -e "rider --line {tsLine} --column {tsCol} {tsFile}" |
| Vim | -e "vim +{tsLine} {tsFile}" |
