Re: A Typescript experiment




On Fri, Jul 7, 2017 at 12:07 AM Sam Jansen <sam jansen starleaf com> wrote:
On 13 June 2017 at 05:48, <philip chimento gmail com> wrote:
On Mon, Jun 12, 2017 at 2:36 PM Sam Jansen <sam jansen starleaf com> wrote:
On 11 June 2017 at 00:04, <philip chimento gmail com> wrote:
On Fri, Jun 9, 2017 at 2:29 PM Sam Jansen <sam jansen starleaf com> wrote:
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

This is *fantastic*.
 

Thanks :)
 
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.

I admit I don't know much about Typescript. If I understand correctly, this would be a plugin for the Typescript compiler, so it should be distributed in whatever way is usual there.
 

It seems the way most people are using it now is via "@typings", which is supported by npm.

I think the best thing for me to do is document what I have at the moment / write a good example and point to it here to solicit further discussion. So I'll come back to this at some point in the future, all going well.

Yes, an example and/or "getting started" document would be quite useful!


Well, this led me down quite the rabbit-hole...

The end result is that I've completely rewritten the tool, this time in Typescript, and with *much* fewer hacks, and I believe overall a more correct approach. The tool is now at:


This includes sample output, e.g.:


And a couple of sample programs:


The example programs are fairly boring -- they are pretty much just JS. The magic comes in the type-checking, autocompletion, etc. which isn't really easy to see without using it! If anyone wants to play; check out the github project then open the directory in visual studio code, "npm install", and it should all "just work".

Nice! I finally found some time to check it out. May I suggest putting those very instructions in the README? :-)

By the way, I'm giving a talk about "modern" GJS at GUADEC on Sunday, and if you don't mind, I'd like to include a slide about this, with a screenshot of it working in VSCode. I think it deserves a bit of publicity.

You'll also see here how I've implemented modules: just with relative path imports in typescript. Typescript then compiles this to "require" statements, which I bundle together with webpack right now; but this isn't strictly required.

[...]
 
I eventually came to the conclusion that there is fundamentally a mismatch here between the "inheritance" one can describe in Typescript, and that used today in the GI bindings to especially GTK. There are a number of cases where the derived method/property doesn't match exactly. Rather than try and enumerate these all by hand and hack around them, I decided it's best not to use Typescript's inheritance, and just describe the complete set of methods and properties, resolving them all from the inheritance tree I look up in the GI info. Hence you'll see the Gtk.d.ts file is rather large (i.e. 6MB!)

I'm not sure how Typescript inheritance works and what's different from GObject inheritance, but I think that approach sounds good.

Finally, a problem I created for myself with types was wanting a vaguely safe way to down/up-cast. So I invented the rather hacky "giCast" function as defined here:


I have a question: is there a better way to figure out what actual class an instance is at run-time? You can see here what I do is call toString() on it, then parse out the resulting string that has a "GIName:" in it. This works, but feels rather brittle...

You should be able to get the class object with instance.constructor, and the GType object with instance.constructor.$gtype. The GType object has a "name" property.

As things stand, this works well for me, and I'll continue to fix up bugs and limitations in the declarations as I find them (or they're reported to me).

One thing I noticed fairly quickly is that it would be nice to make the properties object optional for constructors: e.g. new GtkSource.View() instead of new GtkSource.View({}).

Best,
Philip C


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]