The aeson-typescript package

[ Tags: bsd3, json, library, text, web ] [ Propose Tags ]

Please see the README on Github at

[Skip to Readme]


Change log
Dependencies aeson, base (>=4.7 && <5), containers, interpolate, mtl, template-haskell, text, th-abstraction, unordered-containers [details]
License BSD3
Copyright 2017 CodeDown
Author Tom McLaughlin
Category Text, Web, JSON
Home page
Bug tracker
Source repo head: git clone
Uploaded Wed Jan 31 01:09:38 UTC 2018 by thomasjm
Distributions NixOS:, Stackage:
Downloads 114 total (114 in the last 30 days)
Rating (no votes yet) [estimated by rule of succession]
Your Rating
  • λ
  • λ
  • λ
Status Docs available [build log]
Last success reported on 2018-01-31 [all 1 reports]
Hackage Matrix CI




Maintainer's Corner

For package maintainers and hackage trustees

Readme for aeson-typescript-

[back to package description]

Welcome to aeson-typescript Hackage Build Status

This library provides a way to generate TypeScript .d.ts files that match your existing Aeson ToJSON instances. If you already use Aeson's Template Haskell support to derive your instances, then deriving TypeScript is as simple as

$(deriveTypeScript myAesonOptions ''MyType)

For example,

data D a = Nullary
         | Unary Int
         | Product String Char a
         | Record { testOne   :: Double
                  , testTwo   :: Bool
                  , testThree :: D a
                  } deriving Eq

Next we derive the necessary instances.

$(deriveTypeScript (defaultOptions {fieldLabelModifier = drop 4, constructorTagModifier = map toLower}) ''D)

Now we can use the newly created instances.

>>> putStrLn $ formatTSDeclarations $ getTypeScriptDeclaration (Proxy :: Proxy D)

type D<T> = "nullary" | IUnary<T> | IProduct<T> | IRecord<T>;

type IUnary<T> = number;

type IProduct<T> = [string, string, T];

interface IRecord<T> {
  tag: "record";
  One: number;
  Two: boolean;
  Three: D<T>;

It's important to make sure your JSON and TypeScript are being derived with the same options. For this reason, we include the convenience HasJSONOptions typeclass, which lets you write the options only once, like this:

instance HasJSONOptions MyType where getJSONOptions _ = (defaultOptions {fieldLabelModifier = drop 4})

$(deriveJSON (getJSONOptions (Proxy :: Proxy MyType)) ''MyType)
$(deriveTypeScript (getJSONOptions (Proxy :: Proxy MyType)) ''MyType)

Suggestions for use

This library was written to make it easier to typecheck your TypeScript frontend against your Haskell backend. Here's how I like to integrate it into my workflow:

The idea is to set up a separate Haskell executable in your Cabal file whose sole purpose is to generate types. For example, in your hpack package.yaml file add a new executable like this:

    main: Main.hs
    source-dirs: tsdef
    - my-main-app

And tsdef/Main.hs should look like this:

module Main where

import Data.Proxy
import Data.Monoid
import MyLibraries

$(deriveTypeScript (getJSONOptions (Proxy :: Proxy MyType1)) ''MyType1)
$(deriveTypeScript (getJSONOptions (Proxy :: Proxy MyType2)) ''MyType2)

main = putStrLn $ formatTSDeclarations (
  (getTypeScriptDeclaration (Proxy :: Proxy MyType1)) <>
  (getTypeScriptDeclaration (Proxy :: Proxy MyType2)) <>

Now you can generate the types by running stack runhaskell tsdef/Main.hs > types.d.ts. I like to make this an automatic step in my Gulpfile, Webpack config, etc.

See also

If you want a much more opinionated web framework for generating APIs, check out servant. (Although it doesn't seem to support TypeScript client generation at the moment.)

For another very powerful framework that can generate TypeScript client code based on an API specification, see Swagger/OpenAPI.