Lots of very breaking changes are likley to occur and im sure there's many bugs to be discovered!
Bring type-safety to the interface between js and elm! Automatically generate decoders/encoders and typescript definitions from your elm types.
Elm is great! But not everything can be done in pure elm. Sometimes we need to pass over into js-land and to do that we have ports. If our Elm app happens to be very port-heavy for whatever reason, we might find ourselved spending increasing amounts of time writing json decoders/encoders, syncing that with the js-side and debugging whenever a typo or something small like that slipps through. Elm and typescript helps us write code with fewer errors, lets bring them to the interface between Elm and js!
npm install --save-dev elm-port-schema
NOTE: We will use typescript instead of javascript. Typescript is essentially javascript with types, which is exacly what we need.
Everything revolves around a schema located at src/Schema.elm
and the two types that needs to be in it: FromElmMessage
and ToElmMessage
.
if your schema looks like this:
module Schema exposing (..)
type FromElmMessage = ...
type ToElmMessage = ...
and you run elm-port-schema
it will generate two files.
src/Port.elm
. You can import this module from the rest of your Elm to send and recive messages. It looks a bit like this:
port module Port exposing (..)
type FromElmMessage = ...
type ToElmMessage = ...
send : FromElmMessage -> Cmd msg
send = ...
recive : (Result Json.Decode.Error ToElmMessage -> msg) -> Sub msg
recive = ...
...
src/Main.d.ts
. This file makes typescript aware of what data can be sent to and from Elm.
It look a little like this:
export let Elm: { Main: { init: (flags?: any) => ElmApp } }
export interface ElmApp {
ports: {
toElm: { send: (msg: ToElmMessage) => void },
fromElm: { subscribe: (f: (msg: FromElmMessage) => void) => void },
}
}
...
Whenever you want to change how data is passed between elm and typescript,
just update Schema.elm
, run elm-port-schema
and fix all compiler errors
in your elm and typescript. Piece of cake!
Bool
<=>bool
Int
,Float
<=>number
Char
,String
<=>string
List
<=>Array
( Int, String )
<=>[ number, string ]
{ foo : Int, bar : String }
<=>{ foo: number, bar: string }
type Foo = Bar Int String
<=>{ variant: "bar", _0: number, _1: string }
Maybe
and Result
values map to typescript just the same as any other
custom type would,
i.e Nothing
maps to { variant: "Nothing" }
, not null
!
https://github.com/hugobastas/elm-port-schema-starter has the boilerplate needed
to get up and runing with elm-port-schema
.
Before using this tool, know that it WILL add complexity to your project. compared to plain js and Elm you will need typescript, a bundler like webpack with a typescript and Elm loader. If you're only goin to spend a couple hours interfacing js and Elm this additional complexity might not be worth it. This comic commes to mind.
Also note that elm-port-schema
is NOT intended for data interchange
between client and server. Thats a different problem and something like
elm-graphql would be more appropriate
to solve it.
Also read this vission for data interchange in elm. I found it to be very enlightening!
MIT