not really known
Go to file
2024-04-11 06:39:04 -05:00
.github add dependabot configuration 2024-04-09 17:21:52 -05:00
examples capture the main module 2024-04-10 05:56:39 -05:00
src add namespaces, classes, and methods 2024-04-11 06:39:04 -05:00
tests this doesn't need quoting 2024-04-11 06:09:34 -05:00
.envrc nixify 2024-04-04 05:17:07 -05:00
.gitignore start Rust project 2024-04-04 05:22:07 -05:00
Cargo.lock add trycmd for snapshot testing 2024-04-09 06:30:40 -05:00
Cargo.toml add about 2024-04-09 16:59:57 -05:00
flake.lock nixify 2024-04-04 05:17:07 -05:00
flake.nix add formatters 2024-04-10 06:20:39 -05:00
ideal.d.ts add namespaces, classes, and methods 2024-04-11 06:39:04 -05:00
README.md this doesn't need quoting 2024-04-11 06:09:34 -05:00

elm-duet

Elm is great, and TypeScript is great, but the flags and ports between them are hard to use safely. They're the only part of the a system between those two languages that aren't typed by default.

You can get around this in various ways, of course:

  • Manually maintain a .d.ts for your Elm app: works, but now you have two sources of truth and have to keep them in sync by hand. That falls apart quickly as the app grows or new people join the team.
  • Generate a .d.ts from Elm types. Beats doing it by hand, but it constrains you to simple types unless you want to write an interpreter for both your type aliases and inevitable custom types that need decoders from Json.Decode.Value.
  • Generate Elm types from your TypeScript types. Again, needs a lot of work to intepret the types correctly and translate them.

elm-duet works around this by creating a single source of truth to generate both .d.ts files and Elm types+decoders. We use JSON Type Definitions (JTD, five-minute tutorial) to say precisely what we want and generate ergonomic types on both sides (plus helpers like encoders to make testing easy!)

Here's an example for an app that stores a jwt in localStorage or similar to present to Elm:

{
  "mainModule": "Main",
  "flags": {
    "properties": {
      "currentJwt": {
        "type": "string",
        "nullable": true
      }
    }
  },
  "ports": {
    "newJwt": {
      "metadata": {
        "direction": "elmToJs"
      },
      "type": "string"
    },
    "logout": {
      "metadata": {
        "direction": "elmToJs"
      }
    }
  }
}

You can generate code from this like so:

$ elm-duet examples/jwt_schema.json
// Warning: this file is automatically generated. Don't edit by hand!

type Flags = {
  currentJwt: string;
}

(config: {
  flags: Flags;
  node: HTMLElement;
}): void

Here are more things you can do with the tool:

$ elm-duet --help
Generate Elm and TypeScript types from a single shared definition.

Usage: elm-duet <SOURCE>

Arguments:
  <SOURCE>  Location of the definition file

Options:
  -h, --help     Print help
  -V, --version  Print version