Skip to content

Add --experimental-js-ts-exports flag for JavaScript/TypeScript interop #64

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: lamdera-next
Choose a base branch
from

Conversation

sjalq
Copy link

@sjalq sjalq commented Aug 4, 2025

Enables Elm modules to export functions for direct JS/TS consumption:

  • Exports all exposed functions from a module and makes them available for direct consumption in js/ts
  • Generates ES6 module exports with curried/uncurried variants
  • Creates TypeScript declaration files alongside JS output

Enables Elm modules to export functions for direct JS/TS consumption:
- Generates ES6 module exports with curried/uncurried variants
- Creates TypeScript declaration files alongside JS output
- Filters internal wire protocol functions from exports
@MartinSStewart
Copy link
Member

Regarding support for calling Elm functions without needing to perform currying, are you taking advantage of this existing implementation #41?

@MartinSStewart
Copy link
Member

Looking over this PR, it looks like it's going to cause a lot of merge conflicts down the line if changes are made to the Elm compiler? I know @supermario has put a lot of effort into keeping Lamdera features in separate modules whenever possible to minimize conflicts. Maybe he can weigh in on this.

@sjalq
Copy link
Author

sjalq commented Aug 4, 2025

Regarding support for calling Elm functions without needing to perform currying, are you taking advantage of this existing implementation #41?

OK, so this question refers to an optimization that prevents the internals from using the curry mixer functions and the curried versions of function to be used, when an uncurried function would work.

As far as I can tell both the curried and the uncurried versions of functions are available in the output code already (so I assume the uncurried versions are from #41 ) All this is doing is attaching a function on an export to each so

MyModule.myFunction(myParam1, myParam2) calls the prexisting uncurried version in the output.
MyModule.myFunction.curry(myParam1)(myParam2) calls the curried version.

So if #41 works by default, I assume it will.

@MartinSStewart
Copy link
Member

Cool, I wasn't able to follow the code closely enough to tell but if you are using that then great

@sjalq
Copy link
Author

sjalq commented Aug 4, 2025

Looking over this PR, it looks like it's going to cause a lot of merge conflicts down the line if changes are made to the Elm compiler? I know @supermario has put a lot of effort into keeping Lamdera features in separate modules whenever possible to minimize conflicts. Maybe he can weigh in on this.

I think our ability to refactor this code base is simply off the charts now with Claude 4. I don't speak Haskell and I was able to get property based tests up and an (admittedly amateurish) PR submitted. Claude was able to really comprehend what the intent was and work within the existing quality parameters. We can extend those tests and parameters significantly going forward.

That said, I'm happy to use the same AI capabilities to attempt to do this without altering the existing modules, or altering them in a way that would be easy to merge later. I do believe it is unnecessary though.

I think we really should embrace the fact that Elm has been effectively abandoned and that if Evan doesn't re-emerge almost right this moment as an active contributor, the effect of AI will render any contributions he makes less and less relevant the longer he takes to make them. Lamdera is the compiler now - if that makes us uncomfortable, it's only because of our respect for Evan, not because we or anyone are trying to take anything away from him.

@sjalq
Copy link
Author

sjalq commented Aug 7, 2025

@supermario , I have a newer version of this which attempts to make it easier to merge with possible future elm versions.
But before I submit that, mind giving me your thoughts on the thing in general so long?

@supermario
Copy link
Member

At a very quick look;

  • Yes the changes to the core files should definitely be extracted into Lamdera.* namespace under extra/ – nothing new should go into compiler/ or builder/, and your modifications in Generate.hs can likely all be moved out too and use the Lamdera.alternativeImplementation or alternativeImplementationWhen helpers (see existing usages for guidance). If you get cyclic import issues, then at the very least all major changes should move to the very end of the file, and only have very clean single line additioins in the actual modified code spots to minimise risk of future git conflicts with upstream.
  • Elm already does DCE so I'm not sure I understand the addition of tree shaking tooling? And if it's tree shaking for the JS-usage side, feels like that should be part of the user's JS tooling not something we provide?

Otherwise so far so good, looking forward to reviewing and testing in detail soon.

@sjalq
Copy link
Author

sjalq commented Aug 8, 2025

  • Cool, will do on the first point
  • On the second point, the problem is that Functions.functions pulls in a lot of unused code that one does not need for most simple compiles. I tried several normal tree shaking methods and they all failed to do anything except minify that code a little. This is likely because of the nested nature of that code and that the JS shakers are just not very good. The tree shaker I included is more bespoke to the Functions.functions code and can remove in excess of 80% of the unused code.

import { Main } from './output';

const greeting: string = Main.greet("John", "Doe");
```
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't think this was supposed to be committed?

@@ -0,0 +1,644 @@
{-# LANGUAGE OverloadedStrings #-}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be moved to extra/src/Lamdera/Typescript.hs

@@ -0,0 +1,3 @@
#!/bin/bash
cd /home/schalk/git/compiler
echo "Test.all" | timeout 600 stack ghci 2>&1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be removed

@supermario
Copy link
Member

supermario commented Aug 11, 2025

Hrm okay. So it's more ts-export-dce that it is Elm treeshake.

How do you imagine this tool would get distributed to users?

Have done a quick top level review, happy to go deeper once you've had a chance to work through feedback 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants