Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to mix TypeScript & ClojureScript

I am currently using TypeScript 2.0 with React and webpack on one of my project. I am considering trying out ClojureScript but I would like to start small maybe build single screen with it first.

Is it possible to mix the two together in a single project?

Ideally I would like to use component built in Clojure to be used via ES6 imports.

Main reason for that is to introduce the team/myslef to clojure but we already have a bit of codebase in TypeScript. I understand it is easy to generate totally separate bundle and reference it but that's not ideal.

like image 439
bartosz.lipinski Avatar asked Nov 17 '16 22:11

bartosz.lipinski


2 Answers

Yes.

The output of ClojureScript is JavaScript which can define React components and arbitrary code. For example if you use Reagent 0.6.0, the output of create-class can be used directly as a component.

But! Mixed mode project build configuration is challenging. One approach is to make the ClojureScript page a library that is required by your host project, in which case you can build and test your ClojureScript component independently, then package up the output file as a dependency for your main project. This has the advantage of being able to quickly iterate on developing the component (using figwheel/devcards).

like image 59
Timothy Pratley Avatar answered Nov 22 '22 23:11

Timothy Pratley


In principle, yes, you can do this. Like the other answers I don't think it's a great idea most of the time, but I can certainly believe there's cases where it might be.

Assuming you're using a compatible module system between the two (e.g. both are compiling to ES6 modules as you suggest), then you can write some ClojureScript, compile it to my-cjs.js, add a my-cjs.d.ts file to your TypeScript containing declare module "my-cjs";, import it in TS as import { export1, export2 } from "my-cjs", and start using it.

To go further you'll probably want to build and maintain your own type definitions, rather than using this ambient shorthand module setup (which is easiest to start with, but will any type all your ClojureScript). As far as I know there's no useful way to automatically generate compatible type definitions from ClojureScript, so you'll have to keep that up to date by hand, which may or may not be more effort than it's worth for your case, depending on how much the API for your script is going to change.

The trickier part is probably going to be combining the output of your two separate compilations, so that both load correctly with ES6 modules. You'll want to output your TypeScript JS files into one folder, output your ClojureScript JS into another folder, and then combine those folders in some way to make the paths line up nicely (you could compile them into the same folder directly, but I'd start with combining to start with, to keep things simpler). That depends on how you set up your compilation steps, but it's certainly doable.

I'd aim to compile both to a file structure that's something like:

/cjs-output
 |- /my-component
    |- my-cjs-script.js
/ts-output
 |- my-ts-code.js
 |- some-more-ts-code.js

and to then combine these as a second step to:

/output
 |- /my-component
    |- my-cjs-script.js
 |- my-ts-code.js
 |- some-more-ts-code.js

As far as I can tell webpack doesn't have a ClojureScript loader available, so you'll have to do that compilation step by hand either way. How exactly you want to hook this into Webpack is an open question - I'd normally start by getting the TS + CJS to JS step working outside webpack, and then use webpack to handle the process from the JS onwards, before maybe integrating more later, but YMMV.

From there my-ts-code.js should be able to import my-component/my-cjs-script at runtime just fine, and as long as you've got a type definition in place for my-component/my-cjs-script then tsc should happily compile that for you.

like image 27
Tim Perry Avatar answered Nov 23 '22 01:11

Tim Perry