{"_id":"ts-algebra","_rev":"14-28684504f9467128062c20709e95afa8","name":"ts-algebra","dist-tags":{"beta":"1.2.0-beta.0","latest":"2.0.0"},"versions":{"1.0.0-beta.0":{"name":"ts-algebra","version":"1.0.0-beta.0","description":"Empower your types with new operations!","main":"lib/index.d.ts","scripts":{"release":"bash scripts/release.bash","test":"tsc --noEmit"},"dependencies":{"ts-toolbelt":"^9.6.0"},"devDependencies":{"rollup":"^2.67.3","rollup-plugin-dts":"4.1.0","rollup-plugin-import-map":"^2.2.2","typescript":"^4.5.5"},"author":{"name":"Thomas Aribart"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/ThomasAribart/ts-algebra.git"},"keywords":["typescript","type","ts"],"bugs":{"url":"https://github.com/ThomasAribart/ts-algebra/issues"},"homepage":"https://github.com/ThomasAribart/ts-algebra#readme","gitHead":"2198b2693f130bd63b04c1d10ea5976966a2e2eb","_id":"ts-algebra@1.0.0-beta.0","_nodeVersion":"14.17.1","_npmVersion":"6.14.13","dist":{"integrity":"sha512-KFNLiZsubtQNuFlx83oHE8mVwRsG4vxHq6UyWIVOVEJE6xkLapkkN2yg1NaJ5jLFOkXVOdrvECpFef+S4rRNYw==","shasum":"40a9632477b2debfe9acfeeaab536180848068d0","tarball":"https://registry.npmjs.org/ts-algebra/-/ts-algebra-1.0.0-beta.0.tgz","fileCount":45,"unpackedSize":51515,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiES0dACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmr9Mw/+LXY/Ozt0oEu7aMGF9sbjX3GKwHaNeWN4J7ysTMRykoLSz8D2\r\nbvRavUFf+bCXgDSiLxMYOqdEG+a654ZUcD02u8q3xwD9j4SIqAOEhADeurXR\r\nSjShAvQWRTXuNHX4uHkuuKoa8jLueEqrF4VcgU0lKwtvJm8hqNuFov0zLmMI\r\nfrTY5uLfuVEnBg8rA1cjCY3GnXfbbeWKuHagGCbS4mCOgDOd4Ti4G62Hq2Qo\r\nXBcWpCcykd2Pw85CDQ33O865mVi+/7XfRhTqG8fAEKaxZU1AuX3iZOx2es3M\r\n6vtvbGFx8siSIjMW6uvlbE8XKkkwSXzaPXO/4BJa0oyhvlqbRn8Sy8+0GZ+5\r\nrWeKyKuxfrezETs8YOMKI9sKJmAzQJZjbAgBKjF6tqiFfThQQoC6KpxwyYV5\r\nJrK7kye7TSwsasIF0QHkvtFOiZeJ3JxnP0cjNJubnB8nX57x9zPKXk6TsM4a\r\nwqjqh2KJXtEZP7H82FWgEAIKVjjOS8C5dylb8gSFn8ZJ+s5K8FYSvanfDYKb\r\n3A72GJMy1B3zHsgOlFlrtzkvkUvc6jMiLlolj66rBFrbwv9uHuiBnDN/fGpE\r\nMq2790yl6sLa9prlMKNnysRE1FFfzQHZmGk/iw1RXQ52KzZaioe2BA6BkmMi\r\nDrsHwlbl7v3300U+YGlNOs65jQMg6CFBp/g=\r\n=/C+X\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDpmTUGC3CdF2xpmwaURt8Ael5YKfLoaR3JU/vMV6dRQAIhANJ6HSq1CdVve4nnqYWnCSd+tathZXMi0Lt1MqhJ89Yv"}]},"_npmUser":{"name":"thomasaribart","email":"thomas.aribart@gmail.com"},"directories":{},"maintainers":[{"name":"thomasaribart","email":"thomas.aribart@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ts-algebra_1.0.0-beta.0_1645292829437_0.18249044547755422"},"_hasShrinkwrap":false},"1.0.0-beta.1":{"name":"ts-algebra","version":"1.0.0-beta.1","description":"Types on steroids 💊","main":"lib/index.d.ts","scripts":{"release":"bash scripts/release.bash","test":"tsc --noEmit"},"dependencies":{"ts-toolbelt":"^9.6.0"},"devDependencies":{"rollup":"^2.67.3","rollup-plugin-dts":"4.1.0","rollup-plugin-import-map":"^2.2.2","typescript":"^4.5.5"},"author":{"name":"Thomas Aribart"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/ThomasAribart/ts-algebra.git"},"keywords":["typescript","type","ts"],"bugs":{"url":"https://github.com/ThomasAribart/ts-algebra/issues"},"homepage":"https://github.com/ThomasAribart/ts-algebra#readme","readme":"\n\n

\n If you use this repo, star it ✨\n

\n\n# Types on steroids 💊\n\n`ts-algebra` exposes a subset of TS types called **Meta-types**: Meta-types are types that encapsulate other types.\n\n```typescript\nimport { Meta } from \"ts-algebra\";\n\ntype MetaString = Meta.Primitive;\n```\n\nThe encapsulated type can be retrieved using the `Resolve` operation.\n\n```typescript\ntype Resolved = Meta.Resolve;\n// => string 🙌\n```\n\nYou can also use the more compact `M` notation:\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Primitive\n>;\n```\n\n## Okay, but... why ? 🤔\n\nMeta-types allow operations that **are not possible with conventional types**.\n\nFor instance, they allow new [\"intersect\"](#intersect) and [\"exclude\"](#exclude) operations, and handling objects additional properties:\n\n```typescript\ntype MyObject = {\n str: string; // <= ❌ \"str\" is assignable to string\n [key: string]: number;\n};\n\ntype MyObjectKeys = keyof MyObject;\n// => string <= ❌ Unable to isolate \"str\"\n```\n\nThink of meta-types as a parallel universe where all kinds of magic can happen 🌈 Once your computations are over, you can retrieve the results by resolving them.\n\n\n\n> Meta-types were originally part of [json-schema-to-ts](https://github.com/ThomasAribart/json-schema-to-ts). Check it to see a real-life usage.\n\n## Table of content\n\n- [Installation](#%EF%B8%8F-installation)\n- [Cardinality](#-cardinality)\n- [Meta-types](#-meta-types)\n - [Any](#any)\n - [Never](#never)\n - [Const](#const)\n - [Enum](#enum)\n - [Primitive](#primitive)\n - [Array](#array)\n - [Tuple](#tuple)\n - [Object](#object)\n - [Union](#union)\n- [Methods](#-methods)\n - [Resolve](#resolve)\n - [Intersect](#intersect)\n - [Exclude](#exclude)\n- [Type constraints](#-type-constraints)\n- [Unsafe types](#%EF%B8%8F-unsafe-types-and-methods)\n\n## ☁️ Installation\n\n```bash\n# npm\nnpm install --save-dev ts-algebra\n\n# yarn\nyarn add --dev ts-algebra\n```\n\n## 🧮 Cardinality\n\nA bit of theory first:\n\n- The [**cardinality**](https://en.wikipedia.org/wiki/Cardinality) of a type is the number of distinct values (potentially infinite) that can be assigned to it\n- A meta-type is said **representable** if at least one value can be assigned to its resolved type (cardinality ≥ 1)\n\nAn important notion to keep in mind using `ts-algebra`:\n\n---\n\n

\n M.Never is the only Meta-Type that is non-representable\n
\n (i.e. that resolves to never)\n

\n\n---\n\nAny other non-representable meta-type (e.g. an object with a non-representable but required property) will be instanciated as `M.Never`.\n\nThere are drawbacks to this choice (the said property is hard to find and debug) but stronger benefits: This drastically reduces type computations, in particular in [intersections](#intersect) and [exclusions](#exclude). This is crucial for performances and stability.\n\n## ✨ Meta-types\n\n### Any\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Any\n>;\n// => unknown\n```\n\n### Never\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Never\n>;\n// => never\n```\n\n### Const\n\nUsed for types with [cardinalities](#meta-types) of 1.\n\n**Arguments:**\n\n- Value (type)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Const<\"I love pizza\">\n>;\n// => \"I love pizza\"\n```\n\n### Enum\n\nUsed for types with finite [cardinalities](#meta-types).\n\n**Arguments:**\n\n- Values (type union)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Food = M.Resolve<\n M.Enum<\"pizza\" | \"tacos\" | \"fries\">\n>;\n// => \"pizza\" | \"tacos\" | \"fries\"\n```\n\n> ☝️ `M.Enum` is [non-representable](#✨-meta-types)\n\n### Primitive\n\nUsed for either `string`, `number`, `boolean` or `null`.\n\n**Arguments:**\n\n- Value (string | number | boolean | null)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Primitive\n>;\n// => string\n```\n\n### Array\n\nUsed for lists of items of the same type.\n\n**Arguments:**\n\n- Items (?meta-type = M.Any)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Array\n>;\n// => unknown[]\n\ntype Resolved = M.Resolve<\n M.Array>\n>;\n// => string[]\n```\n\n> ☝️ Any meta-array is representable by `[]`\n\n### Tuple\n\nUsed for finite, ordered lists of items of different types.\n\nMeta-tuples can have **additional items** (typed as [`M.Any`](#any) by default).\n\n**Arguments:**\n\n- RequiredItems (meta-type[]):\n- IsOpen (?boolean = false): Wether the tuple allows\n additional items\n- AdditionalItems (?meta-type = M.Any): Type of\n additional items\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Tuple<[M.Primitive]>\n>;\n// => [string]\n\ntype Resolved = M.Resolve<\n M.Tuple<\n [M.Primitive],\n true\n >\n>;\n// => [string, ...unknown[]]\n\ntype Resolved = M.Resolve<\n M.Tuple<\n [M.Primitive],\n true,\n M.Primitive\n >\n>;\n// => [string, ...string[]]\n```\n\n> ☝️ A meta-tuple is [non-representable](#✨-meta-types) if one of its required items is non-representable\n\n### Object\n\nUsed for sets of key-value pairs (properties) which can be required or not.\n\nMeta-objects can have **additional properties** (typed as [`M.Any`](#any) by default).\n\nIn presence of named properties, additional properties are resolved as `unknown` to avoid conflicts. However, they are used as long as the meta-type is not resolved (especially in [intersections](#intersect) and [exclusions](#exclude)).\n\n**Arguments:**\n\n- NamedProperties (?{ [key:string]: meta-type } = {})\n- RequiredPropertiesKeys (?string union = never)\n- IsOpen (?boolean = false): Wether the object allows\n additional properties\n- AdditionalProperties (?meta-type = M.Any): The type of\n additional properties\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Object<\n {\n required: M.Primitive;\n notRequired: M.Primitive;\n },\n \"required\",\n true,\n M.Primitive\n >\n>;\n// => {\n// req: string,\n// notRequired?: null,\n// [key: string]: unknown\n// }\n```\n\n> ☝️ A meta-object is [non-representable](#✨-meta-types) if one of its required properties value is non-representable:\n>\n> - If it is a non-representable named property\n> - If it is an additional property, and the object doesn't allow it\n> - If it is an additional property, and additional properties are non-representable\n\n### Union\n\nUsed to combine meta-types in a union of meta-types.\n\n**Arguments:**\n\n- Values (meta-type union)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Food = M.Resolve<\n M.Union<\n | M.Primitive\n | M.Enum<\"pizza\" | \"tacos\" | \"fries\">\n | M.Const\n >\n>;\n// => number\n// | \"pizza\" | \"tacos\" | \"fries\"\n// | true\n```\n\n> ☝️ A meta-union is [non-representable](#✨-meta-types) if it is empty, or if none of its elements is representable\n\n## 🔧 Methods\n\n### Resolve\n\nResolves the meta-type to its encapsulated type.\n\n**Arguments:**\n\n- MetaType (meta-type)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Primitive\n>;\n// => string\n```\n\n### Intersect\n\nTakes two meta-types as arguments, and returns their intersection as a meta-type.\n\n**Arguments:**\n\n- LeftMetaType (meta-type)\n- RightMetaType (meta-type)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Intersected = M.Intersect<\n M.Primitive,\n M.Enum<\"I love pizza\"\n | [\"tacos\"]\n | { and: \"fries\" }\n >\n>\n// => M.Enum<\"I love pizza\">\n```\n\nMeta-type intersections differ from conventional intersections:\n\n\n```typescript\ntype ConventionalIntersection =\n { str: string } & { num: number };\n// => { str: string, num: number }\n\ntype MetaIntersection = M.Intersect<\n M.Object<\n { str: M.Primitive },\n \"str\"\n >,\n M.Object<\n { num: M.Primitive },\n \"num\"\n >\n>;\n// => M.Never: \"num\" is required in B\n// ...but denied in A\n```\n\nIntersections are recursively propagated among tuple items and object properties, and take into account additional items and properties:\n\n\n```typescript\ntype Intersected = M.Intersect<\n M.Tuple<\n [M.Primitive],\n true,\n M.Primitive\n >,\n M.Tuple<\n [M.Enum<\"pizza\" | 42>],\n true,\n M.Enum<\"fries\" | true>\n >\n>;\n// => M.Tuple<\n// [M.Enum<42>],\n// true,\n// M.Enum<\"fries\">\n// >\n\ntype Intersected = M.Intersect<\n M.Object<\n { food: M.Primitive },\n \"food\",\n true\n >,\n M.Object<\n { age: M.Primitive },\n \"age\",\n true,\n M.Enum<\"pizza\" | \"fries\" | 42>\n >\n>;\n// => M.Object<\n// {\n// food: M.Enum<\"pizza\" | \"fries\">,\n// age: M.Primitive\n// },\n// \"food\" | \"age\",\n// true,\n// M.Enum<\"pizza\" | \"fries\" | 42>\n// >\n```\n\nIntersections are distributed among unions:\n\n\n```typescript\ntype Intersected = M.Intersect<\n M.Primitive,\n M.Union<\n | M.Const<\"pizza\">\n | M.Const<42>\n >\n>;\n// => M.Union<\n// | M.Const<\"pizza\">\n// | M.Never\n// >\n```\n\n### Exclude\n\nTakes two meta-types as arguments, and returns their exclusion as a meta-type.\n\n**Arguments:**\n\n- SourceMetaType (meta-type)\n- ExcludedMetaType (meta-type)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Excluded = M.Exclude<\n M.Enum<\"I love pizza\"\n | [\"tacos\"]\n | { and: \"fries\" }\n >,\n M.Primitive,\n>\n// => M.Enum<\n// | [\"tacos\"]\n// | { and: \"fries\" }\n// >\n```\n\nMeta-type exclusions differ from conventional exclusions:\n\n\n```typescript\ntype ConventionalExclusion = Exclude<\n { req: string; notReq?: string },\n { req: string }\n>;\n// => never\n// ObjectA is assignable to ObjectB\n\ntype MetaExclusion = M.Exclude<\n M.Object<\n {\n req: M.Primitive;\n notReq: M.Primitive;\n },\n \"req\"\n >,\n M.Object<\n { req: M.Primitive },\n \"req\"\n >\n>;\n// => ObjectA\n// Exclusion is still representable\n```\n\n\n```typescript\ntype ConventionalExclusion = Exclude<\n { food: \"pizza\" | 42 },\n { [k: string]: number }\n>;\n// => { food: \"pizza\" | 42 }\n\ntype MetaExclusion = M.Exclude<\n M.Object<\n { food: M.Enum<\"pizza\" | 42> },\n \"food\"\n >,\n M.Object<\n {},\n never,\n true,\n M.Primitive\n >\n>;\n// => M.Object<\n// { food: M.Enum<\"pizza\"> },\n// \"food\"\n// >\n```\n\nWhen exclusions can be collapsed on a single item or property, they are recursively propagated among tuple items and object properties, taking into account additional items and properties:\n\n\n```typescript\ntype Excluded = M.Exclude<\n M.Tuple<[M.Enum<\"pizza\" | 42>]>,\n M.Tuple<[M.Primitive]>\n>;\n// => M.Tuple<[M.Enum<\"pizza\">]>\n\ntype Excluded = M.Exclude<\n M.Tuple<\n [M.Enum<\"pizza\" | 42>],\n true,\n M.Enum<\"fries\" | true>\n >,\n M.Tuple<\n [M.Primitive],\n true,\n M.Primitive\n >\n>;\n// => TupleA\n// Exclusion is not collapsable on a single item\n\ntype Excluded = M.Exclude<\n M.Object<\n {\n reqA: M.Enum<\"pizza\" | 42>;\n reqB: M.Enum<\"pizza\" | 42>;\n },\n \"reqA\" | \"reqB\"\n >,\n M.Object<\n {},\n never,\n true,\n M.Primitive\n >\n>;\n// => ObjectA\n// Exclusion is not collapsable on a single property\n```\n\nExclusions are distributed among unions:\n\n\n```typescript\ntype Excluded = M.Exclude<\n M.Union<\n | M.Const<\"pizza\">\n | M.Const<42>\n >,\n M.Primitive\n>;\n// => M.Union<\n// | M.Const<\"pizza\">\n// | M.Never\n// >\n```\n\nExluding a union returns the intersection of the exclusions of all elements, applied separately:\n\n\n```typescript\ntype Excluded = M.Exclude<\n M.Enum<42 | \"pizza\" | true>,\n M.Union<\n | M.Primitive\n | M.Primitive\n >\n>;\n// => M.Enum<\"pizza\">\n```\n\n## 🚧 Type constraints\n\nTo prevent errors, meta-types inputs are validated against type constraints:\n\n\n```typescript\ntype Invalid = M.Array<\n string // <= ❌ Meta-type expected\n>;\n```\n\nIf you need to use them, all type constraints are also exported:\n\n| Meta-type | Type constraint |\n| ------------- | :--------------------------------------------------------------------------- |\n| `M.Any` | `M.AnyType` = `M.Any` |\n| `M.Never` | `M.NeverType` = `M.Never` |\n| `M.Const` | `M.ConstType` = `M.Const` |\n| `M.Enum` | `M.EnumType` = `M.Enum` |\n| `M.Primitive` | `M.PrimitiveType` = `M.Primitive` |\n| `M.Array` | `M.ArrayType` = `M.Array` |\n| `M.Tuple` | `M.TupleType` = `M.Tuple` |\n| `M.Object` | `M.ObjectType` = `M.Object, string, boolean, M.Type>` |\n| `M.Union` | `M.UnionType` = `M.Union` |\n| - | `M.Type` = Union of the above |\n\n## ✂️ Unsafe types and methods\n\nIn deep and self-referencing computations like in [json-schema-to-ts](https://github.com/ThomasAribart/json-schema-to-ts), type constraints can become an issue, as the compiler may not be able to confirm the input type validity ahead of usage.\n\n\n```typescript\ntype MyArray = M.Array<\n VeryDeepTypeComputation<\n ...\n > // <= 💥 Type constraint can break\n>\n```\n\nFor such cases, `ts-algebra` exposes **\"unsafe\"** types and methods, that behave the same as \"safe\" ones but removing any type constraints. If you use them, beware: The integrity of the compiling is up to you 😉\n\n| Safe | Unsafe |\n| ------------- | -------------- |\n| `M.Any` | - |\n| `M.Never` | - |\n| `M.Const` | - |\n| `M.Enum` | - |\n| `M.Primitive` | `M.$Primitive` |\n| `M.Array` | `M.$Array` |\n| `M.Tuple` | `M.$Tuple` |\n| `M.Object` | `M.$Object` |\n| `M.Union` | `M.$Union` |\n| `M.Resolve` | `M.$Resolve` |\n| `M.Intersect` | `M.$Intersect` |\n| `M.Exclude` | `M.$Exclude` |\n","readmeFilename":"README.md","gitHead":"3e6e1843bf241babd7bbc64f9bb7b4522c6769d5","_id":"ts-algebra@1.0.0-beta.1","_nodeVersion":"14.17.1","_npmVersion":"8.6.0","dist":{"integrity":"sha512-BKLiIVDHm0BWRssJ3J9ox/ibPzbQ73jW5JfoWLQ9PBPUiQdIcS6QYViN7jEPSFXdflcPnfZeL0cfUAuH+0oeCw==","shasum":"966cf8d1fae8807043830f1d86244c5dc832ecf4","tarball":"https://registry.npmjs.org/ts-algebra/-/ts-algebra-1.0.0-beta.1.tgz","fileCount":48,"unpackedSize":717506,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDLB5EFjP9pITKPz4CYLkdjEGwiUtRUf56tC3Qvn2zDnAIhAOHz/3WKCmKUwNQLrORWwPt+9OOS/nBoN7OV5+J3wBmx"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiTahoACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrCzw//Zmge0H1o9Fy7h3rMr7s5OyNz8dpBXGun/+dZKagbRlRDMNUV\r\nafTDaB+3w+EP7tYLKsRSUli8pXveyLIXRbCzEW3EbprjPo/kFcS2TcGZwsHJ\r\nv+DdrI0TxZFjUhJIiWIa5sgqABwvOHZfcfe+ktR4uzYvyNJt4mnIBHVaq/JO\r\nonitJADom0GIWZ/qkrVl+GytwTB5/DLvFtzQxb/JXzBOncpNzqD22NRVWzok\r\nktOSdExlSNkpDBwlqyjfeVn3wcoTcD623jFsXJMi8yTeLt4qdaENM0QZvNTd\r\n9G4yznco0JrK6DhAt0GE1ZaHdJqFGWSqRtWKMvnlrPdikSSwedORWB2luo95\r\nlIyD5Zb2XpHya/1s0uIxtSPbDBNXa3s+4Z9RWmB8Lc29GOYQfFSUUly7xcd1\r\ncG65QrYbBChWLinP/KnLUOf91nfSmHPtjBkrRnESVOswhbWD4NavIVhbfbbY\r\n9QENMVQlUpXY+sqdSqbEFmI0EleTxLXOLT/o60cqfpfySU33c3KMQ6kfXzOm\r\n8Sy4svaz5RSXb3rjbiG3oFhfcgW3KCQ/RuMj8QfGM9/T9kJpIIrIoMJrRuH1\r\nAOS5TOWiIC24VTJZD3dxP6GxYM2ikDvEpcCfPcphSjRPdHoQEYOYVrnUSquD\r\nkdSM68TYjcRYL3xt6IMsDvzMMp8UkxwfkvY=\r\n=uF8Y\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"thomasaribart","email":"thomas.aribart@gmail.com"},"directories":{},"maintainers":[{"name":"thomasaribart","email":"thomas.aribart@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ts-algebra_1.0.0-beta.1_1649256552402_0.49914840195000365"},"_hasShrinkwrap":false},"1.0.0-beta.3":{"name":"ts-algebra","version":"1.0.0-beta.3","description":"Types on steroids 💊","main":"lib/index.d.ts","scripts":{"release":"bash scripts/release.bash","test":"tsc --noEmit"},"dependencies":{"ts-toolbelt":"^9.6.0"},"devDependencies":{"rollup":"^2.67.3","rollup-plugin-dts":"4.1.0","rollup-plugin-import-map":"^2.2.2","typescript":"^4.5.5"},"author":{"name":"Thomas Aribart"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/ThomasAribart/ts-algebra.git"},"keywords":["typescript","type","ts"],"bugs":{"url":"https://github.com/ThomasAribart/ts-algebra/issues"},"homepage":"https://github.com/ThomasAribart/ts-algebra#readme","readme":"\n\n

\n If you use this repo, star it ✨\n

\n\n# Types on steroids 💊\n\n`ts-algebra` exposes a subset of TS types called **Meta-types**: Meta-types are types that encapsulate other types.\n\n```typescript\nimport { Meta } from \"ts-algebra\";\n\ntype MetaString = Meta.Primitive;\n```\n\nThe encapsulated type can be retrieved using the `Resolve` operation.\n\n```typescript\ntype Resolved = Meta.Resolve;\n// => string 🙌\n```\n\nYou can also use the more compact `M` notation:\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Primitive\n>;\n```\n\n## Okay, but... why ? 🤔\n\nMeta-types allow operations that **are not possible with conventional types**.\n\nFor instance, they allow new [\"intersect\"](#intersect) and [\"exclude\"](#exclude) operations, and handling objects additional properties:\n\n```typescript\ntype MyObject = {\n str: string; // <= ❌ \"str\" is assignable to string\n [key: string]: number;\n};\n\ntype MyObjectKeys = keyof MyObject;\n// => string <= ❌ Unable to isolate \"str\"\n```\n\nThink of meta-types as a parallel universe where all kinds of magic can happen 🌈 Once your computations are over, you can retrieve the results by resolving them.\n\n\n\n> Meta-types were originally part of [json-schema-to-ts](https://github.com/ThomasAribart/json-schema-to-ts). Check it to see a real-life usage.\n\n## Table of content\n\n- [Installation](#%EF%B8%8F-installation)\n- [Cardinality](#-cardinality)\n- [Meta-types](#-meta-types)\n - [Any](#any)\n - [Never](#never)\n - [Const](#const)\n - [Enum](#enum)\n - [Primitive](#primitive)\n - [Array](#array)\n - [Tuple](#tuple)\n - [Object](#object)\n - [Union](#union)\n- [Methods](#-methods)\n - [Resolve](#resolve)\n - [Intersect](#intersect)\n - [Exclude](#exclude)\n- [Type constraints](#-type-constraints)\n- [Unsafe types](#%EF%B8%8F-unsafe-types-and-methods)\n\n## ☁️ Installation\n\n```bash\n# npm\nnpm install --save-dev ts-algebra\n\n# yarn\nyarn add --dev ts-algebra\n```\n\n## 🧮 Cardinality\n\nA bit of theory first:\n\n- The [**cardinality**](https://en.wikipedia.org/wiki/Cardinality) of a type is the number of distinct values (potentially infinite) that can be assigned to it\n- A meta-type is said **representable** if at least one value can be assigned to its resolved type (cardinality ≥ 1)\n\nAn important notion to keep in mind using `ts-algebra`:\n\n---\n\n

\n M.Never is the only Meta-Type that is non-representable\n
\n (i.e. that resolves to never)\n

\n\n---\n\nAny other non-representable meta-type (e.g. an object with a non-representable but required property) will be instanciated as `M.Never`.\n\nThere are drawbacks to this choice (the said property is hard to find and debug) but stronger benefits: This drastically reduces type computations, in particular in [intersections](#intersect) and [exclusions](#exclude). This is crucial for performances and stability.\n\n## ✨ Meta-types\n\n### Any\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Any\n>;\n// => unknown\n```\n\n### Never\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Never\n>;\n// => never\n```\n\n### Const\n\nUsed for types with [cardinalities](#meta-types) of 1.\n\n**Arguments:**\n\n- Value (type)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Const<\"I love pizza\">\n>;\n// => \"I love pizza\"\n```\n\n### Enum\n\nUsed for types with finite [cardinalities](#meta-types).\n\n**Arguments:**\n\n- Values (type union)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Food = M.Resolve<\n M.Enum<\"pizza\" | \"tacos\" | \"fries\">\n>;\n// => \"pizza\" | \"tacos\" | \"fries\"\n```\n\n> ☝️ `M.Enum` is [non-representable](#✨-meta-types)\n\n### Primitive\n\nUsed for either `string`, `number`, `boolean` or `null`.\n\n**Arguments:**\n\n- Value (string | number | boolean | null)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Primitive\n>;\n// => string\n```\n\n### Array\n\nUsed for lists of items of the same type.\n\n**Arguments:**\n\n- Items (?meta-type = M.Any)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Array\n>;\n// => unknown[]\n\ntype Resolved = M.Resolve<\n M.Array>\n>;\n// => string[]\n```\n\n> ☝️ Any meta-array is representable by `[]`\n\n### Tuple\n\nUsed for finite, ordered lists of items of different types.\n\nMeta-tuples can have **additional items**, typed as [`M.Never`](#never) by default. Thus, any meta-tuple is considered **closed** (additional items not allowed), unless a representable additional items meta-type is specified, in which case it becomes **open**.\n\n**Arguments:**\n\n- RequiredItems (meta-type[]):\n- AdditionalItems (?meta-type = M.Never): Type of additional items\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Tuple<[M.Primitive]>\n>;\n// => [string]\n\ntype Resolved = M.Resolve<\n M.Tuple<\n [M.Primitive],\n M.Primitive\n >\n>;\n// => [string, ...string[]]\n```\n\n> ☝️ A meta-tuple is [non-representable](#✨-meta-types) if one of its required items is non-representable\n\n### Object\n\nUsed for sets of key-value pairs (properties) which can be required or not.\n\nMeta-objects can have **additional properties**, typed as [`M.Never`](#never) by default. Thus, any meta-object is considered **closed** (additional properties not allowed), unless a representable additional properties meta-type is specified, in which case it becomes **open**.\n\nIn presence of named properties, open meta-objects additional properties are resolved as `unknown` to avoid conflicts. However, they are used as long as the meta-type is not resolved (especially in [intersections](#intersect) and [exclusions](#exclude)).\n\n**Arguments:**\n\n- NamedProperties (?{ [key:string]: meta-type } = {})\n- RequiredPropertiesKeys (?string union = never)\n- AdditionalProperties (?meta-type = M.Never): The type of additional properties\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Object<\n {\n required: M.Primitive;\n notRequired: M.Primitive;\n },\n \"required\",\n M.Primitive\n >\n>;\n// => {\n// req: string,\n// notRequired?: null,\n// [key: string]: unknown\n// }\n```\n\n> ☝️ A meta-object is [non-representable](#✨-meta-types) if one of its required properties value is non-representable:\n>\n> - If it is a non-representable named property\n> - If it is an additional property, and the object is closed\n\n### Union\n\nUsed to combine meta-types in a union of meta-types.\n\n**Arguments:**\n\n- Values (meta-type union)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Food = M.Resolve<\n M.Union<\n | M.Primitive\n | M.Enum<\"pizza\" | \"tacos\" | \"fries\">\n | M.Const\n >\n>;\n// => number\n// | \"pizza\" | \"tacos\" | \"fries\"\n// | true\n```\n\n> ☝️ A meta-union is [non-representable](#✨-meta-types) if it is empty, or if none of its elements is representable\n\n## 🔧 Methods\n\n### Resolve\n\nResolves the meta-type to its encapsulated type.\n\n**Arguments:**\n\n- MetaType (meta-type)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Primitive\n>;\n// => string\n```\n\n### Intersect\n\nTakes two meta-types as arguments, and returns their intersection as a meta-type.\n\n**Arguments:**\n\n- LeftMetaType (meta-type)\n- RightMetaType (meta-type)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Intersected = M.Intersect<\n M.Primitive,\n M.Enum<\"I love pizza\"\n | [\"tacos\"]\n | { and: \"fries\" }\n >\n>\n// => M.Enum<\"I love pizza\">\n```\n\nMeta-type intersections differ from conventional intersections:\n\n\n```typescript\ntype ConventionalIntersection =\n { str: string } & { num: number };\n// => { str: string, num: number }\n\ntype MetaIntersection = M.Intersect<\n M.Object<\n { str: M.Primitive },\n \"str\"\n >,\n M.Object<\n { num: M.Primitive },\n \"num\"\n >\n>;\n// => M.Never: \"num\" is required in B\n// ...but denied in A\n```\n\nIntersections are recursively propagated among tuple items and object properties, and take into account additional items and properties:\n\n\n```typescript\ntype Intersected = M.Intersect<\n M.Tuple<\n [M.Primitive],\n M.Primitive\n >,\n M.Tuple<\n [M.Enum<\"pizza\" | 42>],\n M.Enum<\"fries\" | true>\n >\n>;\n// => M.Tuple<\n// [M.Enum<42>],\n// M.Enum<\"fries\">\n// >\n\ntype Intersected = M.Intersect<\n M.Object<\n { food: M.Primitive },\n \"food\",\n M.Any\n >,\n M.Object<\n { age: M.Primitive },\n \"age\",\n M.Enum<\"pizza\" | \"fries\" | 42>\n >\n>;\n// => M.Object<\n// {\n// food: M.Enum<\"pizza\" | \"fries\">,\n// age: M.Primitive\n// },\n// \"food\" | \"age\",\n// M.Enum<\"pizza\" | \"fries\" | 42>\n// >\n```\n\nIntersections are distributed among unions:\n\n\n```typescript\ntype Intersected = M.Intersect<\n M.Primitive,\n M.Union<\n | M.Const<\"pizza\">\n | M.Const<42>\n >\n>;\n// => M.Union<\n// | M.Const<\"pizza\">\n// | M.Never\n// >\n```\n\n### Exclude\n\nTakes two meta-types as arguments, and returns their exclusion as a meta-type.\n\n**Arguments:**\n\n- SourceMetaType (meta-type)\n- ExcludedMetaType (meta-type)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Excluded = M.Exclude<\n M.Enum<\"I love pizza\"\n | [\"tacos\"]\n | { and: \"fries\" }\n >,\n M.Primitive,\n>\n// => M.Enum<\n// | [\"tacos\"]\n// | { and: \"fries\" }\n// >\n```\n\nMeta-type exclusions differ from conventional exclusions:\n\n\n```typescript\ntype ConventionalExclusion = Exclude<\n { req: string; notReq?: string },\n { req: string }\n>;\n// => never\n// ObjectA is assignable to ObjectB\n\ntype MetaExclusion = M.Exclude<\n M.Object<\n {\n req: M.Primitive;\n notReq: M.Primitive;\n },\n \"req\"\n >,\n M.Object<\n { req: M.Primitive },\n \"req\"\n >\n>;\n// => ObjectA\n// Exclusion is still representable\n```\n\n\n```typescript\ntype ConventionalExclusion = Exclude<\n { food: \"pizza\" | 42 },\n { [k: string]: number }\n>;\n// => { food: \"pizza\" | 42 }\n\ntype MetaExclusion = M.Exclude<\n M.Object<\n { food: M.Enum<\"pizza\" | 42> },\n \"food\"\n >,\n M.Object<\n {},\n never,\n M.Primitive\n >\n>;\n// => M.Object<\n// { food: M.Enum<\"pizza\"> },\n// \"food\"\n// >\n```\n\nWhen exclusions can be collapsed on a single item or property, they are recursively propagated among tuple items and object properties, taking into account additional items and properties:\n\n\n```typescript\ntype Excluded = M.Exclude<\n M.Tuple<[M.Enum<\"pizza\" | 42>]>,\n M.Tuple<[M.Primitive]>\n>;\n// => M.Tuple<[M.Enum<\"pizza\">]>\n\ntype Excluded = M.Exclude<\n M.Tuple<\n [M.Enum<\"pizza\" | 42>],\n M.Enum<\"fries\" | true>\n >,\n M.Tuple<\n [M.Primitive],\n M.Primitive\n >\n>;\n// => TupleA\n// Exclusion is not collapsable on a single item\n\ntype Excluded = M.Exclude<\n M.Object<\n {\n reqA: M.Enum<\"pizza\" | 42>;\n reqB: M.Enum<\"pizza\" | 42>;\n },\n \"reqA\" | \"reqB\"\n >,\n M.Object<\n {},\n never,\n M.Primitive\n >\n>;\n// => ObjectA\n// Exclusion is not collapsable on a single property\n```\n\nExclusions are distributed among unions:\n\n\n```typescript\ntype Excluded = M.Exclude<\n M.Union<\n | M.Const<\"pizza\">\n | M.Const<42>\n >,\n M.Primitive\n>;\n// => M.Union<\n// | M.Const<\"pizza\">\n// | M.Never\n// >\n```\n\nExluding a union returns the intersection of the exclusions of all elements, applied separately:\n\n\n```typescript\ntype Excluded = M.Exclude<\n M.Enum<42 | \"pizza\" | true>,\n M.Union<\n | M.Primitive\n | M.Primitive\n >\n>;\n// => M.Enum<\"pizza\">\n```\n\n## 🚧 Type constraints\n\nTo prevent errors, meta-types inputs are validated against type constraints:\n\n\n```typescript\ntype Invalid = M.Array<\n string // <= ❌ Meta-type expected\n>;\n```\n\nIf you need to use them, all type constraints are also exported:\n\n| Meta-type | Type constraint |\n| ------------- | :--------------------------------------------------------------------- |\n| `M.Any` | `M.AnyType` = `M.Any` |\n| `M.Never` | `M.NeverType` = `M.Never` |\n| `M.Const` | `M.ConstType` = `M.Const` |\n| `M.Enum` | `M.EnumType` = `M.Enum` |\n| `M.Primitive` | `M.PrimitiveType` = `M.Primitive` |\n| `M.Array` | `M.ArrayType` = `M.Array` |\n| `M.Tuple` | `M.TupleType` = `M.Tuple` |\n| `M.Object` | `M.ObjectType` = `M.Object, string, M.Type>` |\n| `M.Union` | `M.UnionType` = `M.Union` |\n| - | `M.Type` = Union of the above |\n\n## ✂️ Unsafe types and methods\n\nIn deep and self-referencing computations like in [json-schema-to-ts](https://github.com/ThomasAribart/json-schema-to-ts), type constraints can become an issue, as the compiler may not be able to confirm the input type validity ahead of usage.\n\n\n```typescript\ntype MyArray = M.Array<\n VeryDeepTypeComputation<\n ...\n > // <= 💥 Type constraint can break\n>\n```\n\nFor such cases, `ts-algebra` exposes **\"unsafe\"** types and methods, that behave the same as \"safe\" ones but removing any type constraints. If you use them, beware: The integrity of the compiling is up to you 😉\n\n| Safe | Unsafe |\n| ------------- | -------------- |\n| `M.Any` | - |\n| `M.Never` | - |\n| `M.Const` | - |\n| `M.Enum` | - |\n| `M.Primitive` | `M.$Primitive` |\n| `M.Array` | `M.$Array` |\n| `M.Tuple` | `M.$Tuple` |\n| `M.Object` | `M.$Object` |\n| `M.Union` | `M.$Union` |\n| `M.Resolve` | `M.$Resolve` |\n| `M.Intersect` | `M.$Intersect` |\n| `M.Exclude` | `M.$Exclude` |\n","readmeFilename":"README.md","gitHead":"e8567e5fd4574dfb20ea0a61d5812a7da491149f","_id":"ts-algebra@1.0.0-beta.3","_nodeVersion":"14.17.1","_npmVersion":"8.6.0","dist":{"integrity":"sha512-F98TLp/PyIajWfpTXPS8YuZkKxGzAdKtAa9zqvD994gsTD5oEvMx2xoXeE1FY5hDPFZ2simF5m3ZbO1sPk+HMA==","shasum":"8ef6b5d355892a95e7ef435d11fcc0da8503aa20","tarball":"https://registry.npmjs.org/ts-algebra/-/ts-algebra-1.0.0-beta.3.tgz","fileCount":47,"unpackedSize":716138,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGc/85VKZPooIvalNdgpPcRgAkqieIBalyhEDKsT345LAiEAnwpKRgDZ1AyJsv7I675ZS9QGY1v/r44oxmGFAyNpELw="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiTcb7ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmp+lw//RUpmJ8WxcO+zLukMFM5pAsawhAX2gfAjeGKrrg/k/heK3nMD\r\nIkI5p5vPJUpi5z8/fqUPgjX8yjfk3HgLhuDxP16YA1dLOJLTKwTFna/FJfRH\r\nvnPm0dxhTZMiVZwUL6dNPoXOnsavXPos3uwTY92cNs0juZRoQpgmM2d+TI97\r\nvWO2bOJWYs5bIr5dxTGqmfpbr50MHZS3lgnJ+C13nRJ+o2yvhP/gO17MY79M\r\nS7iaikauW2GPNUzgme2YcQllUU/jb+RoXcQwfF59ttTcgCCwEM4lWGsCTzPh\r\nv5NDxIpu3Gr/SkRY4nhd7Sp712hrIkiqVlMBogkCqO7kZIWyX3xIRy88rCGQ\r\n5BCfFkJJAcdzcJhIh+QSCPTTgZsSPXPkMcknF8XqNPYTdl7aicGuqCSuLh5v\r\nyi/ZCUl/SKDLn1AUTHO4uapp8nJhcxJPr2oPyAjjM0m626rLdIB9reIpRWIY\r\nqI6fSbgnWhXrYE4aTu0Gp9i6KL0FAOlpr0rPKhVvbO5bVm5wK/M+SVFgeN9r\r\nz71JfS7ZqY3roWOP6JpwAgN3X7utnPI/4PTjw4EO5zppzVhqmgiSWUHv4Epa\r\n2SWA6Py5xMyINlipdBPSQHTKea4rltJQHSCg1SvVVx+XsU6/E2HOWggmXrXR\r\n76CCm+7bOSCVR9/dNnOGK6At/MyAdGMz4Qg=\r\n=ULkG\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"thomasaribart","email":"thomas.aribart@gmail.com"},"directories":{},"maintainers":[{"name":"thomasaribart","email":"thomas.aribart@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ts-algebra_1.0.0-beta.3_1649264378807_0.5273103487381048"},"_hasShrinkwrap":false},"1.0.0":{"name":"ts-algebra","version":"1.0.0","description":"Types on steroids 💊","main":"lib/index.d.ts","scripts":{"release":"bash scripts/release.bash","test":"tsc --noEmit"},"dependencies":{"ts-toolbelt":"^9.6.0"},"devDependencies":{"rollup":"^2.67.3","rollup-plugin-dts":"4.1.0","rollup-plugin-import-map":"^2.2.2","typescript":"^4.5.5"},"author":{"name":"Thomas Aribart"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/ThomasAribart/ts-algebra.git"},"keywords":["typescript","type","ts"],"bugs":{"url":"https://github.com/ThomasAribart/ts-algebra/issues"},"homepage":"https://github.com/ThomasAribart/ts-algebra#readme","gitHead":"a1a9089c5d7658c4dd6e950d6a7f8fbaf5fc3054","_id":"ts-algebra@1.0.0","_nodeVersion":"14.17.1","_npmVersion":"8.6.0","dist":{"integrity":"sha512-mudi33x31CN5Zq7FlZk+JiHbpwqPeNY8hbOol19u29Dh4hSBZbRAKKQ3bNaRD9KFDTBylER9Uqt+il7oEYTnXQ==","shasum":"107f53618f57445146cfc94f02606fd32633f1ec","tarball":"https://registry.npmjs.org/ts-algebra/-/ts-algebra-1.0.0.tgz","fileCount":47,"unpackedSize":716131,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDQsctNJFUmaMBye5UxZ4D1wce4wqMpXfUvVHUz8KLCjgIhAJ8+jXFZP9q1bszGPJWGF3zyEHY9pkKBL4nT7Cc+QNju"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiTc7RACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmrudg//SHBIUL+TkR5cyOtDHF6xKoQxM3F7P94CdE9lKh4Ay5SYt637\r\nP4ZF7mAbkk8WHxT3U8aKvz3X3tCQFQiseR4xno8t2EGvN+GNUeCjHZCvJ5ep\r\nnCoFXBVbMdyqeBsktDXfYzlHtYIQEvy7pGcN/6DleX3ZpAvqbHyRw2g4nbVz\r\nJdqBOda/bSj1t6bybjsGxQ8qmPCuil7qAaKQEliWQE2V7zfr//ye2OS1k4pA\r\nFXVEK3qKoRCMdAjxFBIM+J1I5vXagtd5Q7+ZyIMxj3BG4f0EngEe+cJ9lHma\r\nR86zaHU99PpYKmU1meeleQlkbdR9nNMsibBZ+wTLI4p0P+pY4tYH3VQiA48Z\r\nPM25Uds96ia9Boq71k2/1o+ONGakV7rotRxLPAmZDj5nqT8L60F5LXIlm3tQ\r\neFCVX0URFQQvKOW1vwdCHDnSS0Lk2X7fI4l5SLq5NhliH88sl+88gXu4fsAV\r\nvpQIS9pxg7l5t7S/aM4gq1X/+pk7/ailLbP4FKDzXpJnnaBjIgva6jfGSk0J\r\n2NL3rA+Z2IB+CIK8p/4kDleWEyKWYG/NupelLTityrmJJu/XkMM2/rfEDurk\r\nFV85o3f3gZPYEcRehjZg3zoTdgBHIAFgNhGdoL0TBMe3bP1uYU1GQNrZI+3r\r\naXpmhgJUPFdGlALN9+lpPuT2NkLOKPQc6aM=\r\n=E/tx\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"thomasaribart","email":"thomas.aribart@gmail.com"},"directories":{},"maintainers":[{"name":"thomasaribart","email":"thomas.aribart@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ts-algebra_1.0.0_1649266385415_0.1418627196034401"},"_hasShrinkwrap":false},"1.0.1":{"name":"ts-algebra","version":"1.0.1","description":"Types on steroids 💊","main":"lib/index.d.ts","scripts":{"release":"bash scripts/release.bash","test":"tsc --noEmit"},"dependencies":{"ts-toolbelt":"^9.6.0"},"devDependencies":{"rollup":"^2.67.3","rollup-plugin-dts":"4.1.0","rollup-plugin-import-map":"^2.2.2","typescript":"^4.5.5"},"author":{"name":"Thomas Aribart"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/ThomasAribart/ts-algebra.git"},"keywords":["typescript","type","ts"],"bugs":{"url":"https://github.com/ThomasAribart/ts-algebra/issues"},"homepage":"https://github.com/ThomasAribart/ts-algebra#readme","gitHead":"1e51e0debfbdca208c3b7ef5b2297968532fdbf9","_id":"ts-algebra@1.0.1","_nodeVersion":"14.17.1","_npmVersion":"8.6.0","dist":{"integrity":"sha512-4AxsR+UtXCM808JQ+x9OoHfq7xajXbh+ODpDVjahFdkXjKY4237e6aQbQK9KXr3X97M8E7mXNYf9VkUYJ0RLpw==","shasum":"fb86115d26b039c761431d7abee83040410fa59b","tarball":"https://registry.npmjs.org/ts-algebra/-/ts-algebra-1.0.1.tgz","fileCount":47,"unpackedSize":716124,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCOTkfTgollxedDcSDPifpAvOBYWtVHSrjZ7EmpbxtBNwIgDGAPslabef5kjyR7kcicA0UbRTbUXVcZQwCh6Axc6qk="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiUIKfACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmpppw/+P07RzBEmuu9CBX5SS/7VGF+OnLj7keVj9LpmJ/TmHQDEPbzy\r\nHr3uRzQ7OAITX8xrSvkpN373fE5XUhc6A1jT9M3w2zOc7tcEr1hEEMCtd8E4\r\nCg6SeSdWBcS6sgL98Dqj89ipENT3LWnC1052KBGFwsxNwFF2CRnOrR4G72fp\r\nJr33YY510GB8AqbbdEu2l8NJhYr2MA/2EZkpZp0Kv72xPpB3UCD1QZylUzS4\r\nwQOMu+w4EdJcBPg0bLg8WK5l1vwXEFmlro2YKlEN2hbrjDYI3AcMRRcpKnXj\r\nXBYKQngcI0i7I2WmxQe3HywNtaVP550C5+AbEa9TqFXWq9qudwmeK1YCkPxU\r\nDfKQnsrT2Ely6F8Jco6nsMMC1/+nzHavPEcO8z0RFpcsGq3DOSSGPOuQVmbU\r\nPBOGoWZWMHRGFiw6JkmOL8LFcAflM772CTspEqqNdtL8msJq5kmW580WCyrk\r\nATewXlSaQD/nDI0mkpxdOobOhyWPJz6JlCS5Q4DpsEp9dHvR575jWq7Upuxy\r\n2SRrTOb/PXnnxqLjZ+D7shDkfy80YmfnhieVXxS5YRn81DpKn1SdJAkUTxu5\r\nqi6cMlcQcJsl09Lox6KghX3tJXfLCD21gfwosy/nBX7ppr29Yh9px8UaeSRH\r\nhPYzjWnAEGgn1Dd7u/z1tfZgt26F+VgyYQY=\r\n=Patj\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"thomasaribart","email":"thomas.aribart@gmail.com"},"directories":{},"maintainers":[{"name":"thomasaribart","email":"thomas.aribart@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ts-algebra_1.0.1_1649443487652_0.601299589123917"},"_hasShrinkwrap":false},"1.1.0-beta.0":{"name":"ts-algebra","version":"1.1.0-beta.0","description":"Types on steroids 💊","main":"lib/index.d.ts","scripts":{"release":"bash scripts/release.bash","test":"tsc --noEmit"},"dependencies":{"ts-toolbelt":"^9.6.0"},"devDependencies":{"rollup":"^2.67.3","rollup-plugin-dts":"4.1.0","rollup-plugin-import-map":"^2.2.2","typescript":"^4.5.5"},"author":{"name":"Thomas Aribart"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/ThomasAribart/ts-algebra.git"},"keywords":["typescript","type","ts"],"bugs":{"url":"https://github.com/ThomasAribart/ts-algebra/issues"},"homepage":"https://github.com/ThomasAribart/ts-algebra#readme","readme":"\n\n

\n If you use this repo, star it ✨\n

\n\n# Types on steroids 💊\n\n`ts-algebra` exposes a subset of TS types called **Meta-types**: Meta-types are types that encapsulate other types.\n\n```typescript\nimport { Meta } from \"ts-algebra\";\n\ntype MetaString = Meta.Primitive;\n```\n\nThe encapsulated type can be retrieved using the `Resolve` operation.\n\n```typescript\ntype Resolved = Meta.Resolve;\n// => string 🙌\n```\n\nYou can also use the more compact `M` notation:\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Primitive\n>;\n```\n\n## Okay, but... why ? 🤔\n\nMeta-types allow operations that **are not possible with conventional types**.\n\nFor instance, they allow new [\"intersect\"](#intersect) and [\"exclude\"](#exclude) operations, and handling objects additional properties:\n\n```typescript\ntype MyObject = {\n str: string; // <= ❌ \"str\" is assignable to string\n [key: string]: number;\n};\n\ntype MyObjectKeys = keyof MyObject;\n// => string <= ❌ Unable to isolate \"str\"\n```\n\nThink of meta-types as a parallel universe where all kinds of magic can happen 🌈 Once your computations are over, you can retrieve the results by resolving them.\n\n\n\n> Meta-types were originally part of [json-schema-to-ts](https://github.com/ThomasAribart/json-schema-to-ts). Check it to see a real-life usage.\n\n## Table of content\n\n- [Installation](#%EF%B8%8F-installation)\n- [Cardinality](#-cardinality)\n- [Meta-types](#-meta-types)\n - [Any](#any)\n - [Never](#never)\n - [Const](#const)\n - [Enum](#enum)\n - [Primitive](#primitive)\n - [Array](#array)\n - [Tuple](#tuple)\n - [Object](#object)\n - [Union](#union)\n- [Methods](#-methods)\n - [Resolve](#resolve)\n - [Intersect](#intersect)\n - [Exclude](#exclude)\n- [Type constraints](#-type-constraints)\n- [Unsafe types](#%EF%B8%8F-unsafe-types-and-methods)\n\n## ☁️ Installation\n\n```bash\n# npm\nnpm install --save-dev ts-algebra\n\n# yarn\nyarn add --dev ts-algebra\n```\n\n## 🧮 Cardinality\n\nA bit of theory first:\n\n- The [**cardinality**](https://en.wikipedia.org/wiki/Cardinality) of a type is the number of distinct values (potentially infinite) that can be assigned to it\n- A meta-type is said **representable** if at least one value can be assigned to its resolved type (cardinality ≥ 1)\n\nAn important notion to keep in mind using `ts-algebra`:\n\n---\n\n

\n M.Never is the only Meta-Type that is non-representable\n
\n (i.e. that resolves to never)\n

\n\n---\n\nAny other non-representable meta-type (e.g. an object with a non-representable but required property) will be instanciated as `M.Never`.\n\nThere are drawbacks to this choice (the said property is hard to find and debug) but stronger benefits: This drastically reduces type computations, in particular in [intersections](#intersect) and [exclusions](#exclude). This is crucial for performances and stability.\n\n## ✨ Meta-types\n\n### Any\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Any\n>;\n// => unknown\n```\n\n### Never\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Never\n>;\n// => never\n```\n\n### Const\n\nUsed for types with [cardinalities](#meta-types) of 1.\n\n**Arguments:**\n\n- Value (type)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Const<\"I love pizza\">\n>;\n// => \"I love pizza\"\n```\n\n### Enum\n\nUsed for types with finite [cardinalities](#meta-types).\n\n**Arguments:**\n\n- Values (type union)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Food = M.Resolve<\n M.Enum<\"pizza\" | \"tacos\" | \"fries\">\n>;\n// => \"pizza\" | \"tacos\" | \"fries\"\n```\n\n> ☝️ `M.Enum` is [non-representable](#✨-meta-types)\n\n### Primitive\n\nUsed for either `string`, `number`, `boolean` or `null`.\n\n**Arguments:**\n\n- Value (string | number | boolean | null)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Primitive\n>;\n// => string\n```\n\n### Array\n\nUsed for lists of items of the same type.\n\n**Arguments:**\n\n- Items (?meta-type = M.Any)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Array\n>;\n// => unknown[]\n\ntype Resolved = M.Resolve<\n M.Array>\n>;\n// => string[]\n```\n\n> ☝️ Any meta-array is representable by `[]`\n\n### Tuple\n\nUsed for finite, ordered lists of items of different types.\n\nMeta-tuples can have **additional items**, typed as [`M.Never`](#never) by default. Thus, any meta-tuple is considered **closed** (additional items not allowed), unless a representable additional items meta-type is specified, in which case it becomes **open**.\n\n**Arguments:**\n\n- RequiredItems (meta-type[]):\n- AdditionalItems (?meta-type = M.Never): Type of additional items\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Tuple<[M.Primitive]>\n>;\n// => [string]\n\ntype Resolved = M.Resolve<\n M.Tuple<\n [M.Primitive],\n M.Primitive\n >\n>;\n// => [string, ...string[]]\n```\n\n> ☝️ A meta-tuple is [non-representable](#✨-meta-types) if one of its required items is non-representable\n\n### Object\n\nUsed for sets of key-value pairs (properties) which can be required or not.\n\nMeta-objects can have **additional properties**, typed as [`M.Never`](#never) by default. Thus, any meta-object is considered **closed** (additional properties not allowed), unless a representable additional properties meta-type is specified, in which case it becomes **open**.\n\nIn presence of named properties, open meta-objects additional properties are resolved as `unknown` to avoid conflicts. However, they are used as long as the meta-type is not resolved (especially in [intersections](#intersect) and [exclusions](#exclude)).\n\n**Arguments:**\n\n- NamedProperties (?{ [key:string]: meta-type } = {})\n- RequiredPropertiesKeys (?string union = never)\n- AdditionalProperties (?meta-type = M.Never): The type of additional properties\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Object<\n {\n required: M.Primitive;\n notRequired: M.Primitive;\n },\n \"required\",\n M.Primitive\n >\n>;\n// => {\n// req: string,\n// notRequired?: null,\n// [key: string]: unknown\n// }\n```\n\n> ☝️ A meta-object is [non-representable](#✨-meta-types) if one of its required properties value is non-representable:\n>\n> - If it is a non-representable named property\n> - If it is an additional property, and the object is closed\n\n### Union\n\nUsed to combine meta-types in a union of meta-types.\n\n**Arguments:**\n\n- Values (meta-type union)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Food = M.Resolve<\n M.Union<\n | M.Primitive\n | M.Enum<\"pizza\" | \"tacos\" | \"fries\">\n | M.Const\n >\n>;\n// => number\n// | \"pizza\" | \"tacos\" | \"fries\"\n// | true\n```\n\n> ☝️ A meta-union is [non-representable](#✨-meta-types) if it is empty, or if none of its elements is representable\n\n## 🔧 Methods\n\n### Resolve\n\nResolves the meta-type to its encapsulated type.\n\n**Arguments:**\n\n- MetaType (meta-type)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Primitive\n>;\n// => string\n```\n\n### Intersect\n\nTakes two meta-types as arguments, and returns their intersection as a meta-type.\n\n**Arguments:**\n\n- LeftMetaType (meta-type)\n- RightMetaType (meta-type)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Intersected = M.Intersect<\n M.Primitive,\n M.Enum<\"I love pizza\"\n | [\"tacos\"]\n | { and: \"fries\" }\n >\n>\n// => M.Enum<\"I love pizza\">\n```\n\nMeta-type intersections differ from conventional intersections:\n\n\n```typescript\ntype ConventionalIntersection =\n { str: string } & { num: number };\n// => { str: string, num: number }\n\ntype MetaIntersection = M.Intersect<\n M.Object<\n { str: M.Primitive },\n \"str\"\n >,\n M.Object<\n { num: M.Primitive },\n \"num\"\n >\n>;\n// => M.Never: \"num\" is required in B\n// ...but denied in A\n```\n\nIntersections are recursively propagated among tuple items and object properties, and take into account additional items and properties:\n\n\n```typescript\ntype Intersected = M.Intersect<\n M.Tuple<\n [M.Primitive],\n M.Primitive\n >,\n M.Tuple<\n [M.Enum<\"pizza\" | 42>],\n M.Enum<\"fries\" | true>\n >\n>;\n// => M.Tuple<\n// [M.Enum<42>],\n// M.Enum<\"fries\">\n// >\n\ntype Intersected = M.Intersect<\n M.Object<\n { food: M.Primitive },\n \"food\",\n M.Any\n >,\n M.Object<\n { age: M.Primitive },\n \"age\",\n M.Enum<\"pizza\" | \"fries\" | 42>\n >\n>;\n// => M.Object<\n// {\n// food: M.Enum<\"pizza\" | \"fries\">,\n// age: M.Primitive\n// },\n// \"food\" | \"age\",\n// M.Enum<\"pizza\" | \"fries\" | 42>\n// >\n```\n\nIntersections are distributed among unions:\n\n\n```typescript\ntype Intersected = M.Intersect<\n M.Primitive,\n M.Union<\n | M.Const<\"pizza\">\n | M.Const<42>\n >\n>;\n// => M.Union<\n// | M.Const<\"pizza\">\n// | M.Never\n// >\n```\n\n### Exclude\n\nTakes two meta-types as arguments, and returns their exclusion as a meta-type.\n\n**Arguments:**\n\n- SourceMetaType (meta-type)\n- ExcludedMetaType (meta-type)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Excluded = M.Exclude<\n M.Enum<\"I love pizza\"\n | [\"tacos\"]\n | { and: \"fries\" }\n >,\n M.Primitive,\n>\n// => M.Enum<\n// | [\"tacos\"]\n// | { and: \"fries\" }\n// >\n```\n\nMeta-type exclusions differ from conventional exclusions:\n\n\n```typescript\ntype ConventionalExclusion = Exclude<\n { req: string; notReq?: string },\n { req: string }\n>;\n// => never\n// ObjectA is assignable to ObjectB\n\ntype MetaExclusion = M.Exclude<\n M.Object<\n {\n req: M.Primitive;\n notReq: M.Primitive;\n },\n \"req\"\n >,\n M.Object<\n { req: M.Primitive },\n \"req\"\n >\n>;\n// => ObjectA\n// Exclusion is still representable\n```\n\n\n```typescript\ntype ConventionalExclusion = Exclude<\n { food: \"pizza\" | 42 },\n { [k: string]: number }\n>;\n// => { food: \"pizza\" | 42 }\n\ntype MetaExclusion = M.Exclude<\n M.Object<\n { food: M.Enum<\"pizza\" | 42> },\n \"food\"\n >,\n M.Object<\n {},\n never,\n M.Primitive\n >\n>;\n// => M.Object<\n// { food: M.Enum<\"pizza\"> },\n// \"food\"\n// >\n```\n\nWhen exclusions can be collapsed on a single item or property, they are recursively propagated among tuple items and object properties, taking into account additional items and properties:\n\n\n```typescript\ntype Excluded = M.Exclude<\n M.Tuple<[M.Enum<\"pizza\" | 42>]>,\n M.Tuple<[M.Primitive]>\n>;\n// => M.Tuple<[M.Enum<\"pizza\">]>\n\ntype Excluded = M.Exclude<\n M.Tuple<\n [M.Enum<\"pizza\" | 42>],\n M.Enum<\"fries\" | true>\n >,\n M.Tuple<\n [M.Primitive],\n M.Primitive\n >\n>;\n// => TupleA\n// Exclusion is not collapsable on a single item\n\ntype Excluded = M.Exclude<\n M.Object<\n {\n reqA: M.Enum<\"pizza\" | 42>;\n reqB: M.Enum<\"pizza\" | 42>;\n },\n \"reqA\" | \"reqB\"\n >,\n M.Object<\n {},\n never,\n M.Primitive\n >\n>;\n// => ObjectA\n// Exclusion is not collapsable on a single property\n```\n\nExclusions are distributed among unions:\n\n\n```typescript\ntype Excluded = M.Exclude<\n M.Union<\n | M.Const<\"pizza\">\n | M.Const<42>\n >,\n M.Primitive\n>;\n// => M.Union<\n// | M.Const<\"pizza\">\n// | M.Never\n// >\n```\n\nExluding a union returns the intersection of the exclusions of all elements, applied separately:\n\n\n```typescript\ntype Excluded = M.Exclude<\n M.Enum<42 | \"pizza\" | true>,\n M.Union<\n | M.Primitive\n | M.Primitive\n >\n>;\n// => M.Enum<\"pizza\">\n```\n\n## 🚧 Type constraints\n\nTo prevent errors, meta-types inputs are validated against type constraints:\n\n\n```typescript\ntype Invalid = M.Array<\n string // <= ❌ Meta-type expected\n>;\n```\n\nIf you need to use them, all type constraints are also exported:\n\n| Meta-type | Type constraint |\n| ------------- | :--------------------------------------------------------------------- |\n| `M.Any` | `M.AnyType` = `M.Any` |\n| `M.Never` | `M.NeverType` = `M.Never` |\n| `M.Const` | `M.ConstType` = `M.Const` |\n| `M.Enum` | `M.EnumType` = `M.Enum` |\n| `M.Primitive` | `M.PrimitiveType` = `M.Primitive` |\n| `M.Array` | `M.ArrayType` = `M.Array` |\n| `M.Tuple` | `M.TupleType` = `M.Tuple` |\n| `M.Object` | `M.ObjectType` = `M.Object, string, M.Type>` |\n| `M.Union` | `M.UnionType` = `M.Union` |\n| - | `M.Type` = Union of the above |\n\n## ✂️ Unsafe types and methods\n\nIn deep and self-referencing computations like in [json-schema-to-ts](https://github.com/ThomasAribart/json-schema-to-ts), type constraints can become an issue, as the compiler may not be able to confirm the input type validity ahead of usage.\n\n\n```typescript\ntype MyArray = M.Array<\n VeryDeepTypeComputation<\n ...\n > // <= 💥 Type constraint can break\n>\n```\n\nFor such cases, `ts-algebra` exposes **\"unsafe\"** types and methods, that behave the same as \"safe\" ones but removing any type constraints. If you use them, beware: The integrity of the compiling is up to you 😉\n\n| Safe | Unsafe |\n| ------------- | -------------- |\n| `M.Any` | - |\n| `M.Never` | - |\n| `M.Const` | - |\n| `M.Enum` | - |\n| `M.Primitive` | `M.$Primitive` |\n| `M.Array` | `M.$Array` |\n| `M.Tuple` | `M.$Tuple` |\n| `M.Object` | `M.$Object` |\n| `M.Union` | `M.$Union` |\n| `M.Resolve` | `M.$Resolve` |\n| `M.Intersect` | `M.$Intersect` |\n| `M.Exclude` | `M.$Exclude` |\n","readmeFilename":"README.md","gitHead":"974a3e8db7db66566dac3de8b4a3dacaee350819","_id":"ts-algebra@1.1.0-beta.0","_nodeVersion":"16.6.2","_npmVersion":"7.20.3","dist":{"integrity":"sha512-YQ1AWVU4piEksMmdPz1+Zes2qrBr/2K172Lf9hcLYcgi3o7wqkD+gdyjTdjJw6hH5Lftbe0bWGXNkv1tDhQpAA==","shasum":"b71de986870de1899cad188d1d753f0fc859b74d","tarball":"https://registry.npmjs.org/ts-algebra/-/ts-algebra-1.1.0-beta.0.tgz","fileCount":50,"unpackedSize":724835,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEoRA4O2whBtNPCHbxJZIUWmDL8LquAjkni2AhoA8ByuAiEAiBQYFMTngh5aFd/NpM8hN1/479diZOzejiZCFaizgt4="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJibnbdACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrYhA/8CsvDeG4irk/aB58cok6K913pnfitg4Tl+yC8XFx3Zqe6xcYl\r\nmXNeWqQfiIJ4uPILHjXKjoISZeAI+eXixJOKdGjLmRDmsE4zff9N9DFVLhnY\r\nnk5L8tZTE/Q2xqDlL2t7taXyQa7WVJ8+qZuX/yqHEhTSYpMrUjt8MR2N3Ecq\r\nzHuwjF4DNjeU2LChlEA6ZiL77GyyKQvZZaxSxXEBm7pidhnX1P3BmH0tyQN1\r\ntsWVYcwSBLYuEMcMQ5oTC2G4jrOzci6nsFHLbH0MjLe5kENiCziq8YHZiBoi\r\nnLIHRenMEhTSMFvu6aRaY5hzrSLjSdSwHSwRruDjVSZkcoh5+qAh2AQUeenW\r\nj2VgaWpCMlrk5uNjPLc1UlupJl0SQRQIjQUkjyGSOyLbb6RPPlPwriPFhtfh\r\n+1ZnGDwmPqx6lq0Kf5iP5rVKD5nB+6YFP5mrHbySKn2qc5Fd+rxq9rLd98YQ\r\nFS7CDSSB9rmGgIDbknH/r9VWXYVJqcw1Huc7cPngw/TqoQqPQXQiMWIbuSI1\r\nTPbXbw3CDVMJx5MY5sPJ524GkNLB+KGGwefHHXS6mOXQX47fk8MBWFZvAXnc\r\nx8IsA7Ej25YxEd/29b0T8wZRHIjHh9W9lbUbccNU0qipvMNMeQIQfV2/bgzh\r\nnJwdPcUziOOluuiQISTqMvuZTEJZ9ZYjNsY=\r\n=99cI\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"thomasaribart","email":"thomas.aribart@gmail.com"},"directories":{},"maintainers":[{"name":"thomasaribart","email":"thomas.aribart@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ts-algebra_1.1.0-beta.0_1651406557085_0.5416294866692624"},"_hasShrinkwrap":false},"1.1.0":{"name":"ts-algebra","version":"1.1.0","description":"Types on steroids 💊","main":"lib/index.d.ts","scripts":{"release":"bash scripts/release.bash","test":"tsc --noEmit"},"dependencies":{"ts-toolbelt":"^9.6.0"},"devDependencies":{"rollup":"^2.67.3","rollup-plugin-dts":"4.1.0","rollup-plugin-import-map":"^2.2.2","typescript":"^4.5.5"},"author":{"name":"Thomas Aribart"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/ThomasAribart/ts-algebra.git"},"keywords":["typescript","type","ts"],"bugs":{"url":"https://github.com/ThomasAribart/ts-algebra/issues"},"homepage":"https://github.com/ThomasAribart/ts-algebra#readme","gitHead":"b0da311c27de2652f133c404fe6e251c2eefd1bc","_id":"ts-algebra@1.1.0","_nodeVersion":"16.6.2","_npmVersion":"7.20.3","dist":{"integrity":"sha512-9YoZkbsEa8+QYKdp8+77DUTzx1OWU847oAkKJKEf5b18rpCe6jO75YLlpIcZHVRUaQQXKoJoc2VN6/hVdSzRgw==","shasum":"046da335259ea06bc4f433b1acad5da25fe298d4","tarball":"https://registry.npmjs.org/ts-algebra/-/ts-algebra-1.1.0.tgz","fileCount":50,"unpackedSize":728401,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCTeD3ZOX9vt3wKBMdqKIFzgzSyGKZK0NOKdNfTmR0vnAIhAPdp9m/NNfxfVYEohvUBuj/Jue6wnMqKchk3Bb/cpa7o"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJibrkaACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoPQg/+NrkY2F1e9dDONOIpk7is4Y/Qj8/xYEFzTbvl53ZnWRo/oBNt\r\nalSmd8UDKrWlSEHuCFBu1jAXgXaDVDfglrGGN9Iv0AIaFHnWMaAdggdng/p+\r\nCetveCcYkWMMKBvcsuI68hzC9u0RARqRvgUnH34SM0dm8LNq6Kl/Cj5sdtvt\r\nYZ59R+L/09JxPt5WG/LcUJAy/sCdSP17euajLsd59Rg2TKVXs5C/tU1PfZ0q\r\nfmD6S+uA/UerMGHmiAA/Lpa3dL+V+nEtKyDgTWfhwGjyB441qCtOXuoU8o7u\r\n6EYOn4v8QOEYNiCU+ywCB3aY93QhxngcqAIokAZQBr1aZlVFVhFxy6Ex65Pb\r\nW+ctlJRj+fFD31oLA/Mb52C/AgZoJEYU5jw/Iu2N3gMKk0hVgdpwUh/NxrTf\r\nu+O7e9aQrMXx19g6t8Wh44j9F17zHRRykBbU42XMdRaTYVYPvZ7fnwKPyXvc\r\na/0TSmDypYlXLseEffMVXzmjhtRJbQtAAPTPYTdfof7DDMigpUM+qUWo5tuS\r\ny6/FNeM7TMLiogl0LSq/VDvXvc7dPl7whaxccybaGAhDqaS+7qDGSrEK8u+L\r\nPyg9vAHqKTEzZ9Ci5SL2HMRI0saZ6Z0CX8MO10z0DAQZu5UTnlHgb7kuFyRi\r\nTFC0ohnHqid/s14T2Xs/UaPT5E5uOpR3tkQ=\r\n=RGjD\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"thomasaribart","email":"thomas.aribart@gmail.com"},"directories":{},"maintainers":[{"name":"thomasaribart","email":"thomas.aribart@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ts-algebra_1.1.0_1651423513802_0.16514716056734646"},"_hasShrinkwrap":false},"1.1.1-beta.0":{"name":"ts-algebra","version":"1.1.1-beta.0","description":"Types on steroids 💊","main":"lib/index.js","module":"lib/index.js","types":"lib/index.d.ts","scripts":{"release":"bash scripts/release.bash","test":"tsc --noEmit","build":"tsc -p tsconfig.build.json"},"dependencies":{"ts-toolbelt":"^9.6.0"},"devDependencies":{"rollup":"^2.67.3","rollup-plugin-dts":"4.1.0","rollup-plugin-import-map":"^2.2.2","typescript":"^4.5.5"},"author":{"name":"Thomas Aribart"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/ThomasAribart/ts-algebra.git"},"keywords":["typescript","type","ts"],"bugs":{"url":"https://github.com/ThomasAribart/ts-algebra/issues"},"homepage":"https://github.com/ThomasAribart/ts-algebra#readme","readme":"\n\n

\n If you use this repo, star it ✨\n

\n\n# Types on steroids 💊\n\n`ts-algebra` exposes a subset of TS types called **Meta-types**: Meta-types are types that encapsulate other types.\n\n```typescript\nimport { Meta } from \"ts-algebra\";\n\ntype MetaString = Meta.Primitive;\n```\n\nThe encapsulated type can be retrieved using the `Resolve` operation.\n\n```typescript\ntype Resolved = Meta.Resolve;\n// => string 🙌\n```\n\nYou can also use the more compact `M` notation:\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Primitive\n>;\n```\n\n## Okay, but... why ? 🤔\n\nMeta-types allow operations that **are not possible with conventional types**.\n\nFor instance, they allow new [\"intersect\"](#intersect) and [\"exclude\"](#exclude) operations, and handling objects additional properties:\n\n```typescript\ntype MyObject = {\n str: string; // <= ❌ \"str\" is assignable to string\n [key: string]: number;\n};\n\ntype MyObjectKeys = keyof MyObject;\n// => string <= ❌ Unable to isolate \"str\"\n```\n\nThink of meta-types as a parallel universe where all kinds of magic can happen 🌈 Once your computations are over, you can retrieve the results by resolving them.\n\n\n\n> Meta-types were originally part of [json-schema-to-ts](https://github.com/ThomasAribart/json-schema-to-ts). Check it to see a real-life usage.\n\n## Table of content\n\n- [Installation](#%EF%B8%8F-installation)\n- [Cardinality](#-cardinality)\n- [Meta-types](#-meta-types)\n - [Never](#never)\n - [Any](#any)\n - [Const](#const)\n - [Enum](#enum)\n - [Primitive](#primitive)\n - [Array](#array)\n - [Tuple](#tuple)\n - [Object](#object)\n - [Union](#union)\n- [Methods](#-methods)\n - [Resolve](#resolve)\n - [Intersect](#intersect)\n - [Exclude](#exclude)\n- [Deserialization](#-deserialization)\n- [Type constraints](#-type-constraints)\n- [Unsafe types](#%EF%B8%8F-unsafe-types-and-methods)\n\n## ☁️ Installation\n\n```bash\n# npm\nnpm install --save-dev ts-algebra\n\n# yarn\nyarn add --dev ts-algebra\n```\n\n## 🧮 Cardinality\n\nA bit of theory first:\n\n- The [**cardinality**](https://en.wikipedia.org/wiki/Cardinality) of a type is the number of distinct values (potentially infinite) that can be assigned to it\n- A meta-type is said **representable** if at least one value can be assigned to its resolved type (cardinality ≥ 1)\n\nAn important notion to keep in mind using `ts-algebra`:\n\n---\n\n

\n M.Never is the only Meta-Type that is non-representable\n
\n (i.e. that resolves to never)\n

\n\n---\n\nAny other non-representable meta-type (e.g. an object with a non-representable but required property) will be instanciated as `M.Never`.\n\nThere are drawbacks to this choice (the said property is hard to find and debug) but stronger benefits: This drastically reduces type computations, in particular in [intersections](#intersect) and [exclusions](#exclude). This is crucial for performances and stability.\n\n## ✨ Meta-types\n\n### Never\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Never\n>;\n// => never\n```\n\n### Any\n\n**Arguments:**\n\n- IsSerialized (?boolean = false): See [deserialization](#-deserialization)\n- Deserialized (?type = never): See [deserialization](#-deserialization)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Any\n>;\n// => unknown\n```\n\n### Const\n\nUsed for types with [cardinalities](#meta-types) of 1.\n\n**Arguments:**\n\n- Value (type)\n- IsSerialized (?boolean = false): See [deserialization](#-deserialization)\n- Deserialized (?type = never): See [deserialization](#-deserialization)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Const<\"I love pizza\">\n>;\n// => \"I love pizza\"\n```\n\n### Enum\n\nUsed for types with finite [cardinalities](#meta-types).\n\n**Arguments:**\n\n- Values (type union)\n- IsSerialized (?boolean = false): See [deserialization](#-deserialization)\n- Deserialized (?type = never): See [deserialization](#-deserialization)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Food = M.Resolve<\n M.Enum<\"pizza\" | \"tacos\" | \"fries\">\n>;\n// => \"pizza\" | \"tacos\" | \"fries\"\n```\n\n> ☝️ `M.Enum` is [non-representable](#✨-meta-types)\n\n### Primitive\n\nUsed for either `string`, `number`, `boolean` or `null`.\n\n**Arguments:**\n\n- Value (string | number | boolean | null)\n- IsSerialized (?boolean = false): See [deserialization](#-deserialization)\n- Deserialized (?type = never): See [deserialization](#-deserialization)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Primitive\n>;\n// => string\n```\n\n### Array\n\nUsed for lists of items of the same type.\n\n**Arguments:**\n\n- Items (?meta-type = M.Any)\n- IsSerialized (?boolean = false): See [deserialization](#-deserialization)\n- Deserialized (?type = never): See [deserialization](#-deserialization)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Array\n>;\n// => unknown[]\n\ntype Resolved = M.Resolve<\n M.Array>\n>;\n// => string[]\n```\n\n> ☝️ Any meta-array is representable by `[]`\n\n### Tuple\n\nUsed for finite, ordered lists of items of different types.\n\nMeta-tuples can have **additional items**, typed as [`M.Never`](#never) by default. Thus, any meta-tuple is considered **closed** (additional items not allowed), unless a representable additional items meta-type is specified, in which case it becomes **open**.\n\n**Arguments:**\n\n- RequiredItems (meta-type[]):\n- AdditionalItems (?meta-type = M.Never): Type of additional items\n- IsSerialized (?boolean = false): See [deserialization](#-deserialization)\n- Deserialized (?type = never): See [deserialization](#-deserialization)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Tuple<[M.Primitive]>\n>;\n// => [string]\n\ntype Resolved = M.Resolve<\n M.Tuple<\n [M.Primitive],\n M.Primitive\n >\n>;\n// => [string, ...string[]]\n```\n\n> ☝️ A meta-tuple is [non-representable](#✨-meta-types) if one of its required items is non-representable\n\n### Object\n\nUsed for sets of key-value pairs (properties) which can be required or not.\n\nMeta-objects can have **additional properties**, typed as [`M.Never`](#never) by default. Thus, any meta-object is considered **closed** (additional properties not allowed), unless a representable additional properties meta-type is specified, in which case it becomes **open**.\n\nIn presence of named properties, open meta-objects additional properties are resolved as `unknown` to avoid conflicts. However, they are used as long as the meta-type is not resolved (especially in [intersections](#intersect) and [exclusions](#exclude)).\n\n**Arguments:**\n\n- NamedProperties (?{ [key:string]: meta-type } = {})\n- RequiredPropertiesKeys (?string union = never)\n- AdditionalProperties (?meta-type = M.Never): The type of additional properties\n- IsSerialized (?boolean = false): See [deserialization](#-deserialization)\n- Deserialized (?type = never): See [deserialization](#-deserialization)\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Object<\n {\n required: M.Primitive;\n notRequired: M.Primitive;\n },\n \"required\",\n M.Primitive\n >\n>;\n// => {\n// req: string,\n// notRequired?: null,\n// [key: string]: unknown\n// }\n```\n\n> ☝️ A meta-object is [non-representable](#✨-meta-types) if one of its required properties value is non-representable:\n>\n> - If it is a non-representable named property\n> - If it is an additional property, and the object is closed\n\n### Union\n\nUsed to combine meta-types in a union of meta-types.\n\n**Arguments:**\n\n- Values (meta-type union)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Food = M.Resolve<\n M.Union<\n | M.Primitive\n | M.Enum<\"pizza\" | \"tacos\" | \"fries\">\n | M.Const\n >\n>;\n// => number\n// | \"pizza\" | \"tacos\" | \"fries\"\n// | true\n```\n\n> ☝️ A meta-union is [non-representable](#✨-meta-types) if it is empty, or if none of its elements is representable\n\n> ☝️ Along with [M.Never](#never), M.Union is the only meta-type that doesn't support [serialization](#-deserialization)\n\n## 🔧 Methods\n\n### Resolve\n\nResolves the meta-type to its encapsulated type.\n\n**Arguments:**\n\n- MetaType (meta-type)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Primitive\n>;\n// => string\n```\n\n### Intersect\n\nTakes two meta-types as arguments, and returns their intersection as a meta-type.\n\n**Arguments:**\n\n- LeftMetaType (meta-type)\n- RightMetaType (meta-type)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Intersected = M.Intersect<\n M.Primitive,\n M.Enum<\"I love pizza\"\n | [\"tacos\"]\n | { and: \"fries\" }\n >\n>\n// => M.Enum<\"I love pizza\">\n```\n\nMeta-type intersections differ from conventional intersections:\n\n\n```typescript\ntype ConventionalIntersection =\n { str: string } & { num: number };\n// => { str: string, num: number }\n\ntype MetaIntersection = M.Intersect<\n M.Object<\n { str: M.Primitive },\n \"str\"\n >,\n M.Object<\n { num: M.Primitive },\n \"num\"\n >\n>;\n// => M.Never: \"num\" is required in B\n// ...but denied in A\n```\n\nIntersections are recursively propagated among tuple items and object properties, and take into account additional items and properties:\n\n\n```typescript\ntype Intersected = M.Intersect<\n M.Tuple<\n [M.Primitive],\n M.Primitive\n >,\n M.Tuple<\n [M.Enum<\"pizza\" | 42>],\n M.Enum<\"fries\" | true>\n >\n>;\n// => M.Tuple<\n// [M.Enum<42>],\n// M.Enum<\"fries\">\n// >\n\ntype Intersected = M.Intersect<\n M.Object<\n { food: M.Primitive },\n \"food\",\n M.Any\n >,\n M.Object<\n { age: M.Primitive },\n \"age\",\n M.Enum<\"pizza\" | \"fries\" | 42>\n >\n>;\n// => M.Object<\n// {\n// food: M.Enum<\"pizza\" | \"fries\">,\n// age: M.Primitive\n// },\n// \"food\" | \"age\",\n// M.Enum<\"pizza\" | \"fries\" | 42>\n// >\n```\n\nIntersections are distributed among unions:\n\n\n```typescript\ntype Intersected = M.Intersect<\n M.Primitive,\n M.Union<\n | M.Const<\"pizza\">\n | M.Const<42>\n >\n>;\n// => M.Union<\n// | M.Const<\"pizza\">\n// | M.Never\n// >\n```\n\n### Exclude\n\nTakes two meta-types as arguments, and returns their exclusion as a meta-type.\n\n**Arguments:**\n\n- OriginMetaType (meta-type)\n- SubstractedMetaType (meta-type)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Excluded = M.Exclude<\n M.Enum<\"I love pizza\"\n | [\"tacos\"]\n | { and: \"fries\" }\n >,\n M.Primitive,\n>\n// => M.Enum<\n// | [\"tacos\"]\n// | { and: \"fries\" }\n// >\n```\n\nMeta-type exclusions differ from conventional exclusions:\n\n\n```typescript\ntype ConventionalExclusion = Exclude<\n { req: string; notReq?: string },\n { req: string }\n>;\n// => never\n// ObjectA is assignable to ObjectB\n\ntype MetaExclusion = M.Exclude<\n M.Object<\n {\n req: M.Primitive;\n notReq: M.Primitive;\n },\n \"req\"\n >,\n M.Object<\n { req: M.Primitive },\n \"req\"\n >\n>;\n// => ObjectA\n// Exclusion is still representable\n```\n\n\n```typescript\ntype ConventionalExclusion = Exclude<\n { food: \"pizza\" | 42 },\n { [k: string]: number }\n>;\n// => { food: \"pizza\" | 42 }\n\ntype MetaExclusion = M.Exclude<\n M.Object<\n { food: M.Enum<\"pizza\" | 42> },\n \"food\"\n >,\n M.Object<\n {},\n never,\n M.Primitive\n >\n>;\n// => M.Object<\n// { food: M.Enum<\"pizza\"> },\n// \"food\"\n// >\n```\n\nWhen exclusions can be collapsed on a single item or property, they are recursively propagated among tuple items and object properties, taking into account additional items and properties:\n\n\n```typescript\ntype Excluded = M.Exclude<\n M.Tuple<[M.Enum<\"pizza\" | 42>]>,\n M.Tuple<[M.Primitive]>\n>;\n// => M.Tuple<[M.Enum<\"pizza\">]>\n\ntype Excluded = M.Exclude<\n M.Tuple<\n [M.Enum<\"pizza\" | 42>],\n M.Enum<\"fries\" | true>\n >,\n M.Tuple<\n [M.Primitive],\n M.Primitive\n >\n>;\n// => TupleA\n// Exclusion is not collapsable on a single item\n\ntype Excluded = M.Exclude<\n M.Object<\n {\n reqA: M.Enum<\"pizza\" | 42>;\n reqB: M.Enum<\"pizza\" | 42>;\n },\n \"reqA\" | \"reqB\"\n >,\n M.Object<\n {},\n never,\n M.Primitive\n >\n>;\n// => ObjectA\n// Exclusion is not collapsable on a single property\n```\n\nExclusions are distributed among unions:\n\n\n```typescript\ntype Excluded = M.Exclude<\n M.Union<\n | M.Const<\"pizza\">\n | M.Const<42>\n >,\n M.Primitive\n>;\n// => M.Union<\n// | M.Const<\"pizza\">\n// | M.Never\n// >\n```\n\nExluding a union returns the intersection of the exclusions of all elements, applied separately:\n\n\n```typescript\ntype Excluded = M.Exclude<\n M.Enum<42 | \"pizza\" | true>,\n M.Union<\n | M.Primitive\n | M.Primitive\n >\n>;\n// => M.Enum<\"pizza\">\n```\n\n## 📦 Deserialization\n\nAll meta-types except [`M.Never`](#never) and [`M.Union`](#union) can carry an extra type for [deserialization](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html) purposes. This extra-type will be passed along in operations and override the resolved type.\n\nFor instance, it is common to deserialize timestamps as `Date` objects. The last two arguments of [`M.Primitive`](#primitive) can be used to implement this:\n\n\n```typescript\ntype MetaTimestamp = M.Primitive<\n string,\n true, // <= enables deserialization (false by default)\n Date // <= overrides resolved type\n>;\n\ntype Resolved = M.Resolve;\n// => Date\n```\n\nNote that `MetaTimestamp` will still be considered as a string meta-type until it is resolved: Deserialization only take effect **at resolution time**.\n\n\n```typescript\ntype Intersected = M.Intersect<\n MetaTimestamp,\n M.Object<{}, never, M.Any> // <= Date is an object...\n>;\n// => M.Never\n// ...but doesn't intersect Timestamp\n```\n\nIn representable [intersections](#intersect):\n\n- If no meta-type is serialized, the resulting intersection is not serialized.\n- If only one meta-type (left or right) is serialized, the resulting intersection inherits from its deserialization properties.\n- If both left and right meta-types are serialized, the resulting intersection inherits from both deserialization properties, through a conventional intersection (`A & B`).\n\n\n```typescript\ntype MetaBrandedString = M.Primitive<\n string,\n true,\n { brand: \"timestamp\" }\n>;\n\ntype Resolved = M.Resolve<\n M.Intersect<\n MetaTimestamp,\n MetaBrandedString\n >\n>\n// => Date & { brand: \"timestamp\" }\n```\n\nIn representable [exclusions](#exclude):\n\n- If the origin meta-type is not serialized, the resulting exclusion is not serialized.\n- If the origin meta-type is serialized, the resulting exclusion inherits of its deserialization properties.\n\n## 🚧 Type constraints\n\nTo prevent errors, meta-types inputs are validated against type constraints:\n\n\n```typescript\ntype Invalid = M.Array<\n string // <= ❌ Meta-type expected\n>;\n```\n\nIf you need to use them, all type constraints are also exported:\n\n| Meta-type | Type constraint |\n| ------------- | :--------------------------------------------------------------------- |\n| `M.Any` | `M.AnyType` = `M.Any` |\n| `M.Never` | `M.NeverType` = `M.Never` |\n| `M.Const` | `M.ConstType` = `M.Const` |\n| `M.Enum` | `M.EnumType` = `M.Enum` |\n| `M.Primitive` | `M.PrimitiveType` = `M.Primitive` |\n| `M.Array` | `M.ArrayType` = `M.Array` |\n| `M.Tuple` | `M.TupleType` = `M.Tuple` |\n| `M.Object` | `M.ObjectType` = `M.Object, string, M.Type>` |\n| `M.Union` | `M.UnionType` = `M.Union` |\n| - | `M.Type` = Union of the above |\n\n## ✂️ Unsafe types and methods\n\nIn deep and self-referencing computations like in [json-schema-to-ts](https://github.com/ThomasAribart/json-schema-to-ts), type constraints can become an issue, as the compiler may not be able to confirm the input type validity ahead of usage.\n\n\n```typescript\ntype MyArray = M.Array<\n VeryDeepTypeComputation<\n ...\n > // <= 💥 Type constraint can break\n>\n```\n\nFor such cases, `ts-algebra` exposes **\"unsafe\"** types and methods, that behave the same as \"safe\" ones but removing any type constraints. If you use them, beware: The integrity of the compiling is up to you 😉\n\n| Safe | Unsafe |\n| ------------- | -------------- |\n| `M.Any` | - |\n| `M.Never` | - |\n| `M.Const` | - |\n| `M.Enum` | - |\n| `M.Primitive` | `M.$Primitive` |\n| `M.Array` | `M.$Array` |\n| `M.Tuple` | `M.$Tuple` |\n| `M.Object` | `M.$Object` |\n| `M.Union` | `M.$Union` |\n| `M.Resolve` | `M.$Resolve` |\n| `M.Intersect` | `M.$Intersect` |\n| `M.Exclude` | `M.$Exclude` |\n","readmeFilename":"README.md","gitHead":"56f0ca47e17344ba7df8c182a53fcae8180e787b","_id":"ts-algebra@1.1.1-beta.0","_nodeVersion":"16.6.2","_npmVersion":"7.20.3","dist":{"integrity":"sha512-piOyjq4A/B/kn2r08swv/DOf30MjXeihrT0AWXMfHqB3z5ogaut0i3bnCzmjChN2s74h4v9E0yHPayxFOFHXTg==","shasum":"c0b1586d76d420f9a2ac464fe2c24c0d2ba5e5fa","tarball":"https://registry.npmjs.org/ts-algebra/-/ts-algebra-1.1.1-beta.0.tgz","fileCount":89,"unpackedSize":74203,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCsqsO1y7kpKCQ8O+CwcUzBhkLBZsLO1tIR40eHDE1SqAIgBUWINkI47ZRTz1O2OK0fbx29klq1K1yA982z4yU/TK8="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJibr+lACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqAhw/8DFHorzU5iF/u7rJ2dLwS8YE408sopOqnKFa758YOvGw4UuhY\r\nI82hw6GC726diYX06LLGZbb0NluRC2TLHEwi57geTlrCd2DCPE4DNhNqQvL0\r\n5z641FngdfUm6KGFP31XtMh7wAjEs2oB6NYXVo1rRn8QA0bWGbFfWexB4BsU\r\n97CQopJ4m5m4sJE+M++P2NqYq3G01GPXxRnrN1XDodotZGItC4mVz/0HqB00\r\nq8g5rZS9d3uuKZXtDGoX2vK9mOin583v2HCFObl/nUNkV0vKTov1WVyz9V8X\r\nK7yHFM9HGV6ufHdHDr6VbxfDQCt1JSrhOX2bE2l+n6Mlb+/Ek6wwPqSaU7aO\r\n819S1bjkTPt48TJWkvQdwpCUy7DF6ZqGfkcgPVNbTYye+LewmuaXsFL5o1EN\r\nY28h56SzdKe+WUdnXlqVtbUAnsDROcybZICXRRD7qU0Vgc1BKYpjAu8RamOk\r\n2t5+vNQXiCNIRbChX2x6xWx+XNFEnu3b5Z9N2D/5KW4miPzbAlnZ9q12syS4\r\nTmdPXzPJBzAOyVcGvjkkEh8bMhUINQQq754Ne2PY5+VEsA9Fm1Xb0H0oRU+G\r\nDKDmgwXmjuYJRTsR1DXv01b57RFXFIEnRqnUHO3JN9TDrCd7xzhrne3mtiCf\r\nL4d97FrPhKZtyl1UsoF2mSjani3Zhbb83d8=\r\n=v/jW\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"thomasaribart","email":"thomas.aribart@gmail.com"},"directories":{},"maintainers":[{"name":"thomasaribart","email":"thomas.aribart@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ts-algebra_1.1.1-beta.0_1651425189371_0.861167566082049"},"_hasShrinkwrap":false},"1.1.1":{"name":"ts-algebra","version":"1.1.1","description":"Types on steroids 💊","main":"lib/index.js","module":"lib/index.js","types":"lib/index.d.ts","scripts":{"release":"bash scripts/release.bash","test":"tsc --noEmit","build":"tsc -p tsconfig.build.json"},"dependencies":{"ts-toolbelt":"^9.6.0"},"devDependencies":{"rollup":"^2.67.3","rollup-plugin-dts":"4.1.0","rollup-plugin-import-map":"^2.2.2","typescript":"^4.5.5"},"author":{"name":"Thomas Aribart"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/ThomasAribart/ts-algebra.git"},"keywords":["typescript","type","ts"],"bugs":{"url":"https://github.com/ThomasAribart/ts-algebra/issues"},"homepage":"https://github.com/ThomasAribart/ts-algebra#readme","gitHead":"e627a4748ed1f23f799f18d44c2b855ededb7479","_id":"ts-algebra@1.1.1","_nodeVersion":"16.6.2","_npmVersion":"7.20.3","dist":{"integrity":"sha512-W43a3/BN0Tp4SgRNERQF/QPVuY1rnHkgCr/fISLY0Ycu05P0NWPYRuViU8JFn+pFZuY6/zp9TgET1fxMzppR/Q==","shasum":"f7593cabcfd64f9d7211fa4f16ea9719e02461bc","tarball":"https://registry.npmjs.org/ts-algebra/-/ts-algebra-1.1.1.tgz","fileCount":89,"unpackedSize":74196,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC+WGCWjTpPiCRPIBcin6R9qQVM77wwuZnmdqkan700yAIgUYZFyLUqcNfrowidcGhNwxORSY5Emgx8J1CPxXKU4QI="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJibsBVACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrLMA//dlOXIToTZpupDY+ssoV/urMXNwBj2tjH0oV/MI19IDnuNl/6\r\nUw4XIQrq3+k6Y81punpaubdZ+Cl4nIKBYOr/j3YAJnDNG2NZOpfb8aIs0I/o\r\nA1DkqqLol5YDEdy7L9AXbY1l/SuwuAoZiIHdrq6N9sQjB4wVt3FyKwRq+yJu\r\nrqw/Otn/NL7MOU7ba0ZneQfkoNCfOs3jr9Nqj9qkuGUSNQpL882QovGruiJn\r\nvTC9pq5L+wQmU/Dwf/xSrdBFysRvC3k8PlLOJ+qJConKzfjmBAfV5JO9rspI\r\nxJODMHJEMy5JLjFqLd5g6g6nqVx1ZUpYF4iqlSAIGcRN5AEeir+kqml3iops\r\nfHmCHBxD3BWJw6z4qqZXLpy3He1d5JLmemibOc+FEveZYZkdvMoUPpI/NHiR\r\n2qIN6iPrVZXdy2p7P5oH/VhwMPQpmWvvYVbeMo8N0tP73ncVqc6ci+hyP48u\r\nsRUQzdtUHojvv0AEC0sfL5y+VdnVKxvtZS01Jd4cCJtUJBlPdt9FFkgcY6Uv\r\nhWTkrs95hymG5eqP9u5cqrlXhr5mrYotg7PJRm04sWO7d/LWlCZQCHd5my0M\r\nXnmmEcPEDxzpbvJ9RGn2IawcZHgyGxHphk+C7rwO9LBxajbvKW1OST6cx61B\r\nNx+OHq5BiSx4fbc/YMgfdnqF5WcuYvFFQGo=\r\n=Ooso\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"thomasaribart","email":"thomas.aribart@gmail.com"},"directories":{},"maintainers":[{"name":"thomasaribart","email":"thomas.aribart@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ts-algebra_1.1.1_1651425364895_0.24035978598927432"},"_hasShrinkwrap":false},"1.2.0-beta.0":{"name":"ts-algebra","version":"1.2.0-beta.0","description":"Types on steroids 💊","main":"lib/index.js","module":"lib/index.js","types":"lib/index.d.ts","scripts":{"release":"bash scripts/release.bash","test":"tsc --noEmit","build":"tsc -p tsconfig.build.json"},"dependencies":{},"devDependencies":{"rollup":"^2.67.3","rollup-plugin-dts":"4.1.0","rollup-plugin-import-map":"^2.2.2","typescript":"^4.5.5","ts-toolbelt":"^9.6.0"},"author":{"name":"Thomas Aribart"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/ThomasAribart/ts-algebra.git"},"keywords":["typescript","type","ts"],"bugs":{"url":"https://github.com/ThomasAribart/ts-algebra/issues"},"homepage":"https://github.com/ThomasAribart/ts-algebra#readme","readme":"\n\n

\n If you use this repo, star it ✨\n

\n\n# Types on steroids 💊\n\n`ts-algebra` exposes a subset of TS types called **Meta-types**: Meta-types are types that encapsulate other types.\n\n```typescript\nimport { Meta } from \"ts-algebra\";\n\ntype MetaString = Meta.Primitive;\n```\n\nThe encapsulated type can be retrieved using the `Resolve` operation.\n\n```typescript\ntype Resolved = Meta.Resolve;\n// => string 🙌\n```\n\nYou can also use the more compact `M` notation:\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Primitive\n>;\n```\n\n## Okay, but... why ? 🤔\n\nMeta-types allow operations that **are not possible with conventional types**.\n\nFor instance, they allow new [\"intersect\"](#intersect) and [\"exclude\"](#exclude) operations, and handling objects additional properties:\n\n```typescript\ntype MyObject = {\n str: string; // <= ❌ \"str\" is assignable to string\n [key: string]: number;\n};\n\ntype MyObjectKeys = keyof MyObject;\n// => string <= ❌ Unable to isolate \"str\"\n```\n\nThink of meta-types as a parallel universe where all kinds of magic can happen 🌈 Once your computations are over, you can retrieve the results by resolving them.\n\n\n\n> Meta-types were originally part of [json-schema-to-ts](https://github.com/ThomasAribart/json-schema-to-ts). Check it to see a real-life usage.\n\n## Table of content\n\n- [Installation](#%EF%B8%8F-installation)\n- [Cardinality](#-cardinality)\n- [Meta-types](#-meta-types)\n - [Never](#never)\n - [Any](#any)\n - [Const](#const)\n - [Enum](#enum)\n - [Primitive](#primitive)\n - [Array](#array)\n - [Tuple](#tuple)\n - [Object](#object)\n - [Union](#union)\n- [Methods](#-methods)\n - [Resolve](#resolve)\n - [Intersect](#intersect)\n - [Exclude](#exclude)\n- [Deserialization](#-deserialization)\n- [Type constraints](#-type-constraints)\n- [Unsafe types](#%EF%B8%8F-unsafe-types-and-methods)\n\n## ☁️ Installation\n\n```bash\n# npm\nnpm install --save-dev ts-algebra\n\n# yarn\nyarn add --dev ts-algebra\n```\n\n## 🧮 Cardinality\n\nA bit of theory first:\n\n- The [**cardinality**](https://en.wikipedia.org/wiki/Cardinality) of a type is the number of distinct values (potentially infinite) that can be assigned to it\n- A meta-type is said **representable** if at least one value can be assigned to its resolved type (cardinality ≥ 1)\n\nAn important notion to keep in mind using `ts-algebra`:\n\n---\n\n

\n M.Never is the only Meta-Type that is non-representable\n
\n (i.e. that resolves to never)\n

\n\n---\n\nAny other non-representable meta-type (e.g. an object with a non-representable but required property) will be instanciated as `M.Never`.\n\nThere are drawbacks to this choice (the said property is hard to find and debug) but stronger benefits: This drastically reduces type computations, in particular in [intersections](#intersect) and [exclusions](#exclude). This is crucial for performances and stability.\n\n## ✨ Meta-types\n\n### Never\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Never\n>;\n// => never\n```\n\n### Any\n\n**Arguments:**\n\n- IsSerialized (?boolean = false): See [deserialization](#-deserialization)\n- Deserialized (?type = never): See [deserialization](#-deserialization)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Any\n>;\n// => unknown\n```\n\n### Const\n\nUsed for types with [cardinalities](#meta-types) of 1.\n\n**Arguments:**\n\n- Value (type)\n- IsSerialized (?boolean = false): See [deserialization](#-deserialization)\n- Deserialized (?type = never): See [deserialization](#-deserialization)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Const<\"I love pizza\">\n>;\n// => \"I love pizza\"\n```\n\n### Enum\n\nUsed for types with finite [cardinalities](#meta-types).\n\n**Arguments:**\n\n- Values (type union)\n- IsSerialized (?boolean = false): See [deserialization](#-deserialization)\n- Deserialized (?type = never): See [deserialization](#-deserialization)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Food = M.Resolve<\n M.Enum<\"pizza\" | \"tacos\" | \"fries\">\n>;\n// => \"pizza\" | \"tacos\" | \"fries\"\n```\n\n> ☝️ `M.Enum` is [non-representable](#✨-meta-types)\n\n### Primitive\n\nUsed for either `string`, `number`, `boolean` or `null`.\n\n**Arguments:**\n\n- Value (string | number | boolean | null)\n- IsSerialized (?boolean = false): See [deserialization](#-deserialization)\n- Deserialized (?type = never): See [deserialization](#-deserialization)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Primitive\n>;\n// => string\n```\n\n### Array\n\nUsed for lists of items of the same type.\n\n**Arguments:**\n\n- Items (?meta-type = M.Any)\n- IsSerialized (?boolean = false): See [deserialization](#-deserialization)\n- Deserialized (?type = never): See [deserialization](#-deserialization)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Array\n>;\n// => unknown[]\n\ntype Resolved = M.Resolve<\n M.Array>\n>;\n// => string[]\n```\n\n> ☝️ Any meta-array is representable by `[]`\n\n### Tuple\n\nUsed for finite, ordered lists of items of different types.\n\nMeta-tuples can have **additional items**, typed as [`M.Never`](#never) by default. Thus, any meta-tuple is considered **closed** (additional items not allowed), unless a representable additional items meta-type is specified, in which case it becomes **open**.\n\n**Arguments:**\n\n- RequiredItems (meta-type[]):\n- AdditionalItems (?meta-type = M.Never): Type of additional items\n- IsSerialized (?boolean = false): See [deserialization](#-deserialization)\n- Deserialized (?type = never): See [deserialization](#-deserialization)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Tuple<[M.Primitive]>\n>;\n// => [string]\n\ntype Resolved = M.Resolve<\n M.Tuple<\n [M.Primitive],\n M.Primitive\n >\n>;\n// => [string, ...string[]]\n```\n\n> ☝️ A meta-tuple is [non-representable](#✨-meta-types) if one of its required items is non-representable\n\n### Object\n\nUsed for sets of key-value pairs (properties) which can be required or not.\n\nMeta-objects can have **additional properties**, typed as [`M.Never`](#never) by default. Thus, any meta-object is considered **closed** (additional properties not allowed), unless a representable additional properties meta-type is specified, in which case it becomes **open**.\n\nIn presence of named properties, open meta-objects additional properties are resolved as `unknown` to avoid conflicts. However, they are used as long as the meta-type is not resolved (especially in [intersections](#intersect) and [exclusions](#exclude)).\n\n**Arguments:**\n\n- NamedProperties (?{ [key:string]: meta-type } = {})\n- RequiredPropertiesKeys (?string union = never)\n- AdditionalProperties (?meta-type = M.Never): The type of additional properties\n- IsSerialized (?boolean = false): See [deserialization](#-deserialization)\n- Deserialized (?type = never): See [deserialization](#-deserialization)\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Object<\n {\n required: M.Primitive;\n notRequired: M.Primitive;\n },\n \"required\",\n M.Primitive\n >\n>;\n// => {\n// req: string,\n// notRequired?: null,\n// [key: string]: unknown\n// }\n```\n\n> ☝️ A meta-object is [non-representable](#✨-meta-types) if one of its required properties value is non-representable:\n>\n> - If it is a non-representable named property\n> - If it is an additional property, and the object is closed\n\n### Union\n\nUsed to combine meta-types in a union of meta-types.\n\n**Arguments:**\n\n- Values (meta-type union)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Food = M.Resolve<\n M.Union<\n | M.Primitive\n | M.Enum<\"pizza\" | \"tacos\" | \"fries\">\n | M.Const\n >\n>;\n// => number\n// | \"pizza\" | \"tacos\" | \"fries\"\n// | true\n```\n\n> ☝️ A meta-union is [non-representable](#✨-meta-types) if it is empty, or if none of its elements is representable\n\n> ☝️ Along with [M.Never](#never), M.Union is the only meta-type that doesn't support [serialization](#-deserialization)\n\n## 🔧 Methods\n\n### Resolve\n\nResolves the meta-type to its encapsulated type.\n\n**Arguments:**\n\n- MetaType (meta-type)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Primitive\n>;\n// => string\n```\n\n### Intersect\n\nTakes two meta-types as arguments, and returns their intersection as a meta-type.\n\n**Arguments:**\n\n- LeftMetaType (meta-type)\n- RightMetaType (meta-type)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Intersected = M.Intersect<\n M.Primitive,\n M.Enum<\"I love pizza\"\n | [\"tacos\"]\n | { and: \"fries\" }\n >\n>\n// => M.Enum<\"I love pizza\">\n```\n\nMeta-type intersections differ from conventional intersections:\n\n\n```typescript\ntype ConventionalIntersection =\n { str: string } & { num: number };\n// => { str: string, num: number }\n\ntype MetaIntersection = M.Intersect<\n M.Object<\n { str: M.Primitive },\n \"str\"\n >,\n M.Object<\n { num: M.Primitive },\n \"num\"\n >\n>;\n// => M.Never: \"num\" is required in B\n// ...but denied in A\n```\n\nIntersections are recursively propagated among tuple items and object properties, and take into account additional items and properties:\n\n\n```typescript\ntype Intersected = M.Intersect<\n M.Tuple<\n [M.Primitive],\n M.Primitive\n >,\n M.Tuple<\n [M.Enum<\"pizza\" | 42>],\n M.Enum<\"fries\" | true>\n >\n>;\n// => M.Tuple<\n// [M.Enum<42>],\n// M.Enum<\"fries\">\n// >\n\ntype Intersected = M.Intersect<\n M.Object<\n { food: M.Primitive },\n \"food\",\n M.Any\n >,\n M.Object<\n { age: M.Primitive },\n \"age\",\n M.Enum<\"pizza\" | \"fries\" | 42>\n >\n>;\n// => M.Object<\n// {\n// food: M.Enum<\"pizza\" | \"fries\">,\n// age: M.Primitive\n// },\n// \"food\" | \"age\",\n// M.Enum<\"pizza\" | \"fries\" | 42>\n// >\n```\n\nIntersections are distributed among unions:\n\n\n```typescript\ntype Intersected = M.Intersect<\n M.Primitive,\n M.Union<\n | M.Const<\"pizza\">\n | M.Const<42>\n >\n>;\n// => M.Union<\n// | M.Const<\"pizza\">\n// | M.Never\n// >\n```\n\n### Exclude\n\nTakes two meta-types as arguments, and returns their exclusion as a meta-type.\n\n**Arguments:**\n\n- OriginMetaType (meta-type)\n- SubstractedMetaType (meta-type)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Excluded = M.Exclude<\n M.Enum<\"I love pizza\"\n | [\"tacos\"]\n | { and: \"fries\" }\n >,\n M.Primitive,\n>\n// => M.Enum<\n// | [\"tacos\"]\n// | { and: \"fries\" }\n// >\n```\n\nMeta-type exclusions differ from conventional exclusions:\n\n\n```typescript\ntype ConventionalExclusion = Exclude<\n { req: string; notReq?: string },\n { req: string }\n>;\n// => never\n// ObjectA is assignable to ObjectB\n\ntype MetaExclusion = M.Exclude<\n M.Object<\n {\n req: M.Primitive;\n notReq: M.Primitive;\n },\n \"req\"\n >,\n M.Object<\n { req: M.Primitive },\n \"req\"\n >\n>;\n// => ObjectA\n// Exclusion is still representable\n```\n\n\n```typescript\ntype ConventionalExclusion = Exclude<\n { food: \"pizza\" | 42 },\n { [k: string]: number }\n>;\n// => { food: \"pizza\" | 42 }\n\ntype MetaExclusion = M.Exclude<\n M.Object<\n { food: M.Enum<\"pizza\" | 42> },\n \"food\"\n >,\n M.Object<\n {},\n never,\n M.Primitive\n >\n>;\n// => M.Object<\n// { food: M.Enum<\"pizza\"> },\n// \"food\"\n// >\n```\n\nWhen exclusions can be collapsed on a single item or property, they are recursively propagated among tuple items and object properties, taking into account additional items and properties:\n\n\n```typescript\ntype Excluded = M.Exclude<\n M.Tuple<[M.Enum<\"pizza\" | 42>]>,\n M.Tuple<[M.Primitive]>\n>;\n// => M.Tuple<[M.Enum<\"pizza\">]>\n\ntype Excluded = M.Exclude<\n M.Tuple<\n [M.Enum<\"pizza\" | 42>],\n M.Enum<\"fries\" | true>\n >,\n M.Tuple<\n [M.Primitive],\n M.Primitive\n >\n>;\n// => TupleA\n// Exclusion is not collapsable on a single item\n\ntype Excluded = M.Exclude<\n M.Object<\n {\n reqA: M.Enum<\"pizza\" | 42>;\n reqB: M.Enum<\"pizza\" | 42>;\n },\n \"reqA\" | \"reqB\"\n >,\n M.Object<\n {},\n never,\n M.Primitive\n >\n>;\n// => ObjectA\n// Exclusion is not collapsable on a single property\n```\n\nExclusions are distributed among unions:\n\n\n```typescript\ntype Excluded = M.Exclude<\n M.Union<\n | M.Const<\"pizza\">\n | M.Const<42>\n >,\n M.Primitive\n>;\n// => M.Union<\n// | M.Const<\"pizza\">\n// | M.Never\n// >\n```\n\nExluding a union returns the intersection of the exclusions of all elements, applied separately:\n\n\n```typescript\ntype Excluded = M.Exclude<\n M.Enum<42 | \"pizza\" | true>,\n M.Union<\n | M.Primitive\n | M.Primitive\n >\n>;\n// => M.Enum<\"pizza\">\n```\n\n## 📦 Deserialization\n\nAll meta-types except [`M.Never`](#never) and [`M.Union`](#union) can carry an extra type for [deserialization](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html) purposes. This extra-type will be passed along in operations and override the resolved type.\n\nFor instance, it is common to deserialize timestamps as `Date` objects. The last two arguments of [`M.Primitive`](#primitive) can be used to implement this:\n\n\n```typescript\ntype MetaTimestamp = M.Primitive<\n string,\n true, // <= enables deserialization (false by default)\n Date // <= overrides resolved type\n>;\n\ntype Resolved = M.Resolve;\n// => Date\n```\n\nNote that `MetaTimestamp` will still be considered as a string meta-type until it is resolved: Deserialization only take effect **at resolution time**.\n\n\n```typescript\ntype Intersected = M.Intersect<\n MetaTimestamp,\n M.Object<{}, never, M.Any> // <= Date is an object...\n>;\n// => M.Never\n// ...but doesn't intersect Timestamp\n```\n\nIn representable [intersections](#intersect):\n\n- If no meta-type is serialized, the resulting intersection is not serialized.\n- If only one meta-type (left or right) is serialized, the resulting intersection inherits from its deserialization properties.\n- If both left and right meta-types are serialized, the resulting intersection inherits from both deserialization properties, through a conventional intersection (`A & B`).\n\n\n```typescript\ntype MetaBrandedString = M.Primitive<\n string,\n true,\n { brand: \"timestamp\" }\n>;\n\ntype Resolved = M.Resolve<\n M.Intersect<\n MetaTimestamp,\n MetaBrandedString\n >\n>\n// => Date & { brand: \"timestamp\" }\n```\n\nIn representable [exclusions](#exclude):\n\n- If the origin meta-type is not serialized, the resulting exclusion is not serialized.\n- If the origin meta-type is serialized, the resulting exclusion inherits of its deserialization properties.\n\n## 🚧 Type constraints\n\nTo prevent errors, meta-types inputs are validated against type constraints:\n\n\n```typescript\ntype Invalid = M.Array<\n string // <= ❌ Meta-type expected\n>;\n```\n\nIf you need to use them, all type constraints are also exported:\n\n| Meta-type | Type constraint |\n| ------------- | :--------------------------------------------------------------------- |\n| `M.Any` | `M.AnyType` = `M.Any` |\n| `M.Never` | `M.NeverType` = `M.Never` |\n| `M.Const` | `M.ConstType` = `M.Const` |\n| `M.Enum` | `M.EnumType` = `M.Enum` |\n| `M.Primitive` | `M.PrimitiveType` = `M.Primitive` |\n| `M.Array` | `M.ArrayType` = `M.Array` |\n| `M.Tuple` | `M.TupleType` = `M.Tuple` |\n| `M.Object` | `M.ObjectType` = `M.Object, string, M.Type>` |\n| `M.Union` | `M.UnionType` = `M.Union` |\n| - | `M.Type` = Union of the above |\n\n## ✂️ Unsafe types and methods\n\nIn deep and self-referencing computations like in [json-schema-to-ts](https://github.com/ThomasAribart/json-schema-to-ts), type constraints can become an issue, as the compiler may not be able to confirm the input type validity ahead of usage.\n\n\n```typescript\ntype MyArray = M.Array<\n VeryDeepTypeComputation<\n ...\n > // <= 💥 Type constraint can break\n>\n```\n\nFor such cases, `ts-algebra` exposes **\"unsafe\"** types and methods, that behave the same as \"safe\" ones but removing any type constraints. If you use them, beware: The integrity of the compiling is up to you 😉\n\n| Safe | Unsafe |\n| ------------- | -------------- |\n| `M.Any` | - |\n| `M.Never` | - |\n| `M.Const` | - |\n| `M.Enum` | - |\n| `M.Primitive` | `M.$Primitive` |\n| `M.Array` | `M.$Array` |\n| `M.Tuple` | `M.$Tuple` |\n| `M.Object` | `M.$Object` |\n| `M.Union` | `M.$Union` |\n| `M.Resolve` | `M.$Resolve` |\n| `M.Intersect` | `M.$Intersect` |\n| `M.Exclude` | `M.$Exclude` |\n","readmeFilename":"README.md","gitHead":"c6e82abc452b92de37ed00a5357b03401aef601b","_id":"ts-algebra@1.2.0-beta.0","_nodeVersion":"18.0.0","_npmVersion":"8.6.0","dist":{"integrity":"sha512-MfIuQQsJjH426C3lwSvpYUaXQstTG+K7o8Lm/JMs//NrmpQECUwz0G+SCDUnUlwaKqnZe2DRxFJlwIhLtSR6GQ==","shasum":"d2e4231661d934c27e4a805a9ff2af5bb6c5e56d","tarball":"https://registry.npmjs.org/ts-algebra/-/ts-algebra-1.2.0-beta.0.tgz","fileCount":99,"unpackedSize":74669,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDemYq/9WOTeBQZVYYL9CawfHbgPpD3Y/aLG87DxKgzBAIhAIX62newUe1zYyuVD1E8Y6vDRV4G4X6jKEKULjAN7L1v"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjy9LNACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmovlA//VFE5XyenKiH/loQjia2R+n0xNADuky5iUy3mYuQ0Wvq4eJ/w\r\nNoOrCqrBkG5HUJWXKUTxSeBhno3JqMBE+YQI2/7WUfe3i8TcsfUM6lJYXJOt\r\nq+biaAdCgnSk7QxOQnKuPuFvhVV7X0Nqg24kPhNXpp0oxH6RwSpYblnf5Phn\r\nxLXjCfQgZOzDdtiLiDMYOfDP2eNyq8cwXiFDBZ1kUV9mzz7LzH+G9l6uFDRk\r\n+vCYNppAAD2mXjMxT79Tov99V4og6Wp2JHswJlxbCNPKv7xsIjuJqukyU8dH\r\n9D8tURHFaP+honlnXx+FjZ1+kO7pyhifGObgWslwP3a+7UDFxiRNgfoEIt2M\r\n4jy016E5B3WXE2yxZcvUK/x7K+xLcjqzAuv+bgRG8nz5kAGeSs7EiJvgKf+S\r\nmRKhV+FlYeeav6SngwZXnnnoVSIgcmJ2DEJUvJKdffjFSSvxCK+awpf69I1G\r\na+vMCEXAkn814qdhVRAtf0pMGWF2374X/THDG84DPIIVcp9CSGG1uvScOLDI\r\nCl9Ij3rAlz4Qan68mFQCzIPMKNOLbfjR8Tb4+I9us6iKIBIMPIhQAeqTfxiB\r\noK7yj816+93ZEzISw1DSm/RsHFfqY9H+usPNQqLGVz1Gvv5DnqL4sMgkmH36\r\neT1YimH+iq0lUcN198ct0bd+0y+qTeNkNaw=\r\n=xeki\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"thomasaribart","email":"thomas.aribart@gmail.com"},"directories":{},"maintainers":[{"name":"thomasaribart","email":"thomas.aribart@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ts-algebra_1.2.0-beta.0_1674302157365_0.15793105395950047"},"_hasShrinkwrap":false},"1.2.0":{"name":"ts-algebra","version":"1.2.0","description":"Types on steroids 💊","main":"lib/index.js","module":"lib/index.js","types":"lib/index.d.ts","scripts":{"release":"bash scripts/release.bash","test":"tsc --noEmit","build":"tsc -p tsconfig.build.json"},"dependencies":{},"devDependencies":{"rollup":"^2.67.3","rollup-plugin-dts":"4.1.0","rollup-plugin-import-map":"^2.2.2","typescript":"^4.5.5","ts-toolbelt":"^9.6.0"},"author":{"name":"Thomas Aribart"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/ThomasAribart/ts-algebra.git"},"keywords":["typescript","type","ts"],"bugs":{"url":"https://github.com/ThomasAribart/ts-algebra/issues"},"homepage":"https://github.com/ThomasAribart/ts-algebra#readme","gitHead":"0189e1c1ccf6dbfe42ea6184ab0c1f9ad1f4839c","_id":"ts-algebra@1.2.0","_nodeVersion":"18.0.0","_npmVersion":"8.6.0","dist":{"integrity":"sha512-kMuJJd8B2N/swCvIvn1hIFcIOrLGbWl9m/J6O3kHx9VRaevh00nvgjPiEGaRee7DRaAczMYR2uwWvXU22VFltw==","shasum":"f91c481207a770f0d14d055c376cbee040afdfc9","tarball":"https://registry.npmjs.org/ts-algebra/-/ts-algebra-1.2.0.tgz","fileCount":99,"unpackedSize":74662,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFdRsNzuKNOC7nrYlCVagGZT/CmGaOWm8QSWqmcQGfm8AiEAhBSb/yJUkoHNYXFW5g5gjWbv9WGm8fkWCiS8MkrvtSI="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJj9p5SACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrBqw//YY1Jghw+lIUhj3Iq8ODhTUTVGqaycve+X/vXdPXSOxwOJ6As\r\nOrtSlMGzMpCqG4+NEJXgYOkBv2lqYkDPgxNWdIsuPjZhU/1k7fFTDc29Atyv\r\nl0M9dQy4SAfq+Gml/Qv17jHYxtLn7/vFRU/a9wiYuMNcHA//1cURx091iDZ6\r\nEQ8h+V3YRfD2F7BuoDcM00ew2rodoUfBKvOWy2FdQifIsDLyLNGKDOBm0Gp1\r\n6COSIvzFDMS0rcWIGMuXDGlWYH+B6iJu7Qn285ThEKBxUG2TkltDUlDbf41u\r\nTS4TkM8+UwB2ez4Tz6AD1+OC3Ve0WlaOdAvLvplVMsBP2y7vVcnTIQ3HgVZj\r\nj+jn0ymOrmNDjjNW9UDErlNp15ZJvGZtBGjVVnE+taoL5OSy0/fnqKYuMyQP\r\nYj2UsBxEFGZa0EUmHGxRmEgfWtoe16REogiufTIhjanptvp50JwfsvKvFIS2\r\n5U+AvLYgceJZvXzOj7rR6JEUxqLTlv48pfnhobPVb2YK4E6hBpZbwOnOLOXh\r\naJUkc7d65UYt0ZMC/JWog7MT5gwmCbDbgVDuL5xNGn9ZKzuOdOFmaK+ilw3+\r\nGngX9unXofXcCBxcbrrydke1zl9KYoCcCZfu8e6YYwP2RlNMLGC/Pu2EAKd1\r\nTEnHcTYbQ9n8murH3hNOJAPuZmE7EjYQ6vA=\r\n=TNoc\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"thomasaribart","email":"thomas.aribart@gmail.com"},"directories":{},"maintainers":[{"name":"thomasaribart","email":"thomas.aribart@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ts-algebra_1.2.0_1677106770314_0.03731503036199135"},"_hasShrinkwrap":false},"1.2.1":{"name":"ts-algebra","version":"1.2.1","description":"Types on steroids 💊","main":"lib/index.js","module":"lib/index.js","types":"lib/index.d.ts","scripts":{"release":"bash scripts/release.bash","set-package-version":"ts-node scripts/setPackageVersion","test":"yarn test-type && yarn test-format && yarn test-unused-exports && yarn test-lint","test-type":"tsc --noEmit","test-format":"yarn prettier . --check","test-unused-exports":"yarn ts-unused-exports ./tsconfig.json --excludePathsFromReport='src/index.ts;'","test-lint":"yarn eslint --ext=js,ts .","format":"yarn prettier . --write","build":"ttsc -p tsconfig.build.json"},"dependencies":{},"devDependencies":{"@trivago/prettier-plugin-sort-imports":"^3.4.0","@types/node":"^20.5.7","@typescript-eslint/eslint-plugin":"^5.42.1","@typescript-eslint/parser":"^5.42.1","@zerollup/ts-transform-paths":"^1.7.18","eslint":"^8.27.0","eslint-config-prettier":"^8.5.0","eslint-import-resolver-typescript":"^3.5.2","eslint-plugin-import":"^2.26.0","eslint-plugin-jsdoc":"^46.4.6","eslint-plugin-prefer-arrow":"^1.2.3","eslint-plugin-prettier":"^4.2.1","eslint-plugin-unused-imports":"^2.0.0","prettier":"^2.7.1","rollup":"^2.67.3","rollup-plugin-dts":"4.1.0","rollup-plugin-import-map":"^2.2.2","ts-node":"^10.9.1","ts-toolbelt":"^9.6.0","ts-unused-exports":"^8.0.0","ttypescript":"^1.5.13","typescript":"^4.5.5"},"author":{"name":"Thomas Aribart"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/ThomasAribart/ts-algebra.git"},"keywords":["typescript","type","ts"],"bugs":{"url":"https://github.com/ThomasAribart/ts-algebra/issues"},"homepage":"https://github.com/ThomasAribart/ts-algebra#readme","gitHead":"d8f4f1f8760a9016ff008a8d9113c1a5eca37766","_id":"ts-algebra@1.2.1","_nodeVersion":"18.17.1","_npmVersion":"9.6.7","dist":{"integrity":"sha512-W6JPG/+6DqG8+pGALWtju1YGDZGmZ+JqGSq4qrbF1hiBUf5x+uYhQyluIbTtrcVmKsWGoOziKlZNNsdrQ8Yzrg==","shasum":"8cefa656b0563f207da2cb01e7094e178649ba0e","tarball":"https://registry.npmjs.org/ts-algebra/-/ts-algebra-1.2.1.tgz","fileCount":104,"unpackedSize":98125,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCmYUCoWY4kdZ1XMZLdCDdn7V3j9uU5nTmRKpAAVEd87wIgYhMlRuJbGWTPe9XofFxNfyE5UUftkUQxybK7qiOwbvw="}]},"_npmUser":{"name":"thomasaribart","email":"thomas.aribart@gmail.com"},"directories":{},"maintainers":[{"name":"thomasaribart","email":"thomas.aribart@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ts-algebra_1.2.1_1693345876621_0.04525903550531529"},"_hasShrinkwrap":false},"1.2.2":{"name":"ts-algebra","version":"1.2.2","description":"Types on steroids 💊","main":"lib/index.js","module":"lib/index.js","types":"lib/index.d.ts","scripts":{"release":"bash scripts/release.bash","set-package-version":"ts-node scripts/setPackageVersion","test":"yarn test-type && yarn test-format && yarn test-unused-exports && yarn test-lint","test-type":"tsc --noEmit","test-format":"yarn prettier . --check","test-unused-exports":"yarn ts-unused-exports ./tsconfig.json --excludePathsFromReport='src/index.ts;'","test-lint":"yarn eslint --ext=js,ts .","format":"yarn prettier . --write","build":"ttsc -p tsconfig.build.json"},"dependencies":{},"devDependencies":{"@trivago/prettier-plugin-sort-imports":"^3.4.0","@types/node":"^20.5.7","@typescript-eslint/eslint-plugin":"^5.42.1","@typescript-eslint/parser":"^5.42.1","@zerollup/ts-transform-paths":"^1.7.18","eslint":"^8.27.0","eslint-config-prettier":"^8.5.0","eslint-import-resolver-typescript":"^3.5.2","eslint-plugin-import":"^2.26.0","eslint-plugin-jsdoc":"^46.4.6","eslint-plugin-prefer-arrow":"^1.2.3","eslint-plugin-prettier":"^4.2.1","eslint-plugin-unused-imports":"^2.0.0","prettier":"^2.7.1","rollup":"^2.67.3","rollup-plugin-dts":"4.1.0","rollup-plugin-import-map":"^2.2.2","ts-node":"^10.9.1","ts-toolbelt":"^9.6.0","ts-unused-exports":"^8.0.0","ttypescript":"^1.5.13","typescript":"^4.5.5"},"author":{"name":"Thomas Aribart"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/ThomasAribart/ts-algebra.git"},"keywords":["typescript","type","ts"],"bugs":{"url":"https://github.com/ThomasAribart/ts-algebra/issues"},"homepage":"https://github.com/ThomasAribart/ts-algebra#readme","gitHead":"4d1c559a86ad651c92007e8adc98e6310917a3ec","_id":"ts-algebra@1.2.2","_nodeVersion":"18.17.1","_npmVersion":"9.6.7","dist":{"integrity":"sha512-kloPhf1hq3JbCPOTYoOWDKxebWjNb2o/LKnNfkWhxVVisFFmMJPPdJeGoGmM+iRLyoXAR61e08Pb+vUXINg8aA==","shasum":"b75d301c28cd4126cd344760a47b43e48e2872e0","tarball":"https://registry.npmjs.org/ts-algebra/-/ts-algebra-1.2.2.tgz","fileCount":104,"unpackedSize":99956,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIA82e67rk5ixOl0DQrbA6XKvR9NV1qy4CYvO3ZbZOx1WAiEAqlPcZjzPMybscs4rQb3m3CJsr8/4FKwttQSzeA6pzxQ="}]},"_npmUser":{"name":"thomasaribart","email":"thomas.aribart@gmail.com"},"directories":{},"maintainers":[{"name":"thomasaribart","email":"thomas.aribart@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ts-algebra_1.2.2_1693953139661_0.6085870909815687"},"_hasShrinkwrap":false},"2.0.0":{"name":"ts-algebra","version":"2.0.0","description":"Types on steroids 💊","main":"lib/index.js","module":"lib/index.js","types":"lib/index.d.ts","scripts":{"release":"bash scripts/release.bash","set-package-version":"ts-node scripts/setPackageVersion","test":"yarn test-type && yarn test-format && yarn test-unused-exports && yarn test-lint","test-type":"tsc --noEmit","test-format":"yarn prettier . --check","test-unused-exports":"yarn ts-unused-exports ./tsconfig.json --excludePathsFromReport='src/index.ts;'","test-lint":"yarn eslint --ext=js,ts .","format":"yarn prettier . --write","build":"ttsc -p tsconfig.build.json"},"dependencies":{},"devDependencies":{"@trivago/prettier-plugin-sort-imports":"^3.4.0","@types/node":"^20.5.7","@typescript-eslint/eslint-plugin":"^5.42.1","@typescript-eslint/parser":"^5.42.1","@zerollup/ts-transform-paths":"^1.7.18","eslint":"^8.27.0","eslint-config-prettier":"^8.5.0","eslint-import-resolver-typescript":"^3.5.2","eslint-plugin-import":"^2.26.0","eslint-plugin-jsdoc":"^46.4.6","eslint-plugin-prefer-arrow":"^1.2.3","eslint-plugin-prettier":"^4.2.1","eslint-plugin-unused-imports":"^2.0.0","prettier":"^2.7.1","rollup":"^2.67.3","rollup-plugin-dts":"4.1.0","rollup-plugin-import-map":"^2.2.2","ts-node":"^10.9.1","ts-toolbelt":"^9.6.0","ts-unused-exports":"^8.0.0","ttypescript":"^1.5.13","typescript":"^4.5.5"},"author":{"name":"Thomas Aribart"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/ThomasAribart/ts-algebra.git"},"keywords":["typescript","type","ts"],"bugs":{"url":"https://github.com/ThomasAribart/ts-algebra/issues"},"homepage":"https://github.com/ThomasAribart/ts-algebra#readme","_id":"ts-algebra@2.0.0","gitHead":"b3dace61651be9277da04e0b1ed3353838fd6175","_nodeVersion":"18.20.2","_npmVersion":"10.5.0","dist":{"integrity":"sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw==","shasum":"4e3e0953878f26518fce7f6bb115064a65388b7a","tarball":"https://registry.npmjs.org/ts-algebra/-/ts-algebra-2.0.0.tgz","fileCount":104,"unpackedSize":101154,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFboOECi0fRm2iOc5VnJ95X8My6S5ttMcMAxIUPzsXG0AiEAzldEGYjOPOOIQ1t8b+ew5VDlH/0tzK8pRDvCsH/eBH4="}]},"_npmUser":{"name":"thomasaribart","email":"thomas.aribart@gmail.com"},"directories":{},"maintainers":[{"name":"thomasaribart","email":"thomas.aribart@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/ts-algebra_2.0.0_1714838368220_0.4146484243715389"},"_hasShrinkwrap":false}},"time":{"created":"2022-02-19T17:47:09.436Z","1.0.0-beta.0":"2022-02-19T17:47:09.639Z","modified":"2024-05-04T15:59:28.548Z","1.0.0-beta.1":"2022-04-06T14:49:12.634Z","1.0.0-beta.3":"2022-04-06T16:59:39.177Z","1.0.0":"2022-04-06T17:33:05.654Z","1.0.1":"2022-04-08T18:44:47.854Z","1.1.0-beta.0":"2022-05-01T12:02:37.341Z","1.1.0":"2022-05-01T16:45:14.050Z","1.1.1-beta.0":"2022-05-01T17:13:09.531Z","1.1.1":"2022-05-01T17:16:05.053Z","1.2.0-beta.0":"2023-01-21T11:55:57.539Z","1.2.0":"2023-02-22T22:59:30.441Z","1.2.1":"2023-08-29T21:51:16.868Z","1.2.2":"2023-09-05T22:32:19.851Z","2.0.0":"2024-05-04T15:59:28.376Z"},"maintainers":[{"name":"thomasaribart","email":"thomas.aribart@gmail.com"}],"description":"Types on steroids 💊","homepage":"https://github.com/ThomasAribart/ts-algebra#readme","keywords":["typescript","type","ts"],"repository":{"type":"git","url":"git+https://github.com/ThomasAribart/ts-algebra.git"},"author":{"name":"Thomas Aribart"},"bugs":{"url":"https://github.com/ThomasAribart/ts-algebra/issues"},"license":"MIT","readme":"\n\n

\n If you use this repo, star it ✨\n

\n\n# Types on steroids 💊\n\n`ts-algebra` exposes a subset of TS types called **Meta-types**: Meta-types are types that encapsulate other types.\n\n```typescript\nimport { Meta } from \"ts-algebra\";\n\ntype MetaString = Meta.Primitive;\n```\n\nThe encapsulated type can be retrieved using the `Resolve` operation.\n\n```typescript\ntype Resolved = Meta.Resolve;\n// => string 🙌\n```\n\nYou can also use the more compact `M` notation:\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Primitive\n>;\n```\n\n## Okay, but... why ? 🤔\n\nMeta-types allow operations that **are not possible with conventional types**.\n\nFor instance, they allow new [\"intersect\"](#intersect) and [\"exclude\"](#exclude) operations, and handling objects additional properties:\n\n```typescript\ntype MyObject = {\n str: string; // <= ❌ \"str\" is assignable to string\n [key: string]: number;\n};\n\ntype MyObjectKeys = keyof MyObject;\n// => string <= ❌ Unable to isolate \"str\"\n```\n\nThink of meta-types as a parallel universe where all kinds of magic can happen 🌈 Once your computations are over, you can retrieve the results by resolving them.\n\n\n\n> Meta-types were originally part of [json-schema-to-ts](https://github.com/ThomasAribart/json-schema-to-ts). Check it to see a real-life usage.\n\n## Table of content\n\n- [Installation](#%EF%B8%8F-installation)\n- [Cardinality](#-cardinality)\n- [Meta-types](#-meta-types)\n - [Never](#never)\n - [Any](#any)\n - [Const](#const)\n - [Enum](#enum)\n - [Primitive](#primitive)\n - [Array](#array)\n - [Tuple](#tuple)\n - [Object](#object)\n - [Union](#union)\n- [Methods](#-methods)\n - [Resolve](#resolve)\n - [Intersect](#intersect)\n - [Exclude](#exclude)\n- [Deserialization](#-deserialization)\n- [Type constraints](#-type-constraints)\n- [Unsafe types](#%EF%B8%8F-unsafe-types-and-methods)\n\n## ☁️ Installation\n\n```bash\n# npm\nnpm install --save-dev ts-algebra\n\n# yarn\nyarn add --dev ts-algebra\n```\n\n## 🧮 Cardinality\n\nA bit of theory first:\n\n- The [**cardinality**](https://en.wikipedia.org/wiki/Cardinality) of a type is the number of distinct values (potentially infinite) that can be assigned to it\n- A meta-type is said **representable** if at least one value can be assigned to its resolved type (cardinality ≥ 1)\n\nAn important notion to keep in mind using `ts-algebra`:\n\n---\n\n

\n M.Never is the only Meta-Type that is non-representable\n
\n (i.e. that resolves to never)\n

\n\n---\n\nAny other non-representable meta-type (e.g. an object with a non-representable but required property) will be instanciated as `M.Never`.\n\nThere are drawbacks to this choice (the said property is hard to find and debug) but stronger benefits: This drastically reduces type computations, in particular in [intersections](#intersect) and [exclusions](#exclude). This is crucial for performances and stability.\n\n## ✨ Meta-types\n\n### Never\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Never\n>;\n// => never\n```\n\n### Any\n\n**Arguments:**\n\n- IsSerialized (?boolean = false): See [deserialization](#-deserialization)\n- Deserialized (?type = never): See [deserialization](#-deserialization)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Any\n>;\n// => unknown\n```\n\n### Const\n\nUsed for types with [cardinalities](#meta-types) of 1.\n\n**Arguments:**\n\n- Value (type)\n- IsSerialized (?boolean = false): See [deserialization](#-deserialization)\n- Deserialized (?type = never): See [deserialization](#-deserialization)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Const<\"I love pizza\">\n>;\n// => \"I love pizza\"\n```\n\n### Enum\n\nUsed for types with finite [cardinalities](#meta-types).\n\n**Arguments:**\n\n- Values (type union)\n- IsSerialized (?boolean = false): See [deserialization](#-deserialization)\n- Deserialized (?type = never): See [deserialization](#-deserialization)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Food = M.Resolve<\n M.Enum<\"pizza\" | \"tacos\" | \"fries\">\n>;\n// => \"pizza\" | \"tacos\" | \"fries\"\n```\n\n> ☝️ `M.Enum` is [non-representable](#✨-meta-types)\n\n### Primitive\n\nUsed for either `string`, `number`, `boolean` or `null`.\n\n**Arguments:**\n\n- Value (string | number | boolean | null)\n- IsSerialized (?boolean = false): See [deserialization](#-deserialization)\n- Deserialized (?type = never): See [deserialization](#-deserialization)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Primitive\n>;\n// => string\n```\n\n### Array\n\nUsed for lists of items of the same type.\n\n**Arguments:**\n\n- Items (?meta-type = M.Any)\n- IsSerialized (?boolean = false): See [deserialization](#-deserialization)\n- Deserialized (?type = never): See [deserialization](#-deserialization)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Array\n>;\n// => unknown[]\n\ntype Resolved = M.Resolve<\n M.Array>\n>;\n// => string[]\n```\n\n> ☝️ Any meta-array is representable by `[]`\n\n### Tuple\n\nUsed for finite, ordered lists of items of different types.\n\nMeta-tuples can have **additional items**, typed as [`M.Never`](#never) by default. Thus, any meta-tuple is considered **closed** (additional items not allowed), unless a representable additional items meta-type is specified, in which case it becomes **open**.\n\n**Arguments:**\n\n- RequiredItems (meta-type[]):\n- AdditionalItems (?meta-type = M.Never): Type of additional items\n- IsSerialized (?boolean = false): See [deserialization](#-deserialization)\n- Deserialized (?type = never): See [deserialization](#-deserialization)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Tuple<[M.Primitive]>\n>;\n// => [string]\n\ntype Resolved = M.Resolve<\n M.Tuple<\n [M.Primitive],\n M.Primitive\n >\n>;\n// => [string, ...string[]]\n```\n\n> ☝️ A meta-tuple is [non-representable](#✨-meta-types) if one of its required items is non-representable\n\n### Object\n\nUsed for sets of key-value pairs (properties) which can be required or not.\n\nMeta-objects can have **additional properties**, typed as [`M.Never`](#never) by default. Thus, any meta-object is considered **closed** (additional properties not allowed), unless a representable additional properties meta-type is specified, in which case it becomes **open**.\n\nIn presence of named properties, open meta-objects additional properties are resolved as `unknown` to avoid conflicts. However, they are used as long as the meta-type is not resolved (especially in [intersections](#intersect) and [exclusions](#exclude)).\n\n**Arguments:**\n\n- NamedProperties (?{ [key:string]: meta-type } = {})\n- RequiredPropertiesKeys (?string union = never)\n- AdditionalProperties (?meta-type = M.Never): The type of additional properties\n- CloseOnResolve (?boolean = false): Ignore `AdditionalProperties` at resolution time\n- IsSerialized (?boolean = false): See [deserialization](#-deserialization)\n- Deserialized (?type = never): See [deserialization](#-deserialization)\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Object<\n {\n required: M.Primitive;\n notRequired: M.Primitive;\n },\n \"required\",\n M.Primitive\n >\n>;\n// => {\n// req: string,\n// notRequired?: null,\n// [key: string]: unknown\n// }\n\ntype ClosedOnResolve = M.Resolve<\n M.Object<\n {\n required: M.Primitive;\n notRequired: M.Primitive;\n },\n \"required\",\n M.Primitive,\n false\n >\n>;\n// => {\n// req: string,\n// notRequired?: null,\n// }\n```\n\n> ☝️ A meta-object is [non-representable](#✨-meta-types) if one of its required properties value is non-representable:\n>\n> - If it is a non-representable named property\n> - If it is an additional property, and the object is closed\n\n### Union\n\nUsed to combine meta-types in a union of meta-types.\n\n**Arguments:**\n\n- Values (meta-type union)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Food = M.Resolve<\n M.Union<\n | M.Primitive\n | M.Enum<\"pizza\" | \"tacos\" | \"fries\">\n | M.Const\n >\n>;\n// => number\n// | \"pizza\" | \"tacos\" | \"fries\"\n// | true\n```\n\n> ☝️ A meta-union is [non-representable](#✨-meta-types) if it is empty, or if none of its elements is representable\n\n> ☝️ Along with [M.Never](#never), M.Union is the only meta-type that doesn't support [serialization](#-deserialization)\n\n## 🔧 Methods\n\n### Resolve\n\nResolves the meta-type to its encapsulated type.\n\n**Arguments:**\n\n- MetaType (meta-type)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Resolved = M.Resolve<\n M.Primitive\n>;\n// => string\n```\n\n### Intersect\n\nTakes two meta-types as arguments, and returns their intersection as a meta-type.\n\n**Arguments:**\n\n- LeftMetaType (meta-type)\n- RightMetaType (meta-type)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Intersected = M.Intersect<\n M.Primitive,\n M.Enum<\"I love pizza\"\n | [\"tacos\"]\n | { and: \"fries\" }\n >\n>\n// => M.Enum<\"I love pizza\">\n```\n\nMeta-type intersections differ from conventional intersections:\n\n\n```typescript\ntype ConventionalIntersection =\n { str: string } & { num: number };\n// => { str: string, num: number }\n\ntype MetaIntersection = M.Intersect<\n M.Object<\n { str: M.Primitive },\n \"str\"\n >,\n M.Object<\n { num: M.Primitive },\n \"num\"\n >\n>;\n// => M.Never: \"num\" is required in B\n// ...but denied in A\n```\n\nIntersections are recursively propagated among tuple items and object properties, and take into account additional items and properties:\n\n\n```typescript\ntype Intersected = M.Intersect<\n M.Tuple<\n [M.Primitive],\n M.Primitive\n >,\n M.Tuple<\n [M.Enum<\"pizza\" | 42>],\n M.Enum<\"fries\" | true>\n >\n>;\n// => M.Tuple<\n// [M.Enum<42>],\n// M.Enum<\"fries\">\n// >\n\ntype Intersected = M.Intersect<\n M.Object<\n { food: M.Primitive },\n \"food\",\n M.Any\n >,\n M.Object<\n { age: M.Primitive },\n \"age\",\n M.Enum<\"pizza\" | \"fries\" | 42>\n >\n>;\n// => M.Object<\n// {\n// food: M.Enum<\"pizza\" | \"fries\">,\n// age: M.Primitive\n// },\n// \"food\" | \"age\",\n// M.Enum<\"pizza\" | \"fries\" | 42>\n// >\n```\n\nIntersections are distributed among unions:\n\n\n```typescript\ntype Intersected = M.Intersect<\n M.Primitive,\n M.Union<\n | M.Const<\"pizza\">\n | M.Const<42>\n >\n>;\n// => M.Union<\n// | M.Const<\"pizza\">\n// | M.Never\n// >\n```\n\n### Exclude\n\nTakes two meta-types as arguments, and returns their exclusion as a meta-type.\n\n**Arguments:**\n\n- SourceMetaType (meta-type)\n- ExcludedMetaType (meta-type)\n\n\n```typescript\nimport { M } from \"ts-algebra\";\n\ntype Excluded = M.Exclude<\n M.Enum<\"I love pizza\"\n | [\"tacos\"]\n | { and: \"fries\" }\n >,\n M.Primitive,\n>\n// => M.Enum<\n// | [\"tacos\"]\n// | { and: \"fries\" }\n// >\n```\n\nMeta-type exclusions differ from conventional exclusions:\n\n\n```typescript\ntype ConventionalExclusion = Exclude<\n { req: string; notReq?: string },\n { req: string }\n>;\n// => never\n// ObjectA is assignable to ObjectB\n\ntype MetaExclusion = M.Exclude<\n M.Object<\n {\n req: M.Primitive;\n notReq: M.Primitive;\n },\n \"req\"\n >,\n M.Object<\n { req: M.Primitive },\n \"req\"\n >\n>;\n// => ObjectA\n// Exclusion is still representable\n```\n\n\n```typescript\ntype ConventionalExclusion = Exclude<\n { food: \"pizza\" | 42 },\n { [k: string]: number }\n>;\n// => { food: \"pizza\" | 42 }\n\ntype MetaExclusion = M.Exclude<\n M.Object<\n { food: M.Enum<\"pizza\" | 42> },\n \"food\"\n >,\n M.Object<\n {},\n never,\n M.Primitive\n >\n>;\n// => M.Object<\n// { food: M.Enum<\"pizza\"> },\n// \"food\"\n// >\n```\n\nWhen exclusions can be collapsed on a single item or property, they are recursively propagated among tuple items and object properties, taking into account additional items and properties:\n\n\n```typescript\ntype Excluded = M.Exclude<\n M.Tuple<[M.Enum<\"pizza\" | 42>]>,\n M.Tuple<[M.Primitive]>\n>;\n// => M.Tuple<[M.Enum<\"pizza\">]>\n\ntype Excluded = M.Exclude<\n M.Tuple<\n [M.Enum<\"pizza\" | 42>],\n M.Enum<\"fries\" | true>\n >,\n M.Tuple<\n [M.Primitive],\n M.Primitive\n >\n>;\n// => TupleA\n// Exclusion is not collapsable on a single item\n\ntype Excluded = M.Exclude<\n M.Object<\n {\n reqA: M.Enum<\"pizza\" | 42>;\n reqB: M.Enum<\"pizza\" | 42>;\n },\n \"reqA\" | \"reqB\"\n >,\n M.Object<\n {},\n never,\n M.Primitive\n >\n>;\n// => ObjectA\n// Exclusion is not collapsable on a single property\n```\n\nExclusions are distributed among unions:\n\n\n```typescript\ntype Excluded = M.Exclude<\n M.Union<\n | M.Const<\"pizza\">\n | M.Const<42>\n >,\n M.Primitive\n>;\n// => M.Union<\n// | M.Const<\"pizza\">\n// | M.Never\n// >\n```\n\nExcluding a union returns the intersection of the exclusions of all elements, applied separately:\n\n\n```typescript\ntype Excluded = M.Exclude<\n M.Enum<42 | \"pizza\" | true>,\n M.Union<\n | M.Primitive\n | M.Primitive\n >\n>;\n// => M.Enum<\"pizza\">\n```\n\n## 📦 Deserialization\n\nAll meta-types except [`M.Never`](#never) and [`M.Union`](#union) can carry an extra type for [deserialization](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html) purposes. This extra-type will be passed along in operations and override the resolved type.\n\nFor instance, it is common to deserialize timestamps as `Date` objects. The last two arguments of [`M.Primitive`](#primitive) can be used to implement this:\n\n\n```typescript\ntype MetaTimestamp = M.Primitive<\n string,\n true, // <= enables deserialization (false by default)\n Date // <= overrides resolved type\n>;\n\ntype Resolved = M.Resolve;\n// => Date\n```\n\nNote that `MetaTimestamp` will still be considered as a string meta-type until it is resolved: Deserialization only take effect **at resolution time**.\n\n\n```typescript\ntype Intersected = M.Intersect<\n MetaTimestamp,\n M.Object<{}, never, M.Any> // <= Date is an object...\n>;\n// => M.Never\n// ...but doesn't intersect Timestamp\n```\n\nIn representable [intersections](#intersect):\n\n- If no meta-type is serialized, the resulting intersection is not serialized.\n- If only one meta-type (left or right) is serialized, the resulting intersection inherits from its deserialization properties.\n- If both left and right meta-types are serialized, the resulting intersection inherits from both deserialization properties, through a conventional intersection (`A & B`).\n\n\n```typescript\ntype MetaBrandedString = M.Primitive<\n string,\n true,\n { brand: \"timestamp\" }\n>;\n\ntype Resolved = M.Resolve<\n M.Intersect<\n MetaTimestamp,\n MetaBrandedString\n >\n>\n// => Date & { brand: \"timestamp\" }\n```\n\nIn representable [exclusions](#exclude):\n\n- If the source meta-type is not serialized, the resulting exclusion is not serialized.\n- If the source meta-type is serialized, the resulting exclusion inherits of its deserialization properties.\n\n## 🚧 Type constraints\n\nTo prevent errors, meta-types inputs are validated against type constraints:\n\n\n```typescript\ntype Invalid = M.Array<\n string // <= ❌ Meta-type expected\n>;\n```\n\nIf you need to use them, all type constraints are also exported:\n\n| Meta-type | Type constraint |\n| ------------- | :--------------------------------------------------------------------- |\n| `M.Any` | `M.AnyType` = `M.Any` |\n| `M.Never` | `M.NeverType` = `M.Never` |\n| `M.Const` | `M.ConstType` = `M.Const` |\n| `M.Enum` | `M.EnumType` = `M.Enum` |\n| `M.Primitive` | `M.PrimitiveType` = `M.Primitive` |\n| `M.Array` | `M.ArrayType` = `M.Array` |\n| `M.Tuple` | `M.TupleType` = `M.Tuple` |\n| `M.Object` | `M.ObjectType` = `M.Object, string, M.Type>` |\n| `M.Union` | `M.UnionType` = `M.Union` |\n| - | `M.Type` = Union of the above |\n\n## ✂️ Unsafe types and methods\n\nIn deep and self-referencing computations like in [json-schema-to-ts](https://github.com/ThomasAribart/json-schema-to-ts), type constraints can become an issue, as the compiler may not be able to confirm the input type validity ahead of usage.\n\n\n```typescript\ntype MyArray = M.Array<\n VeryDeepTypeComputation<\n ...\n > // <= 💥 Type constraint can break\n>\n```\n\nFor such cases, `ts-algebra` exposes **\"unsafe\"** types and methods, that behave the same as \"safe\" ones but removing any type constraints. If you use them, beware: The integrity of the compiling is up to you 😉\n\n| Safe | Unsafe |\n| ------------- | -------------- |\n| `M.Any` | - |\n| `M.Never` | - |\n| `M.Const` | - |\n| `M.Enum` | - |\n| `M.Primitive` | `M.$Primitive` |\n| `M.Array` | `M.$Array` |\n| `M.Tuple` | `M.$Tuple` |\n| `M.Object` | `M.$Object` |\n| `M.Union` | `M.$Union` |\n| `M.Resolve` | `M.$Resolve` |\n| `M.Intersect` | `M.$Intersect` |\n| `M.Exclude` | `M.$Exclude` |\n","readmeFilename":"README.md"}