Skip to content

Gio.Settings: Type inference fails for detailed changed::* signals with arbitrary schema keys #297

@LumenGNU

Description

@LumenGNU

Description

The changed signal in Gio.Settings is a detailed signal (GObject terminology) that notifies about changes to schema keys accessed via get_*(key) methods.

According to GLib documentation:

This signal supports detailed connections. You can connect to the detailed signal changed::x in order to only receive callbacks when key x changes.

The signal handler always has the same signature regardless of the key name:

(gsettings: Gio.Settings, key: string) => void

Current Expected

The current Settings.SignalSignatures typing includes only predefined detailed signals that match GSettings object properties (not schema keys):

interface SignalSignatures {
    changed: (arg0: string) => void;
    'changed::backend': (arg0: string) => void;
    'changed::delay-apply': (arg0: string) => void;
    'changed::path': (arg0: string) => void;
    'changed::schema-id': (arg0: string) => void;
    // ...
}

Why it's confusing:

  • backend, delay-apply, path, schema-id are GSettings object properties, not typical schema keys
  • It creates false impression that only these specific keys are supported for detailed signals
  • It suggests these property names are expected to be used as schema keys (which would be confusing in practice)
  • The pattern implies a closed set, while changed::* works with any schema key

Problem:

When connecting to changed::${arbitrary_schema_key}, TypeScript cannot infer callback parameter types:

// Type inference fails - parameters have type 'any'
gsettings.connect('changed::my-key', (settings, key) => {
    // settings: any
    // key: any
});

// Must annotate types manually
gsettings.connect('changed::my-key', (settings: Gio.Settings, key: string) => {
    // settings: Gio.Settings
    // key: string
});

Expected Behavior

Type inference should work for any changed::* detailed signal, since:

  • All detailed signals have the same handler signature
  • The pattern changed::${key} is the standard way to use GSettings API
  • Actual schema keys (e.g., criteria, gtk-cursor-blink, custom keys) are far more common than keys named after GSettings properties

Proposed Solution

If TypeScript supports template literal types in this context:

interface SignalSignatures {
    changed: (arg0: string) => void;
    [key: `changed::${string}`]: (arg0: string) => void;
}

Or at minimum, document the current limitation and remove the misleading predefined changed::backend, etc. variants.

References

Gio C API reference: https://docs.gtk.org/gio/signal.Settings.changed.html

Environment:

  • GJS Version: 1.80.2 (GNOME 46)
  • Girs packages: @girs/gio-2.0@2.86.0-4.0.0-beta.38
  • TypeScript: 5.8.3

Additional Context

  • This affects all GSettings usage where developers connect to specific schema keys
  • Current workaround: manual type annotations for every callback

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions