{"id":15696027,"url":"https://github.com/ootidea/ts-tagged-union","last_synced_at":"2025-05-08T22:23:22.090Z","repository":{"id":177808326,"uuid":"623221336","full_name":"ootidea/ts-tagged-union","owner":"ootidea","description":"A library for defining and manipulating algebraic data types in TypeScript.","archived":false,"fork":false,"pushed_at":"2024-09-23T13:15:08.000Z","size":588,"stargazers_count":9,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-28T06:35:45.353Z","etag":null,"topics":["algebraic-data-types","discriminated-unions","exhaustiveness-checking","library","narrowing","npm-package","pattern-matching","tagged-unions","typescript"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/ts-tagged-union","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"cc0-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ootidea.png","metadata":{"files":{"readme":"README.md","changelog":null,"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,"zenodo":null}},"created_at":"2023-04-04T00:05:53.000Z","updated_at":"2025-04-10T14:49:20.000Z","dependencies_parsed_at":null,"dependency_job_id":"40ed0e5a-e088-4b33-b535-db8ede42b44a","html_url":"https://github.com/ootidea/ts-tagged-union","commit_stats":null,"previous_names":["ootidea/algebraic-data-type","ootidea/ts-tagged-union"],"tags_count":21,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ootidea%2Fts-tagged-union","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ootidea%2Fts-tagged-union/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ootidea%2Fts-tagged-union/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ootidea%2Fts-tagged-union/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ootidea","download_url":"https://codeload.github.com/ootidea/ts-tagged-union/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253155924,"owners_count":21862776,"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":["algebraic-data-types","discriminated-unions","exhaustiveness-checking","library","narrowing","npm-package","pattern-matching","tagged-unions","typescript"],"created_at":"2024-10-03T19:06:41.614Z","updated_at":"2025-05-08T22:23:22.069Z","avatar_url":"https://github.com/ootidea.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003ets-tagged-union\u003c/h1\u003e\n\nA modern TypeScript library designed to reduce boilerplate for _tagged unions_, also known as _discriminated unions_.  \nThis library is also an implementation of [algebraic data types](https://wikipedia.org/wiki/Algebraic_data_type).  \n\n## Features\n\n- Effortlessly defines tagged union types, encompassing even recursive ones\n- Generates following helper functions for each tagged union type (without code generation 👍)\n    1. **Data constructors**\n    2. **Pattern matching functions**\n    3. **Type guard functions** ([type predicates](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates))\n- Works on both browsers and Node.js\n- 0 dependencies\n\n## Basic example\n\nHere is an example of defining a simple tagged union type and creating its values.  \n\n```ts\nimport { type TaggedUnion, createHelperFunctions } from 'ts-tagged-union'\n\n// Define a tagged union type\nexport type Color = TaggedUnion\u003c{\n  rgb: { r: number; g: number; b: number }\n  primary: {}\n  secondary: {}\n}\u003e\n\n// Get helper functions for the type\nexport const Color = createHelperFunctions\u003cColor\u003e()\n\n// Create object with a data constructor\nconst rgb = Color.rgb({ r: 255, g: 31, b: 0 })\nconst primary = Color.primary() // {} can be omitted\n\nconsole.log(rgb) // { r: 255, g: 31, b: 0, [Symbol(defaultTagKey)]: 'rgb' }\nconsole.log(primary) // { [Symbol(defaultTagKey)]: 'primary' }\n```\n\n## Pattern matching\n\nTo perform pattern matching with **exhaustiveness checking**, use the **`match`** function.  \n\n```ts\nconst color = Math.random() \u003c 0.5 ? Color.primary() : Color.secondary()\n\nconst cssColor = Color.match(color, {\n  rgb: ({ r, g, b }) =\u003e `rgb(${r}, ${g}, ${b})`,\n  primary: () =\u003e '#C0FFEE', \n  secondary: () =\u003e 'blue',\n})\n```\n\nThe third argument serves as a so-called **default case**, as follows.  \n\n```ts\nconst isAchromatic = Color.match(\n  color,\n  { rgb: ({ r, g, b }) =\u003e r === g \u0026\u0026 g === b },\n  (other) =\u003e false,\n)\n```\n\nTo perform pattern matching without **exhaustiveness checking**, use the **`matchPartial`** instead.  \n\n## Type guard functions\n\nType guard functions are available as the **`is`** and **`isNot`** properties, as shown below.  \n\n```ts\nif (Color.is.rgb(color)) {\n  // Here, the variable is narrowed to the rgb variant type.\n  console.log(color.r, color.g, color.b)\n}\n\nif (Color.isNot.secondary(color)) {\n  // Here, the variable is narrowed to the rgb or primary variant type.\n  console.log(color)\n}\n```\n\n## Custom tag key\n\nThe key of the property used to distinguish each variant is called _tag key_.  \nYou can specify a tag key as the second argument to `TaggedUnion\u003cT\u003e` as follows.  \n\n```ts\n// Define a tagged union type with a custom tag key, 'status'\ntype Response = TaggedUnion\u003c\n  {\n    Success: { payload: Blob }\n    Failure: { message: string }\n  },\n  'status' // Either a string literal or symbol type\n\u003e\n// You need to provide the tag key as an argument due to TypeScript specifications.\nconst Response = createHelperFunctions\u003cResponse\u003e('status')\n\nconst failure = Response.Failure({ message: 'Not found' })\nconsole.log(failure.status) // Failure\nconsole.log(Response.tagKey) // status\n```\n\n## Adapters for tagged union types defined without using this library\n\n`createHelperFunctions` and other utilities do not work for tagged union types without a _tag-key-pointer_.  \nThe _tag-key-pointer_ is a special hidden property that specifies which property is a tag.  \nIt exists only at the type level, so it does not affect runtime.  \n\nThe type defined with `TaggedUnion\u003cT\u003e` has the _tag-key-pointer_ property.  \nTo manually add it to an existing type, use **`AddTagKeyPointer`** as follows.  \n\n```ts\nimport { type AddTagKeyPointer, createHelperFunctions } from 'ts-tagged-union'\n\ntype RawTaggedUnion =\n  | { type: 'circle', radius: number }\n  | { type: 'rect', width: number; height: number }\n\ntype Shape = AddTagKeyPointer\u003cRawTaggedUnion, 'type'\u003e\nconst Shape = createHelperFunctions\u003cShape\u003e('type')\n```\n\nIf you need to remove the _tag-key-pointer_, use **`RemoveTagKeyPointer`**.  \n\n## Other utilities\n\nThere are also several other utilities.  \n\n### `TagKeyOf\u003cT\u003e`\nGet the tag key of the given tagged union type.\n\n\u003cdetails\u003e\n\u003csummary\u003eexample\u003c/summary\u003e\n\n```ts\ntype Response = TaggedUnion\u003c\n  {\n    Success: { payload: Blob }\n    Failure: { message: string }\n  },\n  'status'\n\u003e\n\ntype TagKey = TagKeyOf\u003cResponse\u003e // 'status'\n```\n\u003c/details\u003e\n\n### `VariantOf\u003cT, Tag\u003e`\nExtract the variant type with the specific tag from a tagged union type.\n\n\u003cdetails\u003e\n\u003csummary\u003eexample\u003c/summary\u003e\n\n```ts\ntype Response = TaggedUnion\u003c\n  {\n    Success: { payload: Blob }\n    Failure: { message: string }\n  },\n  'status'\n\u003e\n\ntype Variant = VariantOf\u003cResponse, 'Failure'\u003e // { status: 'Failure', message: string }\n```\n\u003c/details\u003e\n\n### `PayloadOf\u003cT, Tag\u003e`\nExtract the payload type of the variant with the specific tag from a tagged union type.\n\n\u003cdetails\u003e\n\u003csummary\u003eexample\u003c/summary\u003e\n\n```ts\ntype Response = TaggedUnion\u003c\n  {\n    Success: { payload: Blob }\n    Failure: { message: string }\n  },\n  'status'\n\u003e\n\ntype Payload = PayloadOf\u003cResponse, 'Failure'\u003e // { message: string }\n```\n\u003c/details\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Footidea%2Fts-tagged-union","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Footidea%2Fts-tagged-union","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Footidea%2Fts-tagged-union/lists"}