• Stars
    star
    42
  • Rank 656,625 (Top 13 %)
  • Language
    Elm
  • License
    BSD 3-Clause "New...
  • Created about 4 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

elm-ts-json Build Status

Build up Encoders/Decoders with well-defined TypeScript types! The API in this package is the foundation of the elm-ts-interop CLI tool, but can be used for other purposes as well.

Core concepts

Figure out the types for your ports (to and from Elm)

How does elm-ts-interop figure out the types of your ports? There's no magic involved at all. You define a special type of Encoder/Decoder using the TsJson.Encoder and TsJson.Decoder modules.

These Decoders and Encoders that you write are the source of truth. It doesn't rely on implicitly generated Decoders or Encoders (Evan generally recommends against implicitly defined serialization because of limitations to that approach that he describes in his vision for data interchange). Instead, you define code with an API that is very similar to elm/json. But this API knows the type information of the Encoder or Decoder you've built.

For example, if you use TsDecode.string, it knows that will expect to receive a string from TypeScript. TsDecode.list TsDecode.string will expect to receive string[] from TypeScript. You can even build up more expressive TypeScript types like Unions:

import TsJson.Decode as TsDecode
import TsJson.Type

TsDecode.oneOf
    [ TsDecode.string
    , TsDecode.int |> TsDecode.map String.fromInt
    ]
    |> TsDecode.tsType
    |> TsJson.Type.toTypeScript
    --> "string | number"

So we've written a Decoder very similar to how we would with elm/json, but this Decoder has one key difference. We can turn the Decoder itself into a TypeScript type (string | number). And without even passing a value through the Decoder From this simple idea, you can build very sophisticated typed interop, even sending/receiving Elm Custom Types, and sending/receiving TypeScript discriminated unions.

Example

import Json.Encode as JE
import TsJson.Encode as Encode exposing (Encoder)
import TsJson.Decode as Decode exposing (Decoder)

type User
    = Regular { name : String }
    | Guest

userEncoder : Encoder User
userEncoder =
    Encode.union
        (\vRegular vGuest value ->
            case value of
                Regular data ->
                    vRegular data
                Guest ->
                    vGuest
        )
        |> Encode.variant
            (Encode.object
                [ Encode.required "kind" identity (Encode.literal <| JE.string "regular")
                , Encode.required "name" .name Encode.string
                ]
            )
        |> Encode.variantLiteral (JE.object [ ( "kind", JE.string "guest" ) ])
        |> Encode.buildUnion


userDecoder : Decoder User
userDecoder =
    Decode.oneOf
        [ Decode.succeed (\() name -> Regular { name = name })
            |> Decode.andMap (Decode.field "kind" (Decode.literal () (JE.string "regular")))
            |> Decode.andMap (Decode.field "name" Decode.string)
        , Decode.literal Guest (JE.object [ ( "kind", JE.string "guest" ) ])
        ]

type alias Name =
    { first : String, last : String }


nameEncoder : Encoder Name
nameEncoder =
    Encode.object
        [ Encode.required "first" .first Encode.string
        , Encode.required "last" .last Encode.string
        ]


nameDecoder : Decoder Name
nameDecoder =
    Decode.succeed Name
        |> Decode.andMap (Decode.field "first" Decode.string)
        |> Decode.andMap (Decode.field "last" Decode.string)

Guest
    |> Encode.runExample userEncoder
--> { output = """{"kind":"guest"}"""
--> , tsType = """{"kind":"guest"} | { kind : "regular"; name : string }"""
--> }

userDecoder |> Decode.runExample """{"kind":"guest"}"""
--> { decoded = Ok Guest
--> , tsType = """{ kind : "regular"; name : string } | {"kind":"guest"}"""
--> }

More Repositories

1

elm-graphql

Autogenerate type-safe GraphQL queries in Elm.
Elm
778
star
2

elm-pages

Hybrid Elm framework with full-stack and static routes.
Elm
655
star
3

mobster

Pair and mob programming timer for Mac, Windows, and Linux.
Elm
308
star
4

elm-typescript-interop

Generate TypeScript declaration files for your elm ports!
Elm
165
star
5

elm-markdown

Extensible markdown parser with custom rendering, in pure Elm.
Elm
106
star
6

elm-review-html-to-elm

Turn HTML into Elm. With support for elm-tailwind-modules.
Elm
96
star
7

elm-pages-starter

Starter blog for elm-pages
Elm
95
star
8

idiomatic-elm-package-guide

Everything you need to know to publish a useful, idiomatic Elm package!
67
star
9

elm-cli-options-parser

Build type-safe command-line utilities in Elm!
Elm
54
star
10

elm-typescript-starter

Boilerplate for Elm web apps with safe TypeScript interop and hot module replacement.
JavaScript
35
star
11

elm-electron-starter

Build native cross-platform desktop apps in Elm
TypeScript
35
star
12

talks

Elm
23
star
13

elm-pages-v3-beta

Elm
22
star
14

elm-electron

Type-safe interprocess communication for Electron apps built with Elm.
Elm
19
star
15

elm-publish-action

TypeScript
19
star
16

elm-form

Standalone version of the elm-pages Form API.
Elm
19
star
17

elm-package-starter

Starter template for an Elm package.
Elm
13
star
18

graphqelm-demo

Demo package to support Ellie examples of Graphqelm.
Elixir
11
star
19

elm-pages-3-alpha-starter

Elm
9
star
20

elm-decoder-koans

Learn about elm decoders by filling in the blanks in test cases.
Elm
8
star
21

elm-radio.com

Elm
7
star
22

elm-pages-tailwind-starter

Elm
7
star
23

elm-ts-interop-starter

Elm
7
star
24

elm-rss

Generate RSS feeds with Elm.
Elm
7
star
25

elm-pages-realworld

Realworld implementation with elm-pages v3.
Elm
6
star
26

elm-ical

Elm
5
star
27

gitbook-elm-graphql

5
star
28

incrementalelm.com

Elm
4
star
29

elm-katas

Placeholder for elm exercises
Elm
4
star
30

graphqelm

This package has been moved to dillonkearns/elm-graphql
Elm
4
star
31

sb-farmar

Elm
4
star
32

atom-vim-mode-plus-exchange

Exchange two text areas in vim-mode-plus
JavaScript
4
star
33

automated-testing-wiki

Automated Testing Wiki - A Community Guide to Effective TDD
3
star
34

legit

A collection of scripts for common git tasks to simplify and improve workflow.
Ruby
3
star
35

elm-view-transitions

A proof of concept of the View Transitions API in Elm.
Elm
3
star
36

elm-snapshot-test

JavaScript
3
star
37

prisma-example

Elm
3
star
38

elm-program-test-katas

Elm
2
star
39

fishbowl

Elm
2
star
40

ellie-app-cli

JavaScript
2
star
41

elm-pages-init

Elm
2
star
42

elm-form-mdl

elm-mdl helpers for the elm-forms library
Elm
2
star
43

Test-Runner

Python
2
star
44

the_lean_cafe

Elixir
2
star
45

chess-vision

Elm
1
star
46

elm-koan-runner

Elm
1
star
47

elm-pages-blog-tutorial

Elm
1
star
48

elm-oembed

Elm
1
star
49

elm-ts-netlify-starter

JavaScript
1
star
50

advent-posts

1
star
51

elm-sitemap

Generate sitemaps in elm.
Elm
1
star
52

elm-program-test-experiment

Elm
1
star
53

dotfile-linker

Ruby
1
star
54

we-connect

Elm
1
star
55

elm-ts-interop.com

Elm
1
star
56

elm-pages-netlify-cms-starter

Starter kit for elm-pages and Netlify CMS.
Elm
1
star