How to use Elm in tsx file?

How do I embed Elm component in React + Typescript files?

Typescript language service can’t find elm module I wrote.

I use create-react-app in this process. I use react-app-rewired to add ‘.elm’ to webpack module resolvers and elm-webpack-loader to compile elm code.
As I understand my build process, that’s not enough as TS runs tsx files expecting to only import ts or js modules.

My code structure:
//folderA/SomeComponent.tsx

import { A } from ‘./A’
//folderA/A.elm
module Main exposing…

I don’t know anything about React or Typescript, but I presume you first need to compile A.elm into A.js with something like elm make A.elm --output A.js --optimize. Then pass A.js into create-react-app.

Create a file called elm.d.ts with the following content:

declare module "*.elm" {
  export const Elm: any;
}

That should do the trick.

You can type it nicer than any if you want.

7 Likes

Thank you for the "*.elm" trick. I had to do some extra debugging to understand what should I pass to react-elm-compoment from "*.elm" module but it all works! :slight_smile:

Here is my current setup (with more details):
Please not that I took elm code from elm-lang guide. It’s very first example, updated to full Browser.element implementation (with Cmd.none and Sub.none and () for the flags type).

//A//B//ComponentAB.tsx
...
import Elm from 'react-elm-components';
import Main from './Main.elm';
...
return (
  <>
  <h3>I'm here</h3>
  <Elm src={Main.Elm.A.B.Main} /> <!-- Main from import statement (dot) Elm from .d.ts? (dot) folder name (dot) another folder name (dot) name of module inside Main.elm -->
  </>
)

//A//B//Main.elm
module A.B.Main Main exposing (Msg(..), main, init, subscriptions, update, view)
...
// Copied here very first example from official guide
// This is Browser.sandbox with 2 buttons and a counter copied over verbatim

//elm.d.ts
declare module "*.elm" {
  export const Elm: any;
}

//react-elm-component.d.ts
declare module 'react-elm-components' {
  import { Component } from "react";
  type ElmProps = {
    src: any  
  };
  class Elm extends Component<ElmProps> {};
  export = Elm;
}
2 Likes

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.