Distribute npm package for non-ReScript users

Hey folks,

I’ve been looking at ReScript for a few weeks now; I’m working on a library which is currently written in plain JavaScript, but for which I regularly get requests to provide TypeScript definitions. Personally, I’d much rather write my application within ReScript’s type system than TS, but I’m wondering about the practicality of it.

Is it practical to write a library in ReScript if your end users are TypeScript/JavaScript users? How would I set up my project to write in ReScript but ship on npm as a regular JS/TS package (that is, a package that plain js users can use trivally, and TS users can use with all of the types they would expect, just as trivially)?

I don’t need my end users to be aware of the fact that the package was written in ReScript, but if there’s a way to ship all three variants (rescript, typescript, javascript) in one npm package, I’m interested in that too.

It seems I can maybe achieve this if I start with a fresh rescript project, configure GenType to output TSX files, and then define my build process as:

  1. Compile rescript → TSX files
  2. Compile TSX files → javascript + typedef files
  3. Ship

But before I get too far down this path, I figured I’d start here and see if anybody else is working in a similar structure.

Thanks!

I haven’t done anything like this, but as far as I know gentype already does everything you need - ReScript generates the JS, and gentype generates the TS at the same time.

Whether it’s used as part of a wider project or packaged for NPM shouldn’t make any difference. You can also ship all three variants and when used as a ReScript dependency the compiler will rebuild the JS if it needs to.

It depends on the surface API you want to export to your users, if it is small: you can have a look at this approach: GitHub - bobzhang/rescript-repack-demo: A demo to show how to package high quality ReScript libraries for JS users

Thanks @spyder, that’s generally my understanding too. Although, when I was playing around with genType, it seemed to produce TSX files, not javascript files + ts defs. Is there a configuration flag I’ve missed or so?

Thanks @Hongbo that’s helpful! I’m curious, why does it matter what the API surface area is? What about this becomes more difficult for larger projects?

iirc, https://github.com/mobily/stacks and https://github.com/kitten/wonka do this.

wonka is using an older version of compiler tho.

1 Like

For small surface API, you can write .d.ts of high quality by hand.
For large surface API, you may need gentype which does this automatically but may be of relatively lower quality

1 Like

See also https://github.com/OctoD/thestate

Thanks all, the examples are helpful!

@Hongbo right ok, I understand. I suppose my API is not necessarily a small surface area but the complexity of the types are rather simple. I’ll see if I can set aside a day to evaluate ReScript’s gentype abilities for my specific use cases. If they’re sufficiently high quality, I’d much rather automatically generate than not.

  1. Write a library using ReScript
  2. Add gentype and generate ts output
  3. Use shims to interop ts types with rescript’s ones
  4. Add index.ts to create js-like api for your library
  5. Use this index.ts file as an etrypoint for your ts library. I use rollup for building libraries.
  6. Publish js output. Publish ReScript library with the npm tag “rescript”. Ideally to use different npmignore configs.

Success!

2 Likes