Make TypeScript FFI Typechecking easier #4561
Replies: 1 comment 3 replies
-
As a huge user of Gleam + JavaScript + TypeScript in production in both frontend and backend (on Node), I have probably some food for thoughts for you. 🙂
Unfortunately, that's not universally right. JavaScript as a target is used by runtimes but also (and especially in Gleam with Lustre) in browsers. And as of today, browsers do not support TypeScript out-of-the-box. You could argue everyone will use a bundler, like ESBuild, Vite or Rollup, but not everyone want to go that process. Also, a lot of people are targetting specific environments, like Node 20 or 22, CloudFlare workers, etc. While TypeScript is not in the ECMA specification, I think it's bad to output TypeScript just like this. In my opinion, Gleam should as much as possible stick with JS standards, and not try to force any tool on top of the developer stack. Everyone use the tool they like, and sticking with standard is the good thing to do to let people bring their tooling. Some will like That being said, Gleam adds the TS superset over JS, by emitting The only part that won't really be type-checked is the FFI, but why not writing your own
Gleam works well in the browser and JS runtimes, but I can say interoperability between JS and Gleam can be hard sometimes, because API are not built the same way in Gleam and in JS. Builder patterns in Gleam are nice, while they are a bit clumsy in pure JS. Builders in JS are built around objects (because there's no pipe), and it makes a huge difference between the two. What we do at Steerlab, is applying some simple patterns: we use pure JS in FFI in Gleam, and we don't have functions in the FFI that are longer than 10 lines. We also manipulate only simple data structure, and we try to avoid at most to open/use the data structure in the FFI. The FFI should stay minimal, and all the logic is written in Gleam. When we need something really specific in JS/TS, we write a proper JS/TS package instead of bending the language (from experience, when what you need is 90% in JS, write it directly in JS instead of going in the FFI too much, that's a huge gain of time). To give some numbers: we had 0 bugs due to FFI in production, because the FFI code is probably like 1% of the codebase at most. Every bugs are coming from something else (business logic most of the time,
I'm not sure I get you here. What you want to do is generate your Gleam code FFI directly from your TS code? That sounds good, but isn't it a bit using a flamethrower to kill a fly? I mean, that's a few lines of code to write as FFI, and that would let you design the FFI as you like. However if you have a lot of code, I understand why you would do this. 🙂 In that case, I would advise to write your TS files as Maybe a solution could be for you to run |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Hello!
I've recently experimented with getting
tsc
to work in a compiled gleam project withtarget = javascript
andtypescript_declarations = true
, given that with runtimes like bun, deno and recently even node (https://nodejs.org/en/learn/typescript/run-natively) you can run*.ts
files natively without having to compile them tojs
.Since I mostly work in typescript codebases, where everything is typed, the thought of having to write FFI bindings that are not type checked is a bit unsettling. Although I would love to replace typescript packages inside of my codebases with gleam packages.
My first idea was to write a generator for gleam that would automatically be able to map typescript types to gleam, so I could always make sure my FFI bindings are in sync with my typescript code. For example:
I could automatically generate this:
I actually have a very small prototype with https://ts-morph.com/ that already works for scalar types, but would need further work and testing for more complex types. So this idea is still something I am considering.
I also had the following idea: maybe we can just run tsc inside of the build/dev/javascript directory, since it should be able to catch a mismatch between the types inside of the .ts file and the function call inside of gleam. However this has not worked out in practice for me. There were some issues I ran into when working on this:
typescript_declarations
which basically overrides the types from the .ts file, so the typescript compiler is blindsightedAnother idea I had was to use JSDoc (https://jsdoc.app/) since I then would not have to generate typescript declarations. However I was unable to get it working as of today.
A couple of talking points I am aware of and are fair to discuss:
tsc
work?But maybe there are modifications to how gleam produces javascript and typescript declarations that would make typechecking easier while keeping the changes on gleam's end minimal.
Perhaps right now there are ways to get it working, that I am just not aware of and this is just a skill issue.
Happy to discuss further,
Cheers!
Beta Was this translation helpful? Give feedback.
All reactions