{"id":13565205,"url":"https://github.com/minoki/purescript-tsd-gen","last_synced_at":"2025-08-01T07:04:52.807Z","repository":{"id":51969361,"uuid":"120106862","full_name":"minoki/purescript-tsd-gen","owner":"minoki","description":"TypeScript Declaration File (.d.ts) generator for PureScript","archived":false,"fork":false,"pushed_at":"2024-02-12T02:06:09.000Z","size":259,"stargazers_count":94,"open_issues_count":4,"forks_count":4,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-05-08T23:48:06.095Z","etag":null,"topics":["purescript","typescript"],"latest_commit_sha":null,"homepage":null,"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/minoki.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}},"created_at":"2018-02-03T16:11:32.000Z","updated_at":"2025-02-17T07:02:09.000Z","dependencies_parsed_at":"2024-01-14T03:51:03.666Z","dependency_job_id":"f8ff3946-5e7f-48f2-b1a2-be26f546c83b","html_url":"https://github.com/minoki/purescript-tsd-gen","commit_stats":{"total_commits":72,"total_committers":2,"mean_commits":36.0,"dds":0.09722222222222221,"last_synced_commit":"9cea0f269185f93867f5056a588794558981b8aa"},"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/minoki%2Fpurescript-tsd-gen","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/minoki%2Fpurescript-tsd-gen/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/minoki%2Fpurescript-tsd-gen/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/minoki%2Fpurescript-tsd-gen/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/minoki","download_url":"https://codeload.github.com/minoki/purescript-tsd-gen/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253166477,"owners_count":21864467,"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":["purescript","typescript"],"created_at":"2024-08-01T13:01:42.522Z","updated_at":"2025-05-08T23:48:14.588Z","avatar_url":"https://github.com/minoki.png","language":"Haskell","readme":"# purescript-tsd-gen\n\nThis is a TypeScript Declaration File (.d.ts) generator for PureScript.\n\nThis tool helps you use PureScript modules from TypeScript.\n\n# How to build\n\n```sh\n$ git clone https://github.com/minoki/purescript-tsd-gen.git\n$ cd purescript-tsd-gen\n$ stack install --stack-yaml=stack-purs0.15.15.yaml\n```\n\nIf you are using PureScript 0.14.x or older, try following:\n\n```sh\n$ git clone -b purs0.14.x https://github.com/minoki/purescript-tsd-gen.git\n$ cd purescript-tsd-gen\n$ stack install --stack-yaml=stack-purs0.14.9.yaml\n```\n\n# How to use\n\nAssuming you have compiled PureScript modules into `./output`:\n\n```sh\n$ tree output/\noutput/\n├── Control.Alt\n│   ├── externs.cbor\n│   └── index.js\n├── Control.Alternative\n│   ├── externs.cbor\n│   └── index.js\n...\n└── YourFancyModuleInPurs\n    ├── externs.cbor\n    └── index.js\n```\n\nRun the following to get the declaration files:\n\n```sh\n$ purs-tsd-gen -d output/ YourFancyModuleInPurs\n```\n\nNow you get `index.d.ts` alongside each module's `index.js`:\n\n```sh\n$ tree output/\noutput/\n├── Control.Alt\n│   ├── externs.cbor\n│   ├── index.d.ts\n│   └── index.js\n├── Control.Alternative\n│   ├── externs.cbor\n│   ├── index.d.ts\n│   └── index.js\n...\n└── YourFancyModuleInPurs\n    ├── externs.cbor\n    ├── index.d.ts\n    └── index.js\n```\n\n# Mapping of types\n\n## Builtin\n\nPrimitive types translate as one would imagine:\n\n- `Function s t` (`s -\u003e t`) --\u003e `(_: s) =\u003e t`\n- `Array t` --\u003e `Array\u003ct\u003e`\n    - TODO: Add an option to emit `ReadonlyArray\u003ct\u003e`.\n- `Record { key1 :: Type1, key2 :: Type2 }` --\u003e `{ key1: Type1, key2: Type2 }`\n    - TODO: Add an option to make fields `readonly`.\n- `Number`, `Int` --\u003e `number`\n- `String`, `Char` --\u003e `string`\n- `Boolean` --\u003e `boolean`\n\nSome modules get special handling:\n\n- `Data.Function.Uncurried`\n    - `Fn0 r` --\u003e `() =\u003e r`\n    - `Fn2 a0 a1 r` --\u003e `(_0: a0, _1: a2) =\u003e r`\n    - `Fn3 a0 a1 a2 r` --\u003e `(_0: a0, _1: a1, _2: a2) =\u003e r`\n    - ...\n    - `Fn10 a0 a1 ... a9 r` --\u003e `(_0: a0, _1: a1, ..., _9: a9) =\u003e r`\n- `Effect` (from [purescript-effect](https://github.com/purescript/purescript-effect))\n    - `Effect a` -\u003e `() =\u003e a`\n- `Effect.Uncurried` (from purescript-effect)\n    - `EffectFn1 a0 r ` -\u003e `(_0: a0) =\u003e r`\n    - `EffectFn2 a0 a1 r` -\u003e `(_0: a0, _1: a1) =\u003e r`\n    - `EffectFn3 a0 a1 a2 r` -\u003e `(_0: a0, _1: a1, _2: a2) =\u003e r`\n    - ...\n    - `EffectFn10 a0 a1 ... a9 r` -\u003e `(_0: a0, _1: a1, ..., _9: a9) =\u003e r`\n- `Data.Variant` (from [purescript-variant](https://github.com/natefaubion/purescript-variant))\n    - `Variant (tag1 :: Type1, tag2 :: Type2)` --\u003e `{type: \"tag1\", value: Type1} | {type: \"tag2\", value: Type2}`\n- `Data.Nullable` (from [purescript-nullable](https://github.com/purescript-contrib/purescript-nullable))\n    - `Nullable a` --\u003e `a | null`\n- `Foreign.Object` (from [purescript-foreign-object](https://github.com/purescript/purescript-foreign-object))\n    - `Object t` --\u003e `{[_: string]: t}`\n- `Control.Monad.Eff` (deprecated)\n    - `Eff e r` -\u003e `() =\u003e r`\n- `Data.StrMap` (deprecated)\n    - `StrMap t` --\u003e `{[_: string]: t}`\n\n## User-defined Data Types\n\nData type `SomeFancyDataType :: Type -\u003e ... -\u003e Type -\u003e Type` is translated to `SomeFancyDataType\u003ca0, ..., an\u003e`.\n\nIn contrast to usual TypeScript's structual subtyping, the translated types mimicks nominal typing with extra dummy fields.\n\nSum types are translated to discriminated union types, with a dummy tag field.  Type guards with `instanceof` should work.\n\nData constructors are typed as an object type with `new` signature and `create` or `value` field.\n\nTypes whose data constructors are not exposed, i.e. abstract types, are translated to an object type which contains `never` as a field, so that you cannot accidentally create a value of abstract types in TypeScript world.\n\nLet's see some examples:\n\n- Tuple\n\n```purescript\ndata Tuple a b = Tuple a b\n```\n\ncompiles to:\n\n```typescript\nexport type /*data*/ Tuple\u003ca, b\u003e = Tuple$$Tuple\u003c a, b \u003e;\ninterface Tuple$$Tuple\u003ca, b\u003e {\n    \"$$pursType\"?: \"Data.Tuple.Tuple\";\n    \"$$pursTag\"?: \"Tuple\";\n    value0: a;\n    value1: b;\n}\nexport const /*data ctor*/ Tuple: { create: \u003ca, b\u003e(_: a) =\u003e (_: b) =\u003e Tuple\u003c a, b \u003e; new \u003ca, b\u003e(_0: a, _1: b): Tuple$$Tuple\u003c a, b \u003e };\n```\n\n- Maybe\n\n```purescript\ndata Maybe a = Nothing | Just a\n```\n\ncompiles to:\n\n```typescript\nexport type /*data*/ Maybe\u003ca\u003e = Maybe$$Nothing | Maybe$$Just\u003c a \u003e;\ninterface Maybe$$Nothing {\n    \"$$pursType\": \"Data.Maybe.Maybe\";\n    \"$$pursTag\": \"Nothing\";\n}\nexport const /*data ctor*/ Nothing: { value: Maybe\u003c any /* type variable a */ \u003e; new (): Maybe$$Nothing };\ninterface Maybe$$Just\u003ca\u003e {\n    \"$$pursType\": \"Data.Maybe.Maybe\";\n    \"$$pursTag\": \"Just\";\n    value0: a;\n}\nexport const /*data ctor*/ Just: { create: \u003ca\u003e(_: a) =\u003e Maybe\u003c a \u003e; new \u003ca\u003e(_: a): Maybe$$Just\u003c a \u003e };\n```\n\n- Either\n\n```purescript\ndata Either a b = Left a | Right b\n```\n\ncompiles to:\n\n```typescript\nexport type /*data*/ Either\u003ca, b\u003e = Either$$Left\u003c a \u003e | Either$$Right\u003c b \u003e;\ninterface Either$$Left\u003ca\u003e {\n    \"$$pursType\": \"Data.Either.Either\";\n    \"$$pursTag\": \"Left\";\n    value0: a;\n}\nexport const /*data ctor*/ Left: { create: \u003ca, b\u003e(_: a) =\u003e Either\u003c a, b \u003e; new \u003ca\u003e(_: a): Either$$Left\u003c a \u003e };\ninterface Either$$Right\u003cb\u003e {\n    \"$$pursType\": \"Data.Either.Either\";\n    \"$$pursTag\": \"Right\";\n    value0: b;\n}\nexport const /*data ctor*/ Right: { create: \u003ca, b\u003e(_: b) =\u003e Either\u003c a, b \u003e; new \u003cb\u003e(_: b): Either$$Right\u003c b \u003e };\n```\n\n## Newtypes\n\nNewtypes are translated to a type synonym.  The nominal property in PureScript is lost.\n\n## `foreign import data`\n\n`foreign import data` are translated to `any`.\n\nMaybe there should be a way for PS-library authors to provide corresponding `.d.ts` for foreign JavaScript modules.\n\n## Universally Quantified Types\n\nSimple polymorphic functions translate to generic functions.\n\nIf the type is too complex, there may situations where the emitted declarations contain undue `any` type.\n\n## Higher-Kinded Types\n\nNot supported.\n\n## Type Classes\n\nNot supported.\n","funding_links":[],"categories":["Haskell"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fminoki%2Fpurescript-tsd-gen","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fminoki%2Fpurescript-tsd-gen","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fminoki%2Fpurescript-tsd-gen/lists"}