TypeScript type definition generator for GObject introspection GIR files
ts-for-gir reads GObject Introspection data and writes TypeScript definitions for GJS projects. Your editor then knows the whole GNOME stack: jump to definition, autocompletion, and a type error when you pass the wrong thing to g_object_set().
Project page on the gjsify website: gjsify.github.io/gjsify/projects/ts-for-gir. Install paths, quickstart, generator usage, and links to the Patterns docs.
Browse the full TypeScript API Documentation for GLib, GTK, GStreamer, and more.
gjsify dlx @ts-for-gir/cli create my-app # no install, no Node.js
# or
npx @ts-for-gir/cli create my-app # via npmPick a template interactively, or pass --template <id>:
| Template | Best for |
|---|---|
types-gjsify |
A GJS app with no Node.js. Install, build, run and format all go through gjsify |
types-npm |
Single-package, types from @girs/* NPM, esbuild + node |
types-locally |
Generate types into ./@types/ (no @girs/* dep) |
types-workspace |
npm workspace with @girs/* as locally-generated workspace packages |
cd my-app && npm start # or `gjsify run start` for types-gjsifycurl -fsSL https://raw.githubusercontent.com/gjsify/ts-for-gir/main/install.js -o /tmp/install.js
gjs -m /tmp/install.js && rm /tmp/install.jsInstalls to ~/.local/bin/. Update later with ts-for-gir self-update. Powered by GJSify.
If you already have the gjsify CLI, skip that. gjsify dlx @ts-for-gir/cli <args> runs it without installing, gjsify install -g @ts-for-gir/cli installs it globally.
npx @ts-for-gir/cli --help
# or globally:
npm install -g @ts-for-gir/clits-for-gir generate Gtk-4.0 # generate types for a single module
ts-for-gir generate Gtk-4.0 --reporter # with diagnostics
ts-for-gir analyze -f ./ts-for-gir-report.json # inspect the report
ts-for-gir --help # all commandsSee the CLI documentation for advanced options.
If you just want the types without generating them yourself:
npm install @girs/gjs @girs/gtk-4.0import "@girs/gjs";
import "@girs/gjs/dom";
import "@girs/gtk-4.0";
import Gtk from "gi://Gtk?version=4.0";
const button = new Gtk.Button();All packages are listed at gjsify/types. Missing a module? Open an issue.
The quickest start is the template. It sets up Meson, the Flatpak manifest and everything described below:
gjsify dlx @ts-for-gir/cli create my-app --template types-flatpakIf you are adding TypeScript to an existing app instead, read on. You keep Meson as your build system. Two facts about Flathub decide the rest: the build runs without network access, and the GNOME SDK does not include Node.js.
Usually not.
| You need types for | Run ts-for-gir in the Flatpak build? | Where the types come from |
|---|---|---|
Public GNOME libraries (Gtk-4.0, Adw-1, ...) |
No | @girs/* packages from npm |
Your own .gir files |
Better not | Generate them once, commit the output |
A .gir that changes with every build |
Yes | ts-for-gir runs offline in the sandbox, so it has to be in sources like every other npm package |
Most apps are in the first row. The @girs/* packages contain only types, and the
bundler removes types. The finished app contains one JavaScript bundle and no npm
packages, the same as an app written in JavaScript.
You still need npm packages while building: the compiler, the bundler and the
@girs/* types. flatpak-builder works in two phases. First it downloads everything
listed in the manifest's sources and checks each checksum. Then it runs the build
with the network switched off. So every package has to be listed in sources:
- Commit a lockfile.
- Generate a sources file from it, with one entry and checksum per package.
- Add that file to your module's
sourcesand tell npm to install from what was downloaded. Withflatpak-node-generatorthat means thesebuild-options.enventries:"npm_config_cache": "/run/build/<module>/flatpak-node/npm-cache"and"npm_config_offline": "true". - Install the bundle, not
node_modules.
flatpak-node-generator does step
2 for npm, yarn and pnpm lockfiles. If you use gjsify,
gjsify flatpak sources does
the same without needing Python.
Regenerate the sources file every time you change a dependency. The lockfile and the
sources file come from different commands. If you only update the lockfile, everything
works on your machine and the Flatpak build fails later with ENOTCACHED, because the
new package was never downloaded.
The TypeScript build step that Meson runs also runs inside the offline sandbox, so it has to install from the same cache.
Add org.freedesktop.Sdk.Extension.node24 to sdk-extensions. Two things tripped us up:
- Write the name without a branch. With
//25.08appended,flatpak-builderlooks up the extension under the GNOME runtime's version and fails withRequested extension ... not installed. - The extension is mounted at
/usr/lib/sdk/node24, which is not onPATH. Add/usr/lib/sdk/node24/binwithappend-pathinbuild-options, or Meson will not findnpm.
GNOME Applications
- Audio Player: Play audio files
- Counters: Keep track of anything
- Ignition: Manage startup apps and scripts
- Learn 6502: Learn programming on vintage game consoles
- Sound Recorder: A simple, modern sound recorder
- Sticky Notes: Pin notes to your desktop
- Weather: Show weather conditions and forecast
- K'uychi: Generate color palettes
GNOME Shell Extensions
- gTile: Tiling window management for GNOME Shell
- Copyous: Clipboard manager for GNOME Shell
- Rounded Window Corners: Add rounded corners to windows
These example projects wire the definitions up with different bundlers:
- GTK 4 Template with Vite: Modern UI with Vite bundling
- GNOME TypeScript Template: A template using GTK, libadwaita, TypeScript, Flatpak, and Meson
The Examples directory has more, with screenshots. The CLI documentation covers running them under different CLI options.
ts-for-gir consists of several packages:
@ts-for-gir/cli: Command-line interface for generating TypeScript definitions, documentation, and analyzing reports@gi.ts/parser: Parser for GObject Introspection XML files@ts-for-gir/lib: Core library for processing GIR data@ts-for-gir/reporter: Reporting system for problems and statistics with dependency injection@ts-for-gir/generator-typescript: TypeScript definition generator@ts-for-gir/generator-json: TypeDoc JSON generator with GIR metadata enrichment@ts-for-gir/generator-html-doc: HTML documentation generator using TypeDoc@ts-for-gir/generator-base: Shared base class for generators@ts-for-gir/typedoc-theme: Custom TypeDoc theme inspired by gi-docgen@ts-for-gir/gir-module-metadata: Curated metadata (descriptions, logos, licenses) for GIR namespaces@ts-for-gir/templates: Template files for generated packages (tsconfig, typedoc config, ambient declarations)@ts-for-gir/tsconfig: Shared TypeScript configuration@ts-for-gir/language-server: Language server for GIR files (experimental)
This repo contains Git submodules for pre-generated types and documentation:
types-dev(branchdev): used during local development. Scripts write generated packages here.types-release(branchmain): updated by the release workflow on tags.docs(branchmain): generated HTML documentation, deployed to gjsify.github.io/docs.
Useful scripts:
gjsify run build:types # regenerate into ./types-dev
gjsify run build:types:release # regenerate into ./types-release
gjsify run build:doc # build HTML docs into ./docs- TypeScript API Documentation
- Examples
- CLI Documentation
- Using ts-for-gir as a library: building your own TSX or framework types from GIR, and which of the three routes needs no library at all
- Publishing
@girs/*: how a 716-package set is released, why sibling ranges are carets, and the ordering defect that left 513 of v4.9.0's 716 packages uninstallable for up to two hours - gjsify/types: pre-generated NPM packages
- gjsify/gnome-shell: hand-written Shell Extension types

