Hello,

I've been following in the steps of some others [1] [2] who have attempted
to produce Typescript definitions for Gtk and Gjs. I believe I have
something more complete than any other effort I've found, so I thought it
was time to share my work, and a couple of questions.

Starting with gir2dts [2], I tried to write a basic application... And
failed. Due to various limitations (no constructors, interfaces, etc.) So I
went about at fixing any limitation I found and have ended up with a fairly
thorough description in Typescript of the GI interfaces presented by Gjs.

Examples of some features I'm particularly happy with:

   - Signals, via the connect() function, are checked using Typescript's
   string literal type checking [3]
   - The above includes the "notify::attribute" syntax
   - All possible parameters for a class are described in an interface, and
   this is used in the default Gjs constructor. This allows editors like
   Visual Studio Code to provide code completion and type checking for the
   arguments to this object
   - Classes are decomposed into static and instance sides. The static side
   is used to describe the Gjs constructor, and then extended with the other
   GI constructor functions
   - Ability to include the documentation, such that it will be shown in
   code completion popups
   - Multiple return values described correctly


All of this is possible due to the excellent work of the original project,
gir2dts, that I have simply forked and added extra support to.

This project is available at: https://github.com/sammydre/gir2dts

I'm still not sure it's all that useful generally just yet -- largely due
to me not knowing how such code should be distributed, or work with module
systems. Any comments on how to structure this would be appreciated.

On to my questions:

   - In some cases functions and properties end up with the same name in
   Javascript. Take the "is_active" [4] function and "is-active" [5] property,
   for example. How does Gjs decide how to resolve ".is_active"? My research
   suggests it favours the property, with no ability to call the function on
   the object. Is this correct?
   - Similarly, if a class has a method called "connect()", is it
   impossible to call, due to the signal-connection function being the only
   one available? This is the case in e.g. Gio.Socket.
   - I tried to use "GLib.idle_add(func, data)" -- the GObject
   introspection suggests this is the correct signature. Unfortunately it
   appears it needs a priority argument first, but I don't understand why this
   is. Could you explain what I'm missing to correctly generate the typing for
   this function?
   - I've sometimes found that derived functions have different signatures,
   with Typescript does not like. An example of this is the "activate" symbol
   used in Gtk; consider "Widget.activate()" vs. "Button.activate(button:
   Button)" -- Button derives from Widget, but has a different signature for
   this method. What does Gjs do about this? "let a = new Gtk.Button({});
   a.activate()"


Finally, a few examples of this at work:

The start of the Gtk.Button interface:

    export interface Button extends Bin {
        clicked():void
        enter():void
        get_alignment():[/*xalign:*/ number, /*yalign:*/ number]

Signals are described explicitly, both property change and otherwise:

        connect(sigName: "notify::xalign", callback: ((obj_: Button, pspec:
GObject.ParamSpec) => void))
        connect(sigName: "notify::yalign", callback: ((obj_: Button, pspec:
GObject.ParamSpec) => void))
        connect(sigName: "activate", callback: ((button_: Button) =>
void)): void
        connect(sigName: "clicked", callback: ((button_: Button) => void)):
void

Parameters possible on construction:

    interface Button_Parameters extends Bin_Parameters {
        always_show_image?: boolean;
        focus_on_click?: boolean;
        image?: Widget;
        image_position?: PositionType;
        label?: string;
        relief?: ReliefStyle;
        use_stock?: boolean;
        use_underline?: boolean;
        xalign?: number;
        yalign?: number;
    }

The constructors use interface merging to allow both a constructor function
and a function called new:

    export interface Button_Constructor {
        new (config: Button_Parameters): Button
    }
    export declare class Button_Constructor {
        new(): Button
        new_from_icon_name(icon_name: string, size: number): Button
        new_from_stock(stock_id: string): Button
        new_with_label(label: string): Button
        new_with_mnemonic(label: string): Button
    }
    export declare var Button: Button_Constructor

Cheers,
Sam

[1]: https://github.com/niagr/GIR2TS / https://github.com/niagr/gjs-ts
[2]: https://www.npmjs.com/package/gir2dts
[3]: https://www.typescriptlang.org/docs/handbook/advanced-types.html
[4]:
https://people.gnome.org/~gcampagna/docs/Gtk-3.0/Gtk.Window.is_active.html
[5]:
https://people.gnome.org/~gcampagna/docs/Gtk-3.0/Gtk.Window-is-active.html
_______________________________________________
javascript-list mailing list
javascript-list@gnome.org
https://mail.gnome.org/mailman/listinfo/javascript-list

Reply via email to