Skip to content

Latest commit

 

History

History

README.md

TS for GIR

TypeScript type definition generator for GObject introspection GIR files

CLI

CLI tool to generate TypeScript type definitions and HTML documentation for GObject Introspection Repository (GIR) files, primarily for GJS applications.

Getting started

Install (GJS, without Node.js)

curl -fsSL https://raw.githubusercontent.com/gjsify/ts-for-gir/main/install.js -o /tmp/ts-for-gir-install.js
gjs -m /tmp/ts-for-gir-install.js
rm /tmp/ts-for-gir-install.js

Installs ts-for-gir to ~/.local/bin/ts-for-gir. Update later with:

ts-for-gir self-update

Install (Node.js)

npx @ts-for-gir/cli --help

Alternatively add @ts-for-gir/cli to your dependencies:

npm install --save-dev @ts-for-gir/cli

Or install globally:

npm install -g @ts-for-gir/cli
ts-for-gir --help

GJS bundle

The GJS bundle (ts-for-gir-gjs) supports the full TypeScript / TypeDoc pipeline thanks to gjsify's runtime-relative import.meta.url rewrite. All non-interactive commands run natively on GJS:

  • ts-for-gir generate: .d.ts generation
  • ts-for-gir json: TypeDoc-backed JSON export
  • ts-for-gir doc: HTML documentation. TypeDoc's shiki highlighter loads the oniguruma regex engine via WebAssembly.compile(...). GJS 1.88 (SpiderMonkey 140) exposes the synchronous WebAssembly.{Module,Instance} constructors but ships the Promise APIs as stubs that throw on first call; @gjsify/webassembly (gjsify v0.3.6+) wraps the synchronous constructors with Promise.{resolve,reject} so compile/instantiate resolve natively in the GJS bundle.
  • ts-for-gir list / copy / analyze / self-update

The only command still gated on Node.js is create. Its inquirer-based interactive prompt cannot run on GJS without a TTY-aware port. Use npx @ts-for-gir/cli create ... from a Node install for now.

TypeScript type definition generator for GObject introspection GIR files

Commands:
  ts-for-gir generate [modules..]  Generates .d.ts files from GIR for GJS
  ts-for-gir json [modules..]      Generates JSON representation from GIR files for analysis and tooling
  ts-for-gir doc [modules..]       Generates HTML documentation from GIR files using TypeDoc
  ts-for-gir list [modules..]      Lists all available GIR modules
  ts-for-gir copy [modules..]      Scan for *.gir files and copy them to a new directory
  ts-for-gir analyze               Analyze report files generated by ts-for-gir reporter

Options:
  --version  Show version number                                       [boolean]
  --help     Show help                                                 [boolean]

Example

To generate the TypeScript type definitions of Gtk-4.0 for GJS run:

ts-for-gir generate Gtk-4.0

You can also look at the examples to see how the types are generated and/or used there.

Generate .d.ts files

ts-for-gir generate [modules..]

Generates .d.ts files from GIR for GJS

Options:
      --version                 Show version number                    [boolean]
      --help                    Show help                              [boolean]
      --modules                 GIR modules to load, e.g. 'Gio-2.0'. Accepts
                                multiple modules        [array] [default: ["*"]]
  -g, --girDirectories          GIR directories                          [array]
      --root                    Root directory of your project           [string]
  -o, --outdir                  Directory to output to
                                                  [string] [default: "./@types"]
  -i, --ignore                  Modules that should be ignored
                                                           [array] [default: []]
  -v, --verbose                 Switch on/off the verbose mode
                                                      [boolean] [default: false]
      --ignoreVersionConflicts  Skip prompts for library version selection when
                                multiple versions are detected
                                                      [boolean] [default: false]
  -p, --print                   Print the output to console and create no files
                                                      [boolean] [default: false]
      --configName              Specify a custom name for the configuration file
                                          [string] [default: ".ts-for-girrc.js"]
  -d, --noNamespace             Do not export all symbols for each module as a
                                namespace             [boolean] [default: false]
  -n, --noComments              Do not generate documentation comments
                                                      [boolean] [default: false]
      --promisify               Generate promisified functions for async/finish
                                calls                  [boolean] [default: true]
      --widgetVocabulary           Emit the GIR-derived widget vocabulary on a
                                `./vocabulary` subpath for namespaces that declare
                                GtkWidget descendants [boolean] [default: false]
      --npmScope                Scope of the generated NPM packages
                                                     [string] [default: "@girs"]
      --bundle                  Emit every generated namespace as ONE npm package
                                with this name (e.g. '@girs/sdk-gnome-50').
                                Implies --package and sets --npmScope    [string]
      --bundleMeta              JSON object merged into the bundle package.json,
                                for provenance the generator cannot know. Only
                                valid with --bundle                      [string]
      --workspace               Uses the workspace protocol for the generated
                                packages              [boolean] [default: false]
      --onlyVersionPrefix       Only use the version prefix for the ambient
                                module exports        [boolean] [default: false]
      --noPrettyPrint           Do not prettify the generated types
                                                      [boolean] [default: false]
      --noAdvancedVariants      Disable GLib.Variant class with string parsing
                                                      [boolean] [default: false]
      --package                 Generate the typescript types with package.json
                                support               [boolean] [default: false]
      --reporter                Enable generation problem reporter and create a
                                detailed report file  [boolean] [default: false]
      --reporterOutput          Output file path for the reporter
                               [string] [default: "ts-for-gir-report.json"]

Examples:
  ts-for-gir generate                                Run 'ts-for-gir generate'
                                                     in your gjs project to
                                                     generate typings
  ts-for-gir generate 'Gtk*'                         You can also use wild cards
  ts-for-gir generate '*'                            Parse all locally installed
                                                     gir modules
  ts-for-gir generate --configName='.rc.js'          Use a special config file
  ts-for-gir generate --ignore=Gtk-4.0 xrandr-1.3   Generate .d.ts files but
                                                     not for Gtk-4.0 and
                                                     xrandr-1.3

Generate TypeDoc JSON

Generates TypeDoc JSON output enriched with GIR-specific metadata. This is useful as an intermediate step before generating HTML documentation (see doc --merge), or for custom tooling.

ts-for-gir json [modules..]

Generates JSON representation from GIR files for analysis and tooling

Options:
      --version                 Show version number                    [boolean]
      --help                    Show help                              [boolean]
      --modules                 GIR modules to load, e.g. 'Gio-2.0'. Accepts
                                multiple modules        [array] [default: ["*"]]
  -g, --girDirectories          GIR directories                          [array]
      --root                    Root directory of your project           [string]
  -o, --outdir                  Directory to output to
                                                  [string] [default: "./@types"]
  -i, --ignore                  Modules that should be ignored
                                                           [array] [default: []]
  -v, --verbose                 Switch on/off the verbose mode
                                                      [boolean] [default: false]
      --ignoreVersionConflicts  Skip prompts for library version selection when
                                multiple versions are detected
                                                      [boolean] [default: false]
      --configName              Specify a custom name for the configuration file
                                          [string] [default: ".ts-for-girrc.js"]

Examples:
  ts-for-gir json                          Generate JSON for all modules
  ts-for-gir json Gtk-4.0 --outdir ./json  Generate JSON for Gtk-4.0 into ./json
  ts-for-gir json '*' --outdir ./json      Generate JSON for all modules

Generate HTML documentation

Generates a browsable HTML API reference using TypeDoc. Supports two modes:

  • Direct mode: Generates .d.ts files from GIR, then converts to HTML in one step.
  • Merge mode (--merge): Reads pre-generated JSON files (from ts-for-gir json) and produces HTML. This uses less memory and is suitable for large module sets.

The generated documentation uses a custom theme inspired by gi-docgen with a 3-column layout, GIR metadata badges, and categorized module listings.

See the live documentation at gjsify.github.io/docs.

ts-for-gir doc [modules..]

Generates HTML documentation from GIR files using TypeDoc

Options:
      --version                 Show version number                    [boolean]
      --help                    Show help                              [boolean]
      --modules                 GIR modules to load, e.g. 'Gio-2.0'. Accepts
                                multiple modules        [array] [default: ["*"]]
  -g, --girDirectories          GIR directories                          [array]
      --root                    Root directory of your project           [string]
  -o, --outdir                  Directory to output to
                                                    [string] [default: "./docs"]
  -i, --ignore                  Modules that should be ignored
                                                           [array] [default: []]
  -v, --verbose                 Switch on/off the verbose mode
                                                      [boolean] [default: false]
      --ignoreVersionConflicts  Skip prompts for library version selection when
                                multiple versions are detected
                                                      [boolean] [default: false]
      --configName              Specify a custom name for the configuration file
                                          [string] [default: ".ts-for-girrc.js"]
      --combined                Generate a single unified documentation for all
                                modules (use --no-combined for separate
                                per-module docs)       [boolean] [default: true]
      --sourceLinkTemplate      URL template for source links in generated
                                documentation. Supports {path}, {line},
                                {gitRevision} placeholders              [string]
      --theme                   Theme for HTML documentation generation.
                                Use "default" for TypeDoc's built-in theme.
                                              [string] [default: "gi-docgen"]
      --readme                  Path to a README file for the documentation
                                index page. Use "none" to disable.      [string]
      --merge                   Use TypeDoc merge mode to generate HTML from
                                pre-generated JSON files (requires --jsonDir)
                                                      [boolean] [default: false]
      --jsonDir                 Directory containing pre-generated TypeDoc JSON
                                files for merge mode (from 'ts-for-gir json')
                                                                        [string]

Examples:
  ts-for-gir doc Gtk-4.0 --outdir ./docs       Generate HTML documentation
                                                for Gtk-4.0
  ts-for-gir doc '*' --outdir ./docs            Generate documentation for all
                                                locally installed GIR modules
  ts-for-gir doc --merge --jsonDir ./json       Generate HTML from pre-generated
      --outdir ./docs                           JSON files (low memory)

Two-phase workflow

For large module sets, you can split documentation generation into two phases to reduce peak memory usage:

# Phase 1: Generate JSON files (one per module)
ts-for-gir json '*' --outdir ./json

# Phase 2: Merge JSON files into HTML documentation
ts-for-gir doc --merge --jsonDir ./json --outdir ./docs

List available GIR modules

ts-for-gir list [modules..]

Lists all available GIR modules

Options:
      --version         Show version number                            [boolean]
      --help            Show help                                      [boolean]
      --modules         GIR modules to load, e.g. 'Gio-2.0'. Accepts
                        multiple modules                [array] [default: ["*"]]
  -g, --girDirectories  GIR directories                                  [array]
      --root            Root directory of your project                   [string]
  -i, --ignore          Modules that should be ignored     [array] [default: []]
      --configName      Specify a custom name for the configuration file
                                          [string] [default: ".ts-for-girrc.js"]
  -v, --verbose         Switch on/off the verbose mode [boolean] [default: false]

Examples:
  ts-for-gir list -g ./vala-girs/gir-1.0             Lists all available GIR
                                                      modules in
                                                      ./vala-girs/gir-1.0
  ts-for-gir list --ignore=Gtk-3.0 xrandr-1.3        Lists all available GIR
                                                      modules but not Gtk-3.0
                                                      and xrandr-1.3

Copy GIR files

ts-for-gir copy [modules..]

Scan for *.gir files and copy them to a new directory

Options:
      --version         Show version number                            [boolean]
      --help            Show help                                      [boolean]
      --modules         GIR modules to load, e.g. 'Gio-2.0'. Accepts
                        multiple modules                [array] [default: ["*"]]
  -g, --girDirectories  GIR directories                                  [array]
      --root            Root directory of your project                   [string]
  -o, --outdir          Directory to output to            [string] [default: "./@types"]
  -i, --ignore          Modules that should be ignored     [array] [default: []]
      --configName      Specify a custom name for the configuration file
                                          [string] [default: ".ts-for-girrc.js"]
  -v, --verbose         Switch on/off the verbose mode [boolean] [default: false]

Examples:
  ts-for-gir copy -o ./gir                            Copy found *.gir files to
                                                      ./gir
  ts-for-gir copy -g /usr/share/gir-1.0               Copy all found *.gir files
      --ignore=Gtk-3.0 xrandr-1.3 -o ./gir            excluding Gtk-3.0 and
                                                      xrandr-1.3 to ./gir

Analyze report files

ts-for-gir analyze [options]

Analyze report files generated by ts-for-gir reporter

Options:
      --version      Show version number                               [boolean]
      --help         Show help                                         [boolean]
  -f, --reportFile   Path to the report file to analyze     [string] [required]
  -s, --severity     Filter by problem severity
                     (debug, info, warning, error, critical)             [array]
  -c, --category     Filter by problem category                         [array]
  -n, --namespace    Filter by namespace/module                         [array]
  -t, --type         Filter by specific type name                       [array]
      --search       Search for text in messages, details, or type names
                                                                        [string]
      --since        Filter problems since date/time (ISO format)       [string]
      --until        Filter problems until date/time (ISO format)       [string]
      --top          Show top N most problematic items       [number] [default: 10]
      --format       Output format (table, json, csv)
                                                    [string] [default: "table"]
  -e, --export       Export filtered results to file                    [string]
  -d, --detailed     Show detailed problem information [boolean] [default: false]
      --summary      Show summary statistics only      [boolean] [default: false]
  -v, --verbose      Enable verbose output             [boolean] [default: false]

Examples:
  ts-for-gir analyze -f ./ts-for-gir-report.json
                                            Show summary statistics of the report
  ts-for-gir analyze -f ./report.json --severity error critical
                                            Show only critical and error problems
  ts-for-gir analyze -f ./report.json --category type_resolution --format table
                                            Show type resolution problems
  ts-for-gir analyze -f ./report.json --namespace Gtk --top 10
                                            Show top 10 problems in Gtk namespace
  ts-for-gir analyze -f ./report.json --search "Unable to resolve" --export errors.json
                                            Export unresolved type errors to file

analyze reads a report file and narrows it down. A full run reports thousands of problems; this is how you get to the twelve that concern you.

Key Features:

  • Filtering. By severity, category, namespace, type name, or free text
  • Multiple Output Formats: Table, JSON, or CSV format for different use cases
  • Statistical Analysis: Show most problematic types, namespaces, and categories
  • Export Capabilities: Save filtered results for further analysis
  • Time-based Filtering: Analyze problems within specific time ranges

Config

In addition to the option of passing options as a CLI flag, you can also write them in a config file. To do that, create a new config file called .ts-for-girrc.js in your project root directory, like this:

// or on CommonJs: exports.default = {
export default {
  verbose: true,
  outdir: '@types',
  girDirectories: ['/usr/share/gir-1.0'],
  modules: ['*'],
  ignore: [],
}

The javascript config files must also be in ESM format if you are inside a ESM Package, this is the case if "type": "module" is defined in your package.json. Alternatively, the file can be saved in json format, then it works in both cases.

You can pass the config file name to the CLI using configName.

Doc-specific config

For documentation generation, you can configure doc-specific options in the config file:

export default {
  modules: ['Gtk-4.0', 'Gdk-4.0', 'Gio-2.0', 'GLib-2.0', 'GObject-2.0'],
  outdir: './docs',
  merge: true,
  jsonDir: './json',
  readme: './DOC.md',
  verbose: true,
  sourceLinkTemplate: 'https://github.com/user/repo/blob/main/{path}#L{line}',
}

Options

girDirectories

Directories in which *.gir files are to be searched for. Default is ["/usr/share/gir-1.0"]. More than one can be specified. If you want to generate the types for the GNOME Shell you have to search in several folders for the corresponding types:

girDirectories: [
  // General gir files
  '/usr/share/gir-1.0',

  // GNOME Shell gir file (package: gnome-shell-common / gnome-shell)
  '/usr/share/gnome-shell',
  '/usr/share/gnome-shell/gir-1.0',

  // GNOME Shell gir file dependencies on Fedora Workstation 37 (package: mutter)
  '/usr/lib64/mutter-11',

  //  GNOME Shell gir file dependencies on Ubuntu 22.10 (package: libmutter-11-dev)
  '/usr/lib/x86_64-linux-gnu/mutter-11',
]

outdir

The outdir option is used to specify the name of the directory where the generated TypeScript types should be saved. The default value of the outdir option is "./@types" for generate and "./docs" for doc.

Here is an example of how you can use the outdir option in the CLI of ts-for-gir:

ts-for-gir generate * --outdir ./types

In this example, the generated TypeScript types will be saved in the ./types directory.

It is important to note that the outdir option should be a valid directory path, and ts-for-gir will create the directory if it does not exist. If the specified directory already contains files, ts-for-gir will overwrite the existing files with the newly generated types.

ignore

The ignore CLI option allows you to specify modules that should be ignored when generating TypeScript types. This can be useful if you have multiple versions of a library installed but only want to generate types for one of them.

To use the ignore option, pass one or more module names as arguments. For example, to ignore the Gtk-3.0 module, you would use the following command:

ts-for-gir generate Gtk-* --ignore */Gtk-3.0

You can also ignore multiple modules:

ts-for-gir generate * --ignore */Gtk-2.0 */Gtk-3.0 */Gtk-4.0

Note that ignoring a module will prevent ts-for-gir from generating types for that module and any submodules that it might contain.

verbose

The --verbose or -v option is a flag that can be used to enable verbose output in the console when running the CLI. When this option is enabled, additional warnings and information about the processing of GIR files and the generation of TypeScript definitions will be printed to the console. This information can be useful for debugging purposes or for understanding what is happening behind the scenes when generating the TypeScript definitions.

ignoreVersionConflicts

The ignoreVersionConflicts CLI option allows you to disable the prompt to choose between multiple versions of a .gir file. When multiple versions of a .gir file are found, such as Gtk-3.0.gir and Gtk-4.0.gir, the user is normally asked to select which version to use. However, if the ignoreVersionConflicts option is set, all versions of the file will be loaded without prompt.

This option can be useful in certain scenarios where you want to generate types for all versions of a library, even if there are conflicts between the versions. Note that this may result in type conflicts and other issues, so it should be used with caution.

Another way to disable the prompt and ignore conflicting versions of .gir files is to use the ignore CLI option.

print

The print CLI option allows you to output the generated TypeScript definitions to the console, instead of saving them to files on disk. This is useful if you want to quickly inspect the generated types without having to save them to disk and open them in an editor.

By default, the print option is disabled and the generated types will be saved to disk. To enable the print option, you can pass the --print flag to the command line interface.

configName

The configName CLI option allows you to specify the name of the configuration file to be used when generating the TypeScript definitions. This option is useful if you want to use a custom configuration file instead of the default one.

By default, ts-for-gir looks for a configuration file named .ts-for-girrc.js in the current directory. If a different configuration file name is required, the configName option can be used to specify the name of the configuration file.

For example, if you have a configuration file named custom-config.js, you can use the following command to generate TypeScript definitions using this configuration file:

ts-for-gir generate * --configName custom-config.js

noNamespace

This option disables the namespaces for each module type.

  • By default the types are exported as a namespace. Namespaces should be used when the types are generated and used in ESM format.
  • If imports in imports.gi or CJS format are used, then namespaces should be disabled.

noComments

The noComments option for ts-for-gir is a CLI option used to control the generation of TSDoc comments in the generated TypeScript bindings.

When noComments is set to false, ts-for-gir will include TSDoc comments in the generated TypeScript bindings that are based on the comments found in the GObject Introspection (GIR) files. These comments provide helpful information to developers about the usage and behavior of the bindings, making it easier to work with them.

When noComments is set to true, ts-for-gir will not include TSDoc comments in the generated TypeScript bindings. This can be useful if you want to reduce the size of the generated code.

To use the noComments option, pass it as a command line argument to ts-for-gir:

ts-for-gir generate * --noComments

noPrettyPrint

The noPrettyPrint option controls whether the generated TypeScript definitions are formatted using Prettier. When set to true, the output will not be formatted, which can be useful for debugging or in cases where you want to handle formatting separately.

ts-for-gir generate * --noPrettyPrint

noAdvancedVariants

The noAdvancedVariants option disables the advanced GLib.Variant class with string parsing capabilities. This option is enabled by default (false) as these advanced features can impact performance, especially with older TypeScript versions.

ts-for-gir generate * --noAdvancedVariants=false

widgetVocabulary

Emits the GIR-derived widget vocabulary on an opt-in @girs/<ns>/vocabulary subpath, for the namespaces that declare concrete descendants of GtkWidget: Gtk-4.0, Adw-1, Gtk-3.0, GtkSource, WebKit and so on. Every other namespace emits nothing regardless of the flag, so this is not something a Gio-only project pays for. Requires --package.

What the subpath exports, all module-scoped:

import type { Widgets, GtkBoxProps, GtkOrientationNick } from '@girs/gtk-4.0/vocabulary';
import { OWN_PROPS, ENUM_NICKS, SINCE } from '@girs/gtk-4.0/vocabulary';

// One props interface per GIR DECLARATION, mirroring GIR's own inheritance:
// writable-only, optional, keyed by the name GObject registered.
declare const box: GtkBoxProps;   // { 'css-classes'?: string[]; orientation?: …; spacing?: number }

// A GType-keyed map, pointing at the `SignalSignatures` @girs already emits.
type BoxSignals = Widgets['GtkBox']['signals'];

Three things this is and X.ConstructorProps is not: writable-only (measured on Gtk-4.0, ConstructorProps offers 150 read-only properties across 68 classes as settable, and GTK's failure mode for writing one is exit 0), optional, and keyed by the registered name, the dashed spelling g_object_set(), GtkBuilder XML and Blueprint all use.

What it deliberately does not contain: tag spellings, on<Signal> handler prop names, JSX.IntrinsicElements, a Vue GlobalComponents interface, camelCase property keys. Those are framework dialect, every framework answers them differently, and a JSX namespace is a global declaration. A second library declaring one collides on every shared tag. Build your dialect on these names instead.

Beside the .d.ts, the same subpath exports the facts as runtime data (OWN_PROPS, OWN_SIGNALS, DECLS, ENUM_NICKS, SLOT_CANDIDATES, SINCE), because types are erased and the check worth having is a consumer asking the installed library whether every name is real. SINCE is what lets that check tell a version gap from a defect without an allowlist. It is keyed in GObject's own three spellings — GtkSvgWidget, GtkBox.spacing, GtkBox::clicked — so a consumer can forgive a missing TYPE as well as a missing member; without the bare key a class added after the installed library fails as TypeError: can't access property "$gtype", ctor() is undefined, which does not name the GType. Only where the GIR states a version: the attribute sits on 29 of the 301 classes and interfaces in Gtk-4.0, and none is ever inferred.

package

The --package option of ts-for-gir is used to package the generated TypeScript type definitions into an NPM package. The generated package can be easily installed and used in other TypeScript projects via npm install.

Another advantage is NPM packages is, that you can use them in a monorepo using a package manager with support for workspaces such as Yarn, PNPM and Lerna. To use the generated packages in a monorepo, you can add them as dependencies to your project's package.json file, and use relative file paths or the file: protocol to point to the local package directories. This way, you can import the generated types from within your project like any other TypeScript module.

When this option is used, each GObject introspection module will be packaged into its own NPM package. The package name will be in the format of @girs/<lower case module name>-<version>.

For example, if the --package option is used to generate the TypeScript type definitions for the Gtk-4.0 module, then the generated NPM package will have the name @girs/gtk-4.0.

You can change the NPM package scope name with the --npmScope option.

To use the generated NPM package in your TypeScript project, you can also install our pregenerated packages:

npm install @girs/gtk-4.0

Then, import the desired module in your TypeScript code:

import Gtk from '@girs/gtk-4.0';

const button = new Gtk.Button();

It is recommended to use the --package option when generating TypeScript type definitions for a GObject introspection module, as it allows for easy distribution and consumption of the generated types. However, please note that the generated NPM packages will only work with a package manager like NPM or Yarn, and cannot be used directly in a GJS or Node.js project.

Here are some examples are making use of the --package option:

npmScope

The --npmScope CLI option can be used to specify a custom NPM package scope name for the generated packages. By default, the scope name is @girs.

Here's an example command to generate NPM packages with a custom scope name:

ts-for-gir generate * --package --npmScope my-scope

This command will generate NPM packages with the scope @my-scope instead of the default @girs scope. For Gtk-4.0 this would generate a package with the name of @my-scope/gtk-4.0.

bundle

--package emits one npm package per namespace, each depending on the others by name. That is right for the published @girs/* set, and wrong whenever the types have to match one specific runtime: npm is free to satisfy @girs/glib-2.0 from the registry for one namespace and from your pinned copy for another, and two copies of a namespace are not a version skew — they are duplicate declare module 'gi://GLib' blocks, which is the "Incompatible GObject type" failure of #431.

--bundle emits the same namespaces as ONE package instead:

ts-for-gir generate '*' \
  -g /usr/share/gir-1.0 \
  -o ./sdk-gnome-50 \
  --bundle '@girs/sdk-gnome-50'

Every namespace becomes a subpath of that package, and the namespaces reference each other inside it, so the whole set installs, resolves and versions as a unit:

import "@girs/sdk-gnome-50/gtk-4.0";
import "@girs/sdk-gnome-50/adw-1";

import Gtk from "gi://Gtk?version=4.0";

The flag implies --package and sets --npmScope to the bundle name — bundle mode is a different shape of the same output, not a separate generator, so it sets the options that shape has to have rather than asking you to keep three flags consistent.

There is deliberately no barrel: importing @girs/sdk-gnome-50 on its own is not supported, because a single entry point over every namespace would pull the whole set into any program that touches one of them. To keep the classic specifiers in an existing project, map them once:

// tsconfig.json
"paths": { "@girs/*": ["./node_modules/@girs/sdk-gnome-50/*"] }

--bundleMeta merges a JSON object into the bundle's package.json, for provenance the generator cannot know — which SDK the GIR files came from, at which commit:

--bundleMeta '{"sdk":{"id":"org.gnome.Sdk","branch":"50","commit":"c87589be…"}}'

name and exports are computed from the generated output and cannot be overridden. The library versions the namespaces state about themselves are recorded automatically, under libraryVersions.

Ambient modules

In TypeScript, ambient modules are a way to define external modules that are not part of the TypeScript codebase. This can be useful for importing external libraries or modules, including those generated by ts-for-gir using the gi:// syntax.

If you want to have support for ambient modules, then you have to enable the --package option, this will generate a NPM package for each module. Alternatively, you can also use the pre-generated NPM packages for this, so you don't even need to use ts-for-gir for it. For example, look at the NPM packages gtk-4.0, gio-2.0 and adw-1. All pre-generated NPM packages can be found on gjsify/types.

The advantage of self-generated types is that you generate the types exactly for your locally installed library version. However, we try to keep the pre-generated NPM packages as up to date as possible.

To use ambient modules, the ambient.d.ts file must be imported either in the code like import '@girs/gjs/ambient' or by adding an entry to the includes property in the tsconfig file. The ambient.d.ts file is automatically generated.

// tsconfig.json
{
  "compilerOptions": {
    "lib": ["ESNext"],
    "types": [],
    "target": "ESNext",
    "module": "ESNext"
  },
  "include": ["@girs/gjs", "@girs/gjs/ambient"],
  "files": [
    "main.ts",
  ]
}

Here are some examples demonstrating the usage of ambient modules:

Without version specifier

Some ambient modules declarations are only defined with the version specifier to prevent version conflicts e.g. between Gtk-3.0 and Gtk-4.0. If you want to import the modules without the version specifier you can define the module declarations by yourself, similarly to this:

// gtk4-ambient.d.ts
declare module "gi://Gtk" {
  import Gtk from "gi://Gtk?version=4.0";
  export default Gtk;
}

reporter

The --reporter option enables the generation of a problem reporter and creates a detailed report file.

ts-for-gir generate * --reporter

reporterOutput

The --reporterOutput option specifies the output file path for the reporter. The default value is ts-for-gir-report.json.

ts-for-gir generate * --reporterOutput custom-report.json

Signal type checking

Generated connect, connect_after, and emit methods only accept signals described by GIR. This makes misspelled signal names and incompatible callback parameters TypeScript errors. This is a breaking change: the permissive string/any fallback overloads have been removed. emit takes every declared signal argument; the emitter is only added to connection callbacks.

For a GObject.registerClass subclass, extend the parent's SignalSignatures with your custom signals and declare all three methods using GObject.SignalMethods. These declarations only refine the types; they emit no JavaScript and keep the inherited GJS implementations. Keep the signatures consistent with the registered param_types; the signal interface lists arguments without the emitter:

import GObject from "gi://GObject?version=2.0";

interface CounterSignals extends GObject.Object.SignalSignatures {
  "count-changed": (count: number) => void;
}

class Counter extends GObject.Object {
  static {
    GObject.registerClass(
      {
        GTypeName: "SignalExampleCounter",
        Signals: {
          "count-changed": { param_types: [GObject.TYPE_INT] },
        },
      },
      Counter,
    );
  }

  declare connect: GObject.SignalMethods<this, CounterSignals>["connect"];
  declare connect_after: GObject.SignalMethods<this, CounterSignals>["connect_after"];
  declare emit: GObject.SignalMethods<this, CounterSignals>["emit"];
}

const counter = new Counter();
counter.connect("count-changed", (_source, count) => console.log(count.toFixed()));
counter.connect_after("count-changed", (_source, count) => console.log(count.toFixed()));
counter.emit("count-changed", 1);

For a class registered with Implements: [Gio.ListModel], also extend Gio.ListModel.SignalSignatures in its signal interface, alongside the parent signatures. This preserves type checking for interface signals such as items-changed. See the list model example and the custom signal runtime example.

notify:: details remain unchecked: the inherited [key: `notify::${string}`] index signature accepts any property name, including misspellings. The callback itself stays typed.

Truly dynamic signal names can use GObject.signal_connect, GObject.signal_connect_after, or GObject.signal_emit_by_name explicitly. These lower-level APIs do not check signal names or argument types.