{"id":27048544,"url":"https://github.com/codedownio/aeson-typescript","last_synced_at":"2025-10-06T14:43:57.322Z","repository":{"id":44566853,"uuid":"115482421","full_name":"codedownio/aeson-typescript","owner":"codedownio","description":"Generate TypeScript definition files from your ADTs","archived":false,"fork":false,"pushed_at":"2025-02-07T03:38:04.000Z","size":391,"stargazers_count":61,"open_issues_count":4,"forks_count":27,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-13T05:07:46.676Z","etag":null,"topics":["apis","haskell","json","typescript"],"latest_commit_sha":null,"homepage":"","language":"Haskell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/codedownio.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-12-27T04:47:13.000Z","updated_at":"2025-04-06T16:11:48.000Z","dependencies_parsed_at":"2023-12-06T04:25:05.751Z","dependency_job_id":"e37fa00c-58b2-4dbe-869a-bda3ce5d380f","html_url":"https://github.com/codedownio/aeson-typescript","commit_stats":{"total_commits":303,"total_committers":13,"mean_commits":"23.307692307692307","dds":0.4092409240924092,"last_synced_commit":"d6a3addf220d51dcc1199744869beda2b8bb2aa1"},"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codedownio%2Faeson-typescript","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codedownio%2Faeson-typescript/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codedownio%2Faeson-typescript/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codedownio%2Faeson-typescript/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/codedownio","download_url":"https://codeload.github.com/codedownio/aeson-typescript/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248665747,"owners_count":21142123,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["apis","haskell","json","typescript"],"created_at":"2025-04-05T07:15:09.822Z","updated_at":"2025-10-06T14:43:52.288Z","avatar_url":"https://github.com/codedownio.png","language":"Haskell","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# Welcome to `aeson-typescript` [![Hackage](https://img.shields.io/hackage/v/aeson-typescript.svg)](https://hackage.haskell.org/package/aeson-typescript) ![aeson-typescript](https://github.com/codedownio/aeson-typescript/workflows/aeson-typescript/badge.svg)\n\nThis library provides a way to generate TypeScript `.d.ts` files that match your existing Aeson `ToJSON` instances.\nIf you already use Aeson's Template Haskell support to derive your instances, then deriving TypeScript is as simple as\n\n```haskell\n$(deriveTypeScript myAesonOptions ''MyType)\n```\n\nFor example,\n\n```haskell\ndata D a = Nullary\n         | Unary Int\n         | Product String Char a\n         | Record { testOne   :: Double\n                  , testTwo   :: Bool\n                  -- | This docstring will go into the generated TypeScript!\n                  , testThree :: D a\n                  } deriving Eq\n```\n\nNext we derive the necessary instances.\n\n```haskell\n$(deriveTypeScript (defaultOptions {fieldLabelModifier = drop 4, constructorTagModifier = map toLower}) ''D)\n```\n\nNow we can use the newly created instances.\n\n```haskell\n\u003e\u003e\u003e putStrLn $ formatTSDeclarations $ getTypeScriptDeclarations (Proxy :: Proxy (D T))\n\ntype D\u003cT\u003e = \"nullary\" | IUnary\u003cT\u003e | IProduct\u003cT\u003e | IRecord\u003cT\u003e;\n\ntype IUnary\u003cT\u003e = number;\n\ntype IProduct\u003cT\u003e = [string, string, T];\n\ninterface IRecord\u003cT\u003e {\n  tag: \"record\";\n  One: number;\n  Two: boolean;\n  // This docstring will go into the generated TypeScript!\n  Three: D\u003cT\u003e;\n}\n```\n\nIt's important to make sure your JSON and TypeScript are being derived with the same options. For this reason, we\ninclude the convenience `HasJSONOptions` typeclass, which lets you write the options only once, like this:\n\n```haskell\ninstance HasJSONOptions MyType where getJSONOptions _ = (defaultOptions {fieldLabelModifier = drop 4})\n\n$(deriveJSON (getJSONOptions (Proxy :: Proxy MyType)) ''MyType)\n$(deriveTypeScript (getJSONOptions (Proxy :: Proxy MyType)) ''MyType)\n```\n\nOr, if you want to be even more concise and don't mind defining the instances in the same file,\n\n```haskell\nmyOptions = defaultOptions {fieldLabelModifier = drop 4}\n\n$(deriveJSONAndTypeScript myOptions ''MyType)\n```\n\nRemembering that the Template Haskell `Q` monad is an ordinary monad, you can derive instances for several types at once like this:\n\n```haskell\n$(mconcat \u003c$\u003e traverse (deriveJSONAndTypeScript myOptions) [''MyType1, ''MyType2, ''MyType3])\n```\n\n\n# Suggestions for use\n\nThis 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:\n\nThe 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:\n\n```yaml\nexecutables:\n  ...\n  tsdef:\n    main: Main.hs\n    source-dirs: tsdef\n    dependencies:\n    - my-main-app\n    ...\n```\n\nAnd `tsdef/Main.hs` should look like this:\n\n```haskell\nmodule Main where\n\nimport Data.Proxy\nimport Data.Monoid\nimport MyLibraries\n\n$(deriveTypeScript (getJSONOptions (Proxy :: Proxy MyType1)) ''MyType1)\n$(deriveTypeScript (getJSONOptions (Proxy :: Proxy MyType2)) ''MyType2)\n...\n\nmain = putStrLn $ formatTSDeclarations (\n  (getTypeScriptDeclaration (Proxy :: Proxy MyType1)) \u003c\u003e\n  (getTypeScriptDeclaration (Proxy :: Proxy MyType2)) \u003c\u003e\n  ...\n)\n```\n\nNow you can generate the types by running `stack runhaskell tsdef/Main.hs \u003e types.d.ts`. I like to make this an automatic step in my Gulpfile, Webpack config, etc.\n\n\n# See also\n\nIf you want a more opinionated web framework for generating APIs, check out [servant](http://haskell-servant.readthedocs.io/en/stable/). If you use Servant, you may enjoy [servant-typescript](https://github.com/codedownio/servant-typescript), which is based on `aeson-typescript`! This companion package also has the advantage of magically collecting all the types used in your API, so you don't have to list them out manually.\n\nFor another very powerful framework that can generate TypeScript client code based on an API specification, see [Swagger/OpenAPI](https://github.com/swagger-api/swagger-codegen).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodedownio%2Faeson-typescript","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcodedownio%2Faeson-typescript","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodedownio%2Faeson-typescript/lists"}