├── .eslintrc.js ├── .gitignore ├── .vscode ├── launch.json ├── settings.json └── tasks.json ├── LICENSE ├── README.md ├── jest.config.js ├── package.json ├── pnpm-lock.yaml ├── scripts ├── build │ ├── index.sh │ └── watch.sh └── test │ ├── index.sh │ ├── performance.sh │ └── watch.sh ├── src ├── algebraic │ ├── common │ │ ├── bindOf.ts │ │ ├── bindTo.ts │ │ ├── pipe.ts │ │ ├── sequence.ts │ │ ├── sequenceTuple.ts │ │ └── tap.ts │ ├── defs │ │ ├── Applicative.ts │ │ ├── Apply.ts │ │ ├── Bifunctor.ts │ │ ├── Chain.ts │ │ ├── Foldable.ts │ │ ├── Functor.ts │ │ ├── Monoid.ts │ │ ├── Semigroup.ts │ │ └── Traversable.ts │ ├── index.ts │ └── types │ │ ├── Array │ │ ├── Applicative.ts │ │ ├── Apply.ts │ │ ├── Array.ts │ │ ├── Foldable.ts │ │ ├── Functions.ts │ │ ├── Functor.ts │ │ ├── Traversable.ts │ │ └── index.ts │ │ ├── Async │ │ ├── Applicative.ts │ │ ├── Apply.ts │ │ ├── Async.ts │ │ ├── Chain.ts │ │ ├── Functions.ts │ │ ├── Functor.ts │ │ └── index.ts │ │ ├── AsyncEither │ │ ├── Applicative.ts │ │ ├── Apply.ts │ │ ├── AsyncEither.ts │ │ ├── Chain.ts │ │ ├── Functions.ts │ │ ├── Functor.ts │ │ └── index.ts │ │ ├── AsyncResult │ │ ├── Applicative.ts │ │ ├── Apply.ts │ │ ├── AsyncResult.ts │ │ ├── Chain.ts │ │ ├── Functions.ts │ │ ├── Functor.ts │ │ └── index.ts │ │ ├── Either │ │ ├── Applicative.ts │ │ ├── Apply.ts │ │ ├── Chain.ts │ │ ├── Either.ts │ │ ├── Functions.ts │ │ ├── Functor.ts │ │ └── index.ts │ │ ├── Maybe │ │ ├── Applicative.ts │ │ ├── Apply.ts │ │ ├── Chain.ts │ │ ├── Functions.ts │ │ ├── Functor.ts │ │ ├── Maybe.ts │ │ └── index.ts │ │ ├── NonEmptyArray │ │ ├── Functor.ts │ │ ├── NonEmptyArray.ts │ │ └── index.ts │ │ └── Result │ │ ├── Applicative.ts │ │ ├── Apply.ts │ │ ├── Chain.ts │ │ ├── Functions.ts │ │ ├── Functor.ts │ │ ├── Result.ts │ │ └── index.ts ├── common │ ├── identity.ts │ └── index.ts ├── hkt │ └── index.ts ├── index.ts └── runtime │ ├── defs │ └── index.ts │ ├── index.ts │ ├── introspection.ts │ └── types │ ├── Array │ ├── Array.ts │ ├── Checkable.ts │ └── checks │ │ └── isGreaterThan.ts │ ├── Boolean │ ├── Boolean.ts │ └── Checkable.ts │ ├── Intersect │ ├── Checkable.ts │ └── Intersect.ts │ ├── Literal │ ├── Checkable.ts │ └── Literal.ts │ ├── Number │ ├── Checkable.ts │ ├── Number.ts │ └── checks │ │ └── isGreaterThan.ts │ ├── Partial │ ├── Checkable.ts │ └── Partial.ts │ ├── Record │ ├── Checkable.ts │ └── Record.ts │ ├── String │ ├── Checkable.ts │ ├── String.ts │ ├── checks │ │ └── isGreaterThan.ts │ └── index.ts │ ├── Tuple │ ├── Checkable.ts │ └── Tuple.ts │ └── Union │ ├── Checkable.ts │ └── Union.ts ├── tests ├── algebraic │ ├── Async │ │ └── Functions.test.ts │ ├── AsyncEither │ │ └── Functions.test.ts │ ├── AsyncResult │ │ └── Functions.test.ts │ ├── Either │ │ └── Functions.test.ts │ ├── Maybe │ │ └── Functions.test.ts │ ├── Result │ │ └── Functions.test.ts │ └── common │ │ ├── sequenceTuple.performance.ts │ │ ├── sequenceTuple.test.ts │ │ └── tap.test.ts └── runtime │ ├── 1Examples │ └── Sports.test.ts │ ├── Array │ └── Array.test.ts │ ├── Boolean │ └── Boolean.test.ts │ ├── Intersect │ └── Intersect.test.ts │ ├── Literal │ └── Literal.test.ts │ ├── Number │ └── Number.test.ts │ ├── Partial │ └── Partial.test.ts │ ├── Record │ └── Record.test.ts │ ├── String │ └── String.test.ts │ ├── Tuple │ └── Tuple.test.ts │ └── Union │ └── Union.test.ts ├── tsconfig.build.json ├── tsconfig.esm.json ├── tsconfig.jest.json └── tsconfig.json /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parser: '@typescript-eslint/parser', 4 | plugins: ['@typescript-eslint'], 5 | extends: [ 6 | 'eslint:recommended', 7 | 'plugin:@typescript-eslint/eslint-recommended', 8 | 'plugin:@typescript-eslint/recommended', 9 | ], 10 | rules: { 11 | '@typescript-eslint/no-array-constructor': "off", 12 | 'no-unexpected-multiline': "off", 13 | '@typescript-eslint/ban-types': "off", 14 | "@typescript-eslint/explicit-function-return-type": "off", 15 | '@typescript-eslint/no-use-before-define': "off", 16 | '@typescript-eslint/no-empty-interface': "off", 17 | quotes: [ 18 | 'error', 19 | 'single', 20 | { allowTemplateLiterals: true }, 21 | ], 22 | 'func-call-spacing': [ 23 | 'error', 24 | 'always', 25 | { allowNewlines: true }, 26 | ], 27 | }, 28 | }; 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/node_modules 2 | cjs/ 3 | esm/ 4 | **/*.tsbuildinfo 5 | pnpm-debug.log -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "node", 9 | "request": "attach", 10 | "name": "Launch Program", 11 | "outFiles": [ 12 | "${workspaceFolder}/cjs/**/*.js" 13 | ] 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.formatOnSave": false, 3 | "editor.codeActionsOnSave": { 4 | "source.fixAll": true, 5 | "source.fixAll.eslint": true 6 | }, 7 | "typescript.tsdk": "node_modules/typescript/lib" 8 | } 9 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "build", 8 | "type": "shell", 9 | "command": "pnpm run build", // Could be any other shell command 10 | }, 11 | ] 12 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2020 Antonio Mayrinck Moura 4 | 5 | Permission is hereby granted, free of charge, to any person 6 | obtaining a copy of this software and associated documentation 7 | files (the "Software"), to deal in the Software without 8 | restriction, including without limitation the rights to use, 9 | copy, modify, merge, publish, distribute, sublicense, and/or 10 | sell copies of the Software, and to permit persons to whom the 11 | Software is furnished to do so, subject to the following 12 | conditions: 13 | 14 | The above copyright notice and this permission notice shall be 15 | included in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 19 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 21 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24 | OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 🦸 λΔ super-ts 2 | 3 | > [!WARNING] 4 | > Hey there, just a heads-up: I've stopped updating this repo. If you're diving into functional programming—like monads, higher kinded types, and all that fun stuff—in TypeScript, you might find some handy insights here. But a little word of caution: it's probably not the best fit for production use. Happy coding! 5 | 6 | --- 7 | 8 | [![npm version](https://img.shields.io/npm/v/super-ts.svg)](https://www.npmjs.com/package/super-ts) 9 | 10 | **super-ts** is a Typescript functional programming library inspired by [Haskell](https://www.haskell.org/) and [PureScript](http://www.purescript.org/) providing both runtime type checking and functional algebraic data types. 11 | 12 | **super-ts** were built to unify concepts and tools of some wonderful libraries, such _[fp-ts](https://github.com/gcanti/fp-ts)_, _[io-ts](https://github.com/gcanti/io-ts)_ and _[runtypes](https://github.com/pelotom/runtypes)_. 13 | 14 | Forwarding to be an all-in-one solution, **super-ts** is divided into two main categories: **Algebraic Types** & **Runtime Types**; 15 | 16 | - _Runtime Types_: static and runtime type checking 17 | - _Algebraic Types_: Monads, Functors, Semigroups and others. 18 | 19 | ## Instalation 20 | 21 | `npm install super-ts` will install super-ts for use. 22 | 23 | ## Consuming 24 | 25 | You can use **super-ts** in two flavors: CommonJS or ES Modules. 26 | 27 | ```ts 28 | import { String } from "super-ts/cjs/runtime"; 29 | import { Either } from "super-ts/cjs/algebraic"; 30 | ``` 31 | 32 | ```ts 33 | import { String } from "super-ts/esm/runtime"; 34 | import { Either } from "super-ts/esm/algebraic"; 35 | ``` 36 | 37 | PS: If you are using the package with ES Modules over **node** you should run your application with the flag `--experimental-specifier-resolution=node` 38 | 39 | ES Modules enables [tree shaking](https://webpack.js.org/guides/tree-shaking/) to be possible using bundlers. 40 | 41 | ## Δ Runtime Types 42 | 43 | **super-ts** provides you with primitive types that can be safely type-checked at runtime with custom constraints and use this same schema as your Typescript static type signature. You can also provide custom runtime checks to build more advanced types that fit your use cases. 44 | 45 | ### Δ Why is useful? 46 | 47 | Let's suppose that you have the following static type schema on your Typescript project: 48 | 49 | ```ts 50 | type League = "NFL" | "MLB" | "NBA" | "WNBA"; 51 | 52 | type Gender = "Male" | "Female" | "Other"; 53 | 54 | type Team = { 55 | name: string; 56 | yearFounded: number; 57 | league: League; 58 | type: "team"; 59 | }; 60 | 61 | type Player = { 62 | firstName: string; 63 | lastName: string; 64 | salaryOnTeam: [number, Team]; 65 | age: number; 66 | isActive: boolean; 67 | teamsPlayed: Team[]; 68 | gender: Gender; 69 | type: "player"; 70 | }; 71 | ``` 72 | 73 | This works fine on TypeScript since you use this schema to type safe your application on compile time, but what about runtime? What happens if you receive this schema as a payload from some external source? 74 | 75 | In this scenario your application is unsafe and you need to do a lot of validations to avoid runtime errors. 76 | 77 | ‌To avoid all this boring work you can use **super-ts** runtime types to define your schema keeping your application safe on runtime as well on compile time, re-using static types generated by **super-ts**. 78 | 79 | ### Δ Example (Defining schema with _super-ts_) 80 | 81 | In order to define the same schema as above using _super-ts_ we do the following: 82 | 83 | ```ts 84 | import { 85 | String, 86 | Number, 87 | Boolean, 88 | Array, 89 | Record, 90 | Literal, 91 | Tuple, 92 | Union, 93 | } from "super-ts/esm/runtime"; 94 | 95 | const League = Union( 96 | Literal("NFL"), 97 | Literal("MLB"), 98 | Literal("NBA"), 99 | Literal("WNBA") 100 | ); 101 | 102 | const Gender = Union(Literal("Male"), Literal("Female"), Literal("Other")); 103 | 104 | const Team = Record({ 105 | name: String, 106 | yearFounded: Number, 107 | league: League, 108 | type: Literal("team"), 109 | }); 110 | 111 | const Player = Record({ 112 | firstName: String, 113 | lastName: String, 114 | salaryOnTeam: Tuple(Number, Team), 115 | age: Number, 116 | isActive: Boolean, 117 | teamsPlayed: Array(Team), 118 | gender: Gender, 119 | type: Literal("player"), 120 | }); 121 | ``` 122 | 123 | When you define your schema using **super-ts** you can get Typescript static types using the custom `TypeOf` type. 124 | 125 | ```ts 126 | import { TypeOf } from 'super-ts/esm/runtime' 127 | 128 | type Player = TypeOf; 129 | 130 | // type Player = { 131 | // firstName: string; 132 | // lastName: string; 133 | // salaryOnTeam: [number, { 134 | // name: string; 135 | // yearFounded: number; 136 | // league: "NFL" | "MLB" | "NBA" | "WNBA"; 137 | // type: "team"; 138 | // }]; 139 | // age: number; 140 | // isActive: boolean; 141 | // teamsPlayed: { 142 | // ...; 143 | // }[]; 144 | // gender: "Male" | "Female" | "Other"; 145 | // type: "player"; 146 | // } 147 | 148 | 149 | ``` 150 | 151 | ### Δ API 152 | 153 | When you use the runtime types, we expose an API under the property `.Δ` so you can use functions available for the type. 154 | 155 | #### `check :: a -⁠> Resultλ InvalidCheck a` 156 | 157 | Takes an unknown payload and validates against the type. If the validation suceeds, 158 | we return an algebraic type called _Resultλ_ of _Sucess_ which contains the payload. 159 | If the check fails we return an _Resultλ_ of _Failure_ containing an _NonEmptyArrayλ_ 160 | of _InvalidCheck_ containing all the errors found on that payload. 161 | 162 | **Example** 163 | 164 | ```ts 165 | import { identity } from 'super-ts/common/identity'; 166 | import { Result } from 'super-ts/algebraic'; 167 | 168 | /** other imports .. */ 169 | 170 | /** above code .. */ 171 | 172 | const Team = Record({ 173 | name: String, 174 | yearFounded: Number, 175 | league: League, 176 | type: Literal("team"), 177 | }); 178 | 179 | const teamInvalidPayload = { 180 | name: null, 181 | yearFounded: "1974", 182 | league: "NFL", 183 | type: "team", 184 | }; 185 | 186 | const isValidTeam = Team.Δ.check(teamInvalidPayload); 187 | 188 | const isValidTeamRes = Result.λ.fold (identity, identity) (isValidTeam); 189 | 190 | 191 | // isValidTeamRes = [ 192 | // { 193 | // code: 'IS_STRING', 194 | // message: 'Expected string but found (null :: object)', 195 | // path: 'name' 196 | // }, 197 | // { 198 | // code: 'IS_NUMBER', 199 | // message: 'Expected Number but found (1974 :: string)', 200 | // path: 'yearFounded' 201 | // } 202 | // ] 203 | 204 | ``` 205 | 206 | ## λ Algebraic Types 207 | 208 | This documentation is working in progress.. 😅 🚧 209 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | moduleDirectories: ['', 'node_modules'], 3 | moduleNameMapper: { 4 | '^@runtime/(.*)$': 'src/runtime/$1', 5 | '^@algebraic/(.*)$': 'src/algebraic/$1', 6 | '^@common/(.*)$': 'src/common/$1', 7 | }, 8 | preset: 'ts-jest', 9 | testEnvironment: 'node', 10 | globals: { 11 | 'ts-jest': { 12 | tsConfig: 'tsconfig.jest.json', 13 | packageJson: 'package.json', 14 | }, 15 | }, 16 | }; 17 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "super-ts", 3 | "version": "1.11.1", 4 | "description": "Typescript functional programming library inspired by Haskell and PureScript providing both runtime type checking and functional algebraic data types.", 5 | "main": "cjs/index.js", 6 | "module": "esm/index.mjs", 7 | "files": [ 8 | "cjs", 9 | "esm" 10 | ], 11 | "scripts": { 12 | "test": "scripty", 13 | "test:watch": "scripty", 14 | "test:performance": "scripty", 15 | "build": "scripty", 16 | "build:watch": "scripty", 17 | "prepublish": "pnpm run build && pnpm run test" 18 | }, 19 | "repository": { 20 | "type": "git", 21 | "url": "git+https://github.com/nthypes/super-ts.git" 22 | }, 23 | "keywords": [ 24 | "functional programming", 25 | "fantasy-land", 26 | "static-land", 27 | "fp-ts", 28 | "io-ts", 29 | "runtypes", 30 | "purescript", 31 | "haskell" 32 | ], 33 | "author": "Antonio Moura (nthypes)", 34 | "license": "MIT", 35 | "bugs": { 36 | "url": "https://github.com/nthypes/super-ts/issues" 37 | }, 38 | "homepage": "https://github.com/nthypes/super-ts#readme", 39 | "devDependencies": { 40 | "@ef-carbon/tspm": "^2.2.5", 41 | "@types/benchmark": "^1.0.33", 42 | "@types/jest": "^25.2.1", 43 | "@typescript-eslint/eslint-plugin": "^2.30.0", 44 | "@typescript-eslint/parser": "^2.30.0", 45 | "benchmark": "^2.1.4", 46 | "eslint": "^6.8.0", 47 | "jest": "^25.5.3", 48 | "nodemon": "^2.0.4", 49 | "scripty": "^2.0.0", 50 | "ts-jest": "^25.4.0", 51 | "ts-node": "^8.10.2", 52 | "tsc-watch": "^4.2.9", 53 | "tslib": "^2.0.0", 54 | "typescript": "^3.9.5" 55 | }, 56 | "scripty": { 57 | "silence": true 58 | }, 59 | "dependencies": { 60 | "@types/ramda": "^0.27.4", 61 | "ramda": "^0.27.0" 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /scripts/build/index.sh: -------------------------------------------------------------------------------- 1 | # Build CJS Modules 2 | rm -rf cjs 3 | node_modules/.bin/tsc -p tsconfig.build.json 4 | node_modules/.bin/ef-tspm -c tsconfig.build.json 5 | rm -rf cjs/tsconfig.build.tsbuildinfo 6 | 7 | # Build ES Modules 8 | rm -rf esm 9 | node_modules/.bin/tsc -p tsconfig.esm.json 10 | node_modules/.bin/ef-tspm -c tsconfig.esm.json 11 | find ./esm/ -name "*.js" -exec bash -c 'mv "$1" "${1%.js}".mjs' - '{}' \; 12 | rm -rf esm/tsconfig.esm.tsbuildinfo -------------------------------------------------------------------------------- /scripts/build/watch.sh: -------------------------------------------------------------------------------- 1 | # Build Watch CJS Modules 2 | node_modules/.bin/nodemon -e ts -w src \ 3 | -x 'node_modules/.bin/tsc -p tsconfig.build.json && node_modules/.bin/ef-tspm -c tsconfig.build.json && node cjs/index.js' -------------------------------------------------------------------------------- /scripts/test/index.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | bold=$(tput bold) 3 | normal=$(tput sgr0) 4 | 5 | set -e 6 | 7 | echo -e "👻 💉 ${bold}[funtypes/test]${normal} starting unit testing with jest.." 8 | jest --config jest.config.js --verbose -------------------------------------------------------------------------------- /scripts/test/performance.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | bold=$(tput bold) 3 | normal=$(tput sgr0) 4 | 5 | set -e 6 | 7 | echo -e "🧪 💉 ${bold}[super-ts/test:performance]${normal} starting performance test.." 8 | 9 | if [ $# -eq 0 ] 10 | then 11 | echo -e "[ 🛑 ] ERROR: You must inform a valid performance file. (ex: pnpm run test:performance tests/algebraic/common/sequenceTuple.performance.ts ) \n" 12 | exit 1 13 | fi 14 | 15 | node_modules/.bin/ts-node $1 -------------------------------------------------------------------------------- /scripts/test/watch.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | bold=$(tput bold) 3 | normal=$(tput sgr0) 4 | 5 | set -e 6 | 7 | echo -e "👻 💉 ${bold}[funtypes/test]${normal} starting unit testing with jest (watch mode).." 8 | 9 | node_modules/.bin/nodemon -e ts -w src -w tests \ 10 | -x 'jest --config jest.config.js --verbose' -------------------------------------------------------------------------------- /src/algebraic/common/bindOf.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * TODO: Add Comment 3 | */ 4 | type BindOfReturn = { 5 | [K in Property]: Value 6 | }; 7 | 8 | const bindOf = ( 9 | property: Property, 10 | value: Value 11 | ): BindOfReturn => ({[property]: value}) as any; 12 | 13 | export { bindOf } -------------------------------------------------------------------------------- /src/algebraic/common/bindTo.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * TODO: Add Comment 3 | */ 4 | type BindToReturn = { 5 | [K in keyof Previous | Property]: K extends keyof Previous 6 | ? Previous[K] 7 | : Value; 8 | }; 9 | 10 | const bindTo = ( 11 | previous: Previous, 12 | property: Exclude, 13 | value: Value 14 | ): BindToReturn => Object.assign ({}, previous, { [property]: value }) as any; 15 | 16 | export { bindTo } -------------------------------------------------------------------------------- /src/algebraic/common/pipe.ts: -------------------------------------------------------------------------------- 1 | 2 | export { pipe }; 3 | 4 | function pipe (a: A): A; 5 | function pipe (a: A, a2b: (a: A) => B): B; 6 | function pipe (a: A, a2b: (a: A) => B, b2c: (b: B) => C): C; 7 | function pipe (a: A, a2b: (a: A) => B, b2c: (b: B) => C, c2d: (c: C) => D): D; 8 | function pipe ( 9 | a: A, a2b: (a: A) => B, 10 | b2c: (b: B) => C, 11 | c2d: (c: C) => D, 12 | d2e: (d: D) => E 13 | ): E; 14 | function pipe ( 15 | a: A, a2b: (a: A) => B, 16 | b2c: (b: B) => C, 17 | c2d: (c: C) => D, 18 | d2e: (d: D) => E, 19 | e2f: (e: E) => F 20 | ): F; 21 | function pipe ( 22 | a: A, a2b: (a: A) => B, 23 | b2c: (b: B) => C, 24 | c2d: (c: C) => D, 25 | d2e: (d: D) => E, 26 | e2f: (f: E) => F, 27 | f2g: (e: F) => G 28 | ): G; 29 | function pipe ( 30 | a: A, a2b: (a: A) => B, 31 | b2c: (b: B) => C, 32 | c2d: (c: C) => D, 33 | d2e: (d: D) => E, 34 | e2f: (e: E) => F, 35 | f2g: (f: F) => G, 36 | g2h: (g: G) => H 37 | ): H; 38 | function pipe ( 39 | a: A, a2b: (a: A) => B, 40 | b2c: (b: B) => C, 41 | c2d: (c: C) => D, 42 | d2e: (d: D) => E, 43 | e2f: (e: E) => F, 44 | f2g: (f: F) => G, 45 | g2h: (g: G) => H, 46 | h2i: (h: H) => I 47 | ): I; 48 | function pipe ( 49 | a: A, a2b: (a: A) => B, 50 | b2c: (b: B) => C, 51 | c2d: (c: C) => D, 52 | d2e: (d: D) => E, 53 | e2f: (e: E) => F, 54 | f2g: (f: F) => G, 55 | g2h: (g: G) => H, 56 | h2i: (h: H) => I, 57 | i2j: (i: I) => J 58 | ): J; 59 | function pipe ( 60 | a: A, a2b: (a: A) => B, 61 | b2c: (b: B) => C, 62 | c2d: (c: C) => D, 63 | d2e: (d: D) => E, 64 | e2f: (e: E) => F, 65 | f2g: (f: F) => G, 66 | g2h: (g: G) => H, 67 | h2i: (h: H) => I, 68 | i2j: (i: I) => J, 69 | i2k: (j: J) => K 70 | ): K; 71 | 72 | function pipe(a: any, ...fns: ((...args: any[]) => any)[]): any { 73 | if(fns.length > 0) { 74 | return fns.reduce ((prev, fn) => fn (prev), a); 75 | } 76 | return a; 77 | } 78 | -------------------------------------------------------------------------------- /src/algebraic/common/sequence.ts: -------------------------------------------------------------------------------- 1 | import { ApplicativeOf1, ApplicativeOf2 } from '@algebraic/defs/Applicative'; 2 | import { ApplyOf1, ApplyOf2 } from '@algebraic/defs/Apply'; 3 | import { Kind1, Kind2, Types1, Types2 } from '@hkt'; 4 | 5 | /** 6 | * TODO: Add Comment 7 | */ 8 | 9 | function sequence( 10 | p1: ApplicativeOf1 & ApplyOf1 11 | ): (p2: Array>) => Kind1>; 12 | 13 | function sequence( 14 | p1: ApplicativeOf2 & ApplyOf2 15 | ): (p2: Array>) => Kind2>; 16 | 17 | function sequence( 18 | adtModule: ApplicativeOf1 & ApplyOf1 19 | ) { 20 | return function (adtInstances: Array>): Kind1> { 21 | return adtInstances.reduce ( 22 | (pv, cv) => 23 | adtModule.λ.ap (adtModule.λ.map ((as: B[]) => (b: B) => [...as, b]) (pv)) ( 24 | cv 25 | ), 26 | adtModule.λ.of ([]) 27 | ); 28 | }; 29 | } 30 | 31 | export { sequence }; 32 | -------------------------------------------------------------------------------- /src/algebraic/common/sequenceTuple.ts: -------------------------------------------------------------------------------- 1 | import { ApplicativeOf1, ApplicativeOf2 } from '@algebraic/defs/Applicative'; 2 | import { ApplyOf1, ApplyOf2 } from '@algebraic/defs/Apply'; 3 | import { Kind1, Kind2, Types1, Types2 } from '@hkt'; 4 | 5 | /** 6 | * TODO: Add Comment 7 | */ 8 | 9 | function sequenceTuple( 10 | p1: ApplicativeOf2 & ApplyOf2 11 | ): >>( 12 | ...p2: Z & { 0: Kind2 } 13 | ) => Kind2< 14 | A, 15 | Z extends Array> ? B : never, 16 | { 17 | [K in keyof Z]: [Z[K]] extends [Kind2] ? X : never; 18 | } 19 | >; 20 | 21 | function sequenceTuple( 22 | p1: ApplicativeOf1 & ApplyOf1 23 | ): >>( 24 | ...p2: Z & { 0: Kind1 } 25 | ) => Kind1< 26 | A, 27 | { [K in keyof Z]: [[K]] extends [Kind1] ? X : never } 28 | >; 29 | 30 | function sequenceTuple(adtModule: ApplicativeOf1 & ApplyOf1) { 31 | return function (...adtInstances: Kind1[]): any { 32 | return adtInstances.reduce ( 33 | (pv, cv) => adtModule.λ.ap (pv) (cv), 34 | adtModule.λ.of (constructFn (adtInstances.length, [])) 35 | ); 36 | }; 37 | } 38 | 39 | const constructFn = (currentSize: number, acc: any[]) => { 40 | return function (x: unknown) { 41 | return currentSize > 1 42 | ? constructFn (currentSize - 1, [...acc, x]) 43 | : [...acc, x]; 44 | } 45 | 46 | } 47 | 48 | export { sequenceTuple }; 49 | -------------------------------------------------------------------------------- /src/algebraic/common/tap.ts: -------------------------------------------------------------------------------- 1 | import { ChainOf1, ChainOf2 } from '@algebraic/defs/Chain'; 2 | import { Kind1, Types1, Types2, Kind2 } from '@hkt'; 3 | 4 | /** 5 | * tap :: Chain b => (a -> unit) -> b -> b 6 | * 7 | * Tap is an **impure** and **unsafe** Operation that performs side effects. 8 | * It's recommend only for **DEBUG** purposes. 9 | */ 10 | 11 | function tap( 12 | p1: ChainOf1 13 | ): (p2: (b: B) => void) => (p3: Kind1) => Kind1; 14 | 15 | function tap( 16 | p1: ChainOf2 17 | ): (p2: (c: C) => void) => (p3: Kind2) => Kind2; 18 | 19 | 20 | function tap( 21 | p1: ChainOf1 22 | ) { 23 | return function (p2: (b: B) => void) { 24 | return function (p3: Kind1): Kind1 { 25 | return p1.λU.map ((a) => { 26 | p2 (a) 27 | return a; 28 | }, p3) 29 | } 30 | }; 31 | } 32 | 33 | export { tap }; 34 | 35 | -------------------------------------------------------------------------------- /src/algebraic/defs/Applicative.ts: -------------------------------------------------------------------------------- 1 | import { HKT1, Kind1, Kind2, Types1, Types2 } from '@hkt'; 2 | import { Apply, ApplyOf1, ApplyOf2 } from './Apply'; 3 | 4 | interface Applicative extends Apply { 5 | λ: { 6 | readonly kind: Type; 7 | readonly of: (a: A) => HKT1; 8 | readonly ap: Apply['λ']['ap']; 9 | readonly map: Apply['λ']['map']; 10 | }; 11 | } 12 | 13 | interface ApplicativeOf1 extends ApplyOf1 { 14 | λ: { 15 | readonly kind: Type; 16 | readonly of: (a: A) => Kind1; 17 | readonly ap: ApplyOf1['λ']['ap']; 18 | readonly map: ApplyOf1['λ']['map']; 19 | }; 20 | } 21 | 22 | interface ApplicativeOf2 extends ApplyOf2 { 23 | λ: { 24 | readonly kind: Type; 25 | readonly of: (a: B) => Kind2; 26 | readonly ap: ApplyOf2['λ']['ap']; 27 | readonly map: ApplyOf2['λ']['map']; 28 | }; 29 | } 30 | 31 | export { Applicative, ApplicativeOf1, ApplicativeOf2 }; 32 | -------------------------------------------------------------------------------- /src/algebraic/defs/Apply.ts: -------------------------------------------------------------------------------- 1 | import { HKT1, Kind1, Kind2, Types1, Types2 } from '@hkt'; 2 | import { Functor, FunctorOf1, FunctorOf2 } from './Functor'; 3 | 4 | interface Apply extends Functor { 5 | λ: { 6 | readonly kind: Type; 7 | readonly map: Functor['λ']['map']; 8 | readonly ap: ( 9 | p1: HKT1 B> 10 | ) => (p2: HKT1) => HKT1; 11 | }; 12 | } 13 | 14 | interface ApplyOf1 extends FunctorOf1 { 15 | λ: { 16 | readonly kind: Type; 17 | readonly map: FunctorOf1['λ']['map']; 18 | readonly ap: ( 19 | p1: Kind1 B> 20 | ) => (p2: Kind1) => Kind1; 21 | }; 22 | } 23 | 24 | interface ApplyOf2 extends FunctorOf2 { 25 | λ: { 26 | readonly kind: Type; 27 | readonly map: FunctorOf2['λ']['map']; 28 | readonly ap: ( 29 | p1: Kind2 C> 30 | ) => (p2: Kind2) => Kind2; 31 | }; 32 | } 33 | 34 | export { Apply, ApplyOf1, ApplyOf2 }; 35 | -------------------------------------------------------------------------------- /src/algebraic/defs/Bifunctor.ts: -------------------------------------------------------------------------------- 1 | import { HKT2, Kind2, Types2 } from '@hkt'; 2 | 3 | interface Bifunctor { 4 | λ: { 5 | readonly kind: Type; 6 | readonly bimap: ( 7 | p1: (a: A) => C 8 | ) => (p2: (a: B) => D) => (p3: HKT2) => HKT2; 9 | }; 10 | } 11 | 12 | interface BifunctorOf2 { 13 | λ: { 14 | readonly kind: Type; 15 | readonly bimap: ( 16 | p1: (a: A) => C 17 | ) => (p2: (a: B) => D) => (p3: Kind2) => Kind2; 18 | }; 19 | λU: { 20 | readonly kind: Type; 21 | readonly bimap: ( 22 | p1: (a: A) => C, 23 | p2: (a: B) => D, 24 | p3: Kind2 25 | ) => Kind2; 26 | }; 27 | } 28 | 29 | export { Bifunctor, BifunctorOf2 }; 30 | -------------------------------------------------------------------------------- /src/algebraic/defs/Chain.ts: -------------------------------------------------------------------------------- 1 | import { Kind1, Types1, Types2, Kind2 } from '@hkt'; 2 | import { ApplyOf2, ApplyOf1 } from './Apply'; 3 | 4 | 5 | interface ChainOf1 extends ApplyOf1 { 6 | λ: { 7 | readonly kind: Type; 8 | readonly map: ApplyOf1['λ']['map']; 9 | readonly ap: ApplyOf1['λ']['ap']; 10 | readonly chain: (p1: (a: A) => Kind1) 11 | => (p2: Kind1) 12 | => Kind1; 13 | }; 14 | λU: { 15 | readonly kind: Type; 16 | readonly map: ApplyOf1['λU']['map']; 17 | readonly chain: (p1: (a: A) => Kind1, p2: Kind1) => Kind1; 18 | }; 19 | } 20 | 21 | interface ChainOf2 extends ApplyOf2 { 22 | λ: { 23 | readonly kind: Type; 24 | readonly map: ApplyOf2['λ']['map']; 25 | readonly ap: ApplyOf2['λ']['ap']; 26 | readonly chain: (p1: (b: B) => Kind2) 27 | => (p2: Kind2) 28 | => Kind2; 29 | }; 30 | λU: { 31 | readonly kind: Type; 32 | readonly map: ApplyOf2['λU']['map']; 33 | readonly chain: (p1: (b: B) => Kind2, p2: Kind2) => Kind2; 34 | }; 35 | } 36 | 37 | 38 | export { ChainOf1, ChainOf2 }; 39 | -------------------------------------------------------------------------------- /src/algebraic/defs/Foldable.ts: -------------------------------------------------------------------------------- 1 | import { HKT1, Types1, Kind1, Types2, Kind2 } from '@hkt'; 2 | import { Monoid } from './Monoid'; 3 | 4 | interface Foldable { 5 | λ: { 6 | readonly kind: Type; 7 | 8 | readonly reduce: (p1: (a: A, b: B) => A) 9 | => (p2: A) 10 | => (p3: HKT1) 11 | => A; 12 | 13 | readonly foldMap: (p1: Monoid) 14 | => (p2: (b: B) => A) 15 | => (p3: HKT1) 16 | => A; 17 | }; 18 | } 19 | 20 | interface FoldableOf1 { 21 | λ: { 22 | readonly kind: Type; 23 | 24 | readonly reduce: (p1: (a: A, b: B) => A) 25 | => (p2: A) 26 | => (p3: Kind1) 27 | => A; 28 | 29 | readonly foldMap: (p1: Monoid) 30 | => (p2: (b: B) => A) 31 | => (p3: Kind1) 32 | => A; 33 | }; 34 | } 35 | 36 | interface FoldableOf2 { 37 | λ: { 38 | readonly kind: Type; 39 | 40 | readonly reduce: (p1: (a: A, b: B) => A) 41 | => (p2: A) 42 | => (p3: Kind2) 43 | => C; 44 | 45 | readonly foldMap: (p1: Monoid) 46 | => (p2: (c: C) => A) 47 | => (p3: Kind2) 48 | => A; 49 | }; 50 | } 51 | 52 | export { Foldable, FoldableOf1, FoldableOf2 }; 53 | -------------------------------------------------------------------------------- /src/algebraic/defs/Functor.ts: -------------------------------------------------------------------------------- 1 | import { HKT1, Types1, Kind1, Types2, Kind2 } from '@hkt'; 2 | 3 | interface Functor { 4 | λ: { 5 | readonly kind: Type; 6 | readonly map: ( 7 | p1: (a: A) => B 8 | ) => (p2: HKT1) => HKT1; 9 | }; 10 | } 11 | 12 | interface FunctorOf1 { 13 | λ: { 14 | readonly kind: Type; 15 | readonly map: (p1: (a: A) => B) 16 | => (p2: Kind1) 17 | => Kind1; 18 | }; 19 | λU: { 20 | readonly kind: Type; 21 | readonly map: (p1: (a: A) => B, p2: Kind1) => Kind1; 22 | }; 23 | } 24 | 25 | interface FunctorOf2 { 26 | λ: { 27 | readonly kind: Type; 28 | readonly map: (p1: (b: B) => C) 29 | => (p2: Kind2) 30 | => Kind2; 31 | }; 32 | λU: { 33 | readonly kind: Type; 34 | readonly map: (p1: (b: B) => C, p2: Kind2) => Kind2; 35 | }; 36 | } 37 | 38 | export { Functor, FunctorOf1, FunctorOf2 }; 39 | -------------------------------------------------------------------------------- /src/algebraic/defs/Monoid.ts: -------------------------------------------------------------------------------- 1 | import { Semigroup } from './Semigroup'; 2 | 3 | interface Monoid extends Semigroup { 4 | λ: { 5 | readonly kind: Type; 6 | readonly empty: Type; 7 | readonly concat: Semigroup['λ']['concat']; 8 | }; 9 | } 10 | 11 | export { Monoid }; 12 | -------------------------------------------------------------------------------- /src/algebraic/defs/Semigroup.ts: -------------------------------------------------------------------------------- 1 | interface Semigroup { 2 | λ: { 3 | readonly kind: Type; 4 | readonly concat: (p1: Type) => (p2: Type) => Type; 5 | }; 6 | } 7 | 8 | export { Semigroup }; 9 | -------------------------------------------------------------------------------- /src/algebraic/defs/Traversable.ts: -------------------------------------------------------------------------------- 1 | import { HKT1, Kind1, Types1, Types2, Kind2 } from '@hkt'; 2 | import { 3 | Applicative, 4 | ApplicativeOf1, 5 | ApplicativeOf2 6 | } from './Applicative'; 7 | import { Foldable, FoldableOf1 } from './Foldable'; 8 | import { Functor, FunctorOf1 } from './Functor'; 9 | 10 | interface Traversable extends Functor, Foldable { 11 | λ: { 12 | readonly kind: Type; 13 | readonly map: Functor['λ']['map']; 14 | readonly reduce: Foldable['λ']['reduce']; 15 | readonly foldMap: Foldable['λ']['foldMap']; 16 | readonly traverse: Traverse; 17 | }; 18 | } 19 | 20 | interface TraversableOf1 extends FunctorOf1, FoldableOf1 { 21 | λ: { 22 | readonly kind: Type; 23 | readonly map: FunctorOf1['λ']['map']; 24 | readonly reduce: FoldableOf1['λ']['reduce']; 25 | readonly foldMap: FoldableOf1['λ']['foldMap']; 26 | readonly traverse: TraverseOf1; 27 | }; 28 | } 29 | 30 | interface Traverse { 31 | (p1: ApplicativeOf2): (p2: (b: B) => Kind2) => (p3: HKT1) => Kind2>; 32 | (p1: ApplicativeOf1): (p2: (b: B) => Kind1) => (p3: HKT1) => Kind1>; 33 | (p1: Applicative): (p2: (b: B) => HKT1) => (p3: HKT1) => HKT1>; 34 | } 35 | 36 | interface TraverseOf1 { 37 | (p1: ApplicativeOf2): (p2: (b: B) => Kind2) => (p3: Kind1) => Kind2>; 38 | (p1: ApplicativeOf1): (p2: (b: B) => Kind1) => (p3: Kind1) => Kind1>; 39 | (p1: Applicative): (p2: (b: B) => HKT1) => (p3: Kind1) => HKT1>; 40 | } 41 | 42 | 43 | export { Traversable, TraversableOf1 }; 44 | -------------------------------------------------------------------------------- /src/algebraic/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Array } from '@algebraic/types/Array' 2 | export { default as Either } from '@algebraic/types/Either' 3 | export { default as Maybe } from '@algebraic/types/Maybe' 4 | export { default as NonEmptyArray } from '@algebraic/types/NonEmptyArray' 5 | export { default as Async } from '@algebraic/types/Async' 6 | export { default as AsyncEither } from '@algebraic/types/AsyncEither' 7 | export { default as Result } from '@algebraic/types/Result' -------------------------------------------------------------------------------- /src/algebraic/types/Array/Applicative.ts: -------------------------------------------------------------------------------- 1 | export { of }; 2 | 3 | /** 4 | * TODO: Add comment 5 | * 6 | * of :: a -> Array a 7 | */ 8 | const of = (a: A): Array => [a] 9 | 10 | -------------------------------------------------------------------------------- /src/algebraic/types/Array/Apply.ts: -------------------------------------------------------------------------------- 1 | import { flatten } from './Functions'; 2 | export { ap }; 3 | 4 | /** 5 | * TODO: Add comment 6 | * 7 | * ap :: Array (a -> b) -> Array a -> Array b 8 | */ 9 | const ap = (p1: Array<(a: A) => B>) => 10 | (p2: Array): Array => 11 | 12 | flatten (p1.map (r1 => p2.map (r2 => r1 (r2)))); -------------------------------------------------------------------------------- /src/algebraic/types/Array/Array.ts: -------------------------------------------------------------------------------- 1 | export { Array$λ, Arrayλ }; 2 | 3 | const Array$λ = 'Array'; 4 | type Array$λ = typeof Array$λ; 5 | type Arrayλ = Array; 6 | 7 | declare module '../../../hkt' { 8 | interface Type2Kind1 { 9 | readonly [Array$λ]: Array; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/algebraic/types/Array/Foldable.ts: -------------------------------------------------------------------------------- 1 | import { Monoid } from "@algebraic/defs/Monoid"; 2 | 3 | export { reduce, foldMap }; 4 | 5 | /** 6 | * TODO: Add comment 7 | * 8 | * reduce :: (b -> a -> b) -> b -> Array a -> b 9 | */ 10 | 11 | const reduce = (p1: (b: B, a: A) => B) => (p2: B) => (p3: Array): B => 12 | p3.reduce(p1, p2); 13 | 14 | /** 15 | * TODO: Add comment 16 | * 17 | * foldMap :: (Monoid a) => TypeRep a -> (b -> a) -> Array b -> a 18 | */ 19 | 20 | const foldMap = (p1: Monoid) => (p2: (b: B) => A) => ( 21 | p3: Array 22 | ): A => p3.reduce((pv, cv) => p1.λ.concat(pv)(p2(cv)), p1.λ.empty); 23 | -------------------------------------------------------------------------------- /src/algebraic/types/Array/Functions.ts: -------------------------------------------------------------------------------- 1 | import { Maybeλ } from '../Maybe/Maybe' 2 | import { Arrayλ } from './Array' 3 | import Maybe from '../Maybe' 4 | 5 | export { flatten, head, isEmpty } 6 | 7 | /** 8 | * TODO: Add comment 9 | * 10 | * flatten :: Array Array a -> Array a 11 | */ 12 | const flatten = (p1: Array>): Array => 13 | 14 | ([] as Array).concat (...p1) 15 | 16 | /** 17 | * TODO: Add comment 18 | * 19 | * head :: Array a -> Maybe a 20 | */ 21 | const head = (p1: Arrayλ): Maybeλ => 22 | 23 | isEmpty (p1) 24 | ? Maybe.λ.Nothing 25 | : Maybe.λ.Just (p1[0]) 26 | 27 | /** 28 | * TODO: Add comment 29 | * 30 | * head :: Array a -> Maybe a 31 | */ 32 | const isEmpty = (p1: Arrayλ): boolean => p1.length === 0; -------------------------------------------------------------------------------- /src/algebraic/types/Array/Functor.ts: -------------------------------------------------------------------------------- 1 | export { map, mapU }; 2 | 3 | /** 4 | * TODO: Add comment 5 | * 6 | * map :: (a -> b) -> Array a -> Array b 7 | */ 8 | const map = (p1: (a: A) => B) => 9 | (p2: Array): Array => 10 | 11 | mapU (p1, p2) 12 | 13 | /** 14 | * TODO: Add comment 15 | * 16 | * map :: (a -> b) -> Array a -> Array b 17 | */ 18 | const mapU = (p1: (a: A) => B, p2: Array): Array => 19 | 20 | p2.map (p1); 21 | 22 | -------------------------------------------------------------------------------- /src/algebraic/types/Array/Traversable.ts: -------------------------------------------------------------------------------- 1 | import { HKT1 } from "@hkt"; 2 | import { Applicative } from "@algebraic/defs/Applicative"; 3 | 4 | /** 5 | * TODO: Add comment 6 | * 7 | * traverse :: (Applicative f, Traversable t) => TypeRep f -> (a -> f b) -> t a -> f (t b) 8 | */ 9 | const traverse = (p1: Applicative) => ( 10 | p2: (b: B) => HKT1 11 | ) => (p3: Array): HKT1> => { 12 | const initialValue = p1.λ.of([]); 13 | const mapToApply = (pv: HKT1) => 14 | p1.λ.map C[]>((c1) => (c2) => [...c1, c2])(pv); 15 | const callbackFn = (pv: HKT1, cv: B) => 16 | p1.λ.ap(mapToApply(pv))(p2(cv)); 17 | 18 | return p3.reduce(callbackFn, initialValue); 19 | }; 20 | 21 | export { traverse }; 22 | -------------------------------------------------------------------------------- /src/algebraic/types/Array/index.ts: -------------------------------------------------------------------------------- 1 | import type { ApplicativeOf1 } from '@algebraic/defs/Applicative'; 2 | import type { FunctorOf1 } from '@algebraic/defs/Functor'; 3 | import { TraversableOf1 } from '@algebraic/defs/Traversable'; 4 | import { of } from './Applicative'; 5 | import { Array$λ } from './Array'; 6 | import { map, mapU } from './Functor'; 7 | import { ap } from './Apply'; 8 | import { reduce, foldMap } from './Foldable'; 9 | import { traverse } from './Traversable'; 10 | 11 | type ArrayModule = ApplicativeOf1 & 12 | FunctorOf1 & 13 | TraversableOf1; 14 | 15 | const ArrayModule: ArrayModule = { 16 | λ: { 17 | kind: Array$λ, 18 | of, 19 | map, 20 | ap, 21 | reduce, 22 | foldMap, 23 | traverse, 24 | }, 25 | λU: { 26 | kind: Array$λ, 27 | map: mapU, 28 | }, 29 | }; 30 | 31 | export default ArrayModule; 32 | -------------------------------------------------------------------------------- /src/algebraic/types/Async/Applicative.ts: -------------------------------------------------------------------------------- 1 | import type { Asyncλ } from './Async'; 2 | 3 | export { of }; 4 | 5 | /** 6 | * TODO: Add comment 7 | */ 8 | const of = (p1: A): Asyncλ => () => Promise.resolve (p1); 9 | -------------------------------------------------------------------------------- /src/algebraic/types/Async/Apply.ts: -------------------------------------------------------------------------------- 1 | import type { Asyncλ } from './Async'; 2 | 3 | export { ap }; 4 | 5 | const ap = (p1: Asyncλ<(a: A) => B>) => (p2: Asyncλ): Asyncλ => 6 | () => Promise.all ([p1 (), p2 ()]).then (([f, r]) => f (r)); 7 | -------------------------------------------------------------------------------- /src/algebraic/types/Async/Async.ts: -------------------------------------------------------------------------------- 1 | export { Async$λ }; 2 | export type { Asyncλ }; 3 | 4 | const Async$λ = 'Async'; 5 | type Async$λ = typeof Async$λ; 6 | 7 | declare module '../../../hkt' { 8 | interface Type2Kind1 { 9 | readonly [Async$λ]: Asyncλ; 10 | } 11 | } 12 | 13 | /** 14 | * TODO: Add comment 15 | */ 16 | interface Asyncλ { 17 | (): Promise; 18 | } 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/algebraic/types/Async/Chain.ts: -------------------------------------------------------------------------------- 1 | import { Asyncλ } from './Async'; 2 | import { of } from './Applicative'; 3 | 4 | export { chain, chainU }; 5 | 6 | /** 7 | * TODO: Add comment 8 | * 9 | * chain :: (a -> b) -> Async a -> Async b 10 | */ 11 | const chain = (p1: (b: A) => Asyncλ) => 12 | (p2: Asyncλ): Asyncλ => 13 | 14 | chainU (p1, p2) 15 | 16 | 17 | /** 18 | * TODO: Add comment 19 | * 20 | * chain :: (a -> b) -> Async a -> Async b 21 | */ 22 | const chainU = (p1: (b: A) => Asyncλ, p2: Asyncλ): Asyncλ => 23 | 24 | () => p2 ().then (a => p1 (a) ()) -------------------------------------------------------------------------------- /src/algebraic/types/Async/Functions.ts: -------------------------------------------------------------------------------- 1 | import type { Asyncλ } from './Async'; 2 | import { pipe } from '@algebraic/common/pipe'; 3 | import { chain } from './Chain'; 4 | import { map } from './Functor'; 5 | import { bindTo as cBindTo } from '@algebraic/common/bindTo'; 6 | import { bindOf as cBindOf } from '@algebraic/common/bindOf'; 7 | 8 | export { bindTo, bindOf, chainFirst }; 9 | 10 | /** 11 | * TODO: Add comment 12 | */ 13 | const bindTo = ( 14 | p1: Exclude, 15 | p2: (a: Param) => Asyncλ 16 | ) => ( 17 | p3: Asyncλ 18 | ): Asyncλ< 19 | { 20 | [K in keyof Previous | Property]: K extends keyof Previous 21 | ? Previous[K] 22 | : A; 23 | } 24 | > => 25 | pipe ( 26 | p3, 27 | chain ((a) => 28 | pipe ( 29 | p2 (a), 30 | map ((b) => cBindTo (a, p1, b)) 31 | ) 32 | ) 33 | ); 34 | 35 | /** 36 | * TODO: Add comment 37 | */ 38 | const bindOf = (p1: Property) => ( 39 | p2: Asyncλ 40 | ): Asyncλ<{ [K in Property]: Value }> => 41 | pipe ( 42 | p2, 43 | map ((a) => cBindOf (p1, a)) 44 | ); 45 | 46 | /** 47 | * TODO: Add comment 48 | */ 49 | const chainFirst = (p1: (a: A) => Asyncλ) => (p2: Asyncλ) => 50 | pipe ( 51 | p2, 52 | chain ((b) => 53 | pipe ( 54 | p1 (b), 55 | map (() => b) 56 | ) 57 | ) 58 | ); 59 | -------------------------------------------------------------------------------- /src/algebraic/types/Async/Functor.ts: -------------------------------------------------------------------------------- 1 | import type { Asyncλ } from './Async'; 2 | import { of } from './Applicative'; 3 | 4 | export { map, mapU }; 5 | 6 | /** 7 | * TODO: Add comment 8 | * 9 | * map :: (a -> b) -> Async a -> Async b 10 | */ 11 | const map = (p1: (b: A) => B) => 12 | (p2: Asyncλ): Asyncλ => 13 | 14 | mapU (p1, p2) 15 | 16 | 17 | /** 18 | * TODO: Add comment 19 | * 20 | * map :: (a -> b) -> Async a -> Async b 21 | */ 22 | const mapU = (p1: (b: A) => B, p2: Asyncλ): Asyncλ => 23 | 24 | () => p2 ().then (p1); -------------------------------------------------------------------------------- /src/algebraic/types/Async/index.ts: -------------------------------------------------------------------------------- 1 | import type { ApplicativeOf1 } from '@algebraic/defs/Applicative'; 2 | import type { ApplyOf1 } from '@algebraic/defs/Apply'; 3 | import type { FunctorOf1 } from '@algebraic/defs/Functor'; 4 | import { of } from './Applicative'; 5 | import { ap } from './Apply'; 6 | import { map, mapU } from './Functor'; 7 | import { Async$λ } from './Async'; 8 | import { ChainOf1 } from '@algebraic/defs/Chain'; 9 | import { chain, chainU } from './Chain'; 10 | import { bindTo, bindOf, chainFirst } from './Functions'; 11 | 12 | type AsyncModule = ApplicativeOf1 & 13 | FunctorOf1 & 14 | ChainOf1 & 15 | ApplyOf1 & { 16 | λ: { 17 | bindTo: typeof bindTo; 18 | bindOf: typeof bindOf; 19 | chainFirst: typeof chainFirst; 20 | }; 21 | }; 22 | 23 | const AsyncModule: AsyncModule = { 24 | λ: { 25 | kind: Async$λ, 26 | ap, 27 | of, 28 | map, 29 | chainFirst, 30 | bindTo, 31 | bindOf, 32 | chain, 33 | }, 34 | λU: { 35 | kind: Async$λ, 36 | map: mapU, 37 | chain: chainU, 38 | }, 39 | }; 40 | 41 | export default AsyncModule; 42 | -------------------------------------------------------------------------------- /src/algebraic/types/AsyncEither/Applicative.ts: -------------------------------------------------------------------------------- 1 | import type { AsyncEitherλ } from './AsyncEither'; 2 | import Either from '@algebraic/types/Either'; 3 | import Async from '@algebraic/types/Async'; 4 | export { Right as of, Right, Left }; 5 | 6 | /** 7 | * TODO: Add comment 8 | */ 9 | const Right = (p1: B): AsyncEitherλ => 10 | Async.λ.of (Either.λ.of (p1)); 11 | 12 | /** 13 | * TODO: Add comment 14 | */ 15 | const Left = (p1: A): AsyncEitherλ => 16 | Async.λ.of (Either.λ.Left (p1)); 17 | -------------------------------------------------------------------------------- /src/algebraic/types/AsyncEither/Apply.ts: -------------------------------------------------------------------------------- 1 | import type { Eitherλ } from '@algebraic/types/Either/Either'; 2 | import type { AsyncEitherλ } from './AsyncEither'; 3 | import Either from '@algebraic/types/Either'; 4 | import Async from '@algebraic/types/Async'; 5 | 6 | export { ap }; 7 | 8 | const ap = (p1: AsyncEitherλ C>) => ( 9 | p2: AsyncEitherλ 10 | ): AsyncEitherλ => 11 | Async.λ.ap ( 12 | Async.λ.map ((h: Eitherλ C>) => (ga: Eitherλ) => 13 | Either.λ.ap (h) (ga) 14 | ) (p1) 15 | ) (p2); 16 | -------------------------------------------------------------------------------- /src/algebraic/types/AsyncEither/AsyncEither.ts: -------------------------------------------------------------------------------- 1 | import type { Eitherλ } from '@algebraic/types/Either/Either'; 2 | import type { Asyncλ } from '@algebraic/types/Async/Async'; 3 | 4 | export { AsyncEither$λ }; 5 | export type { AsyncEitherλ }; 6 | 7 | const AsyncEither$λ = 'AsyncEither'; 8 | type AsyncEither$λ = typeof AsyncEither$λ; 9 | 10 | declare module '../../../hkt' { 11 | interface Type2Kind2 { 12 | readonly [AsyncEither$λ]: AsyncEitherλ; 13 | } 14 | } 15 | 16 | type AsyncEitherλ = Asyncλ>; 17 | -------------------------------------------------------------------------------- /src/algebraic/types/AsyncEither/Chain.ts: -------------------------------------------------------------------------------- 1 | import type { AsyncEitherλ } from './AsyncEither'; 2 | import AsyncModule from '../Async'; 3 | import EitherModule from '../Either'; 4 | import pipe from 'ramda/src/pipe' 5 | import AsyncEitherModule from '.'; 6 | 7 | export { chain, chainU, chainStrict, chainStrictU }; 8 | 9 | /** 10 | * TODO: Add comment 11 | * 12 | * chainStrict :: (b -> c) -> AsyncEither b -> AsyncEither c 13 | */ 14 | const chainStrict = (p1: (b: B) => AsyncEitherλ) => 15 | (p2: AsyncEitherλ): AsyncEitherλ => 16 | 17 | chainStrictU (p1, p2) 18 | 19 | 20 | /** 21 | * TODO: Add comment 22 | * 23 | * chainStrict :: (b -> c) -> AsyncEither b -> AsyncEither c 24 | */ 25 | const chainStrictU = (p1: (b: B) => AsyncEitherλ, p2: AsyncEitherλ): AsyncEitherλ => 26 | pipe (() => p2, AsyncModule.λ.chain (EitherModule.λ.fold (AsyncEitherModule.λ.Left, p1))) () 27 | 28 | 29 | /** 30 | * TODO: Add comment 31 | */ 32 | const chain = (p1: (b: B) => AsyncEitherλ) => (p2: AsyncEitherλ): AsyncEitherλ => 33 | 34 | chainU (p1, p2) 35 | 36 | /** 37 | * TODO: Add comment 38 | */ 39 | const chainU = (p1: (b: B) => AsyncEitherλ, p2: AsyncEitherλ): AsyncEitherλ => 40 | 41 | AsyncModule.λU.chain (EitherModule.λ.fold > (AsyncEitherModule.λ.Left, p1), p2) -------------------------------------------------------------------------------- /src/algebraic/types/AsyncEither/Functions.ts: -------------------------------------------------------------------------------- 1 | import { AsyncEitherλ } from './AsyncEither'; 2 | import { isFailure } from '@algebraic/types/Result/Functions'; 3 | import AsyncEitherModule from '.'; 4 | import { Resultλ } from '@algebraic/types/Result/Result'; 5 | import { NonEmptyArrayλ } from '@algebraic/types/NonEmptyArray/NonEmptyArray'; 6 | import EitherModule from '../Either'; 7 | import { Asyncλ } from '../Async/Async'; 8 | import AsyncModule from '../Async'; 9 | import { pipe } from '@algebraic/common/pipe'; 10 | import { chain } from './Chain'; 11 | import { map, mapU } from './Functor'; 12 | import { bindTo as cBindTo } from '@algebraic/common/bindTo'; 13 | import { bindOf as cBindOf } from '@algebraic/common/bindOf'; 14 | import { Eitherλ } from '../Either/Either'; 15 | import { isLeft } from '../Either/Functions'; 16 | import { AsyncResultλ } from '../AsyncResult/AsyncResult'; 17 | 18 | export { 19 | fromResult, 20 | fromEither, 21 | fold, 22 | foldUnion, 23 | tryCatch, 24 | mapLeft, 25 | bindTo, 26 | bindToStrict, 27 | bindOf, 28 | chainFirst, 29 | chainFirstStrict, 30 | }; 31 | 32 | /** 33 | * TODO: Add comment 34 | * @param p1 35 | */ 36 | const fromResult = ( 37 | p1: Resultλ 38 | ): AsyncEitherλ, B> => 39 | isFailure (p1) 40 | ? AsyncEitherModule.λ.Left (p1.λ.value) 41 | : AsyncEitherModule.λ.Right (p1.λ.value); 42 | 43 | /** 44 | * TODO: Add comment 45 | * @param p1 46 | */ 47 | const fromEither = (p1: Eitherλ): AsyncEitherλ => 48 | isLeft (p1) 49 | ? AsyncEitherModule.λ.Left (p1.λ.value) 50 | : AsyncEitherModule.λ.Right (p1.λ.value); 51 | 52 | /** 53 | * TODO: Add comment 54 | * @param p1 55 | */ 56 | const fold = (onLeft: (a: A) => C, onRight: (b: B) => C) => ( 57 | p1: AsyncEitherλ 58 | ): Asyncλ => () => p1 ().then (EitherModule.λ.fold (onLeft, onRight)); 59 | 60 | /** 61 | * TODO: Add comment 62 | * @param p1 63 | */ 64 | const foldUnion = (p1: AsyncEitherλ): Asyncλ => () => 65 | p1 ().then (EitherModule.λ.foldUnion); 66 | 67 | /** 68 | * TODO: Add comment 69 | */ 70 | const tryCatch = ( 71 | p1: () => Promise, 72 | onRejected: (reason: unknown) => A 73 | ): AsyncEitherλ => () => 74 | p1 ().then (EitherModule.λ.Right, (reason) => 75 | EitherModule.λ.Left (onRejected (reason)) 76 | ); 77 | 78 | /** 79 | * TODO: Add comment 80 | */ 81 | const mapLeft = (p1: (a: A) => C) => ( 82 | p2: AsyncEitherλ 83 | ): AsyncEitherλ => AsyncModule.λU.map (EitherModule.λ.mapLeft (p1), p2); 84 | 85 | /** 86 | * TODO: Add comment 87 | */ 88 | const bindTo = ( 89 | p1: Exclude, 90 | p2: (a: Param) => AsyncEitherλ 91 | ) => ( 92 | p3: AsyncEitherλ 93 | ): AsyncEitherλ< 94 | A | C, 95 | { 96 | [K in keyof Previous | Property]: K extends keyof Previous 97 | ? Previous[K] 98 | : B; 99 | } 100 | > => 101 | pipe ( 102 | p3, 103 | chain ((a) => 104 | pipe ( 105 | p2 (a), 106 | map ((b) => cBindTo (a, p1, b)) 107 | ) 108 | ) 109 | ); 110 | 111 | /** 112 | * TODO: Add comment 113 | */ 114 | const bindToStrict = ( 115 | p1: Exclude, 116 | p2: (a: Param) => AsyncEitherλ 117 | ) => ( 118 | p3: AsyncEitherλ 119 | ): AsyncEitherλ< 120 | A, 121 | { 122 | [K in keyof Previous | Property]: K extends keyof Previous 123 | ? Previous[K] 124 | : B; 125 | } 126 | > => bindTo (p1, p2) (p3); 127 | 128 | /** 129 | * TODO: Add comment 130 | */ 131 | const bindOf = (p1: Property) => ( 132 | p2: AsyncEitherλ 133 | ): AsyncEitherλ => 134 | mapU ((a) => cBindOf (p1, a), p2); 135 | 136 | /** 137 | * TODO: Add comment 138 | */ 139 | const chainFirst = (p1: (b: B) => AsyncEitherλ) => ( 140 | p2: AsyncEitherλ 141 | ) => 142 | pipe ( 143 | p2, 144 | chain ((b) => 145 | pipe ( 146 | p1 (b), 147 | map (() => b) 148 | ) 149 | ) 150 | ); 151 | 152 | /** 153 | * TODO: Add comment 154 | */ 155 | const chainFirstStrict: ( 156 | p1: (b: B) => AsyncEitherλ 157 | ) => (p2: AsyncEitherλ) => AsyncEitherλ = chainFirst; 158 | 159 | /** 160 | * TODO: Add comment 161 | */ 162 | export const getOrElse = (onLeft: (a: A) => Asyncλ) => (p2: AsyncEitherλ): Asyncλ => 163 | pipe ( 164 | p2, 165 | AsyncModule.λ.chain ( 166 | EitherModule.λ.fold> (onLeft, AsyncModule.λ.of) 167 | ) 168 | ) 169 | 170 | /** 171 | * TODO: Add comment 172 | */ 173 | export const getOrElseStrict: (onLeft: (a: A) => Asyncλ) => (p2: AsyncEitherλ) => Asyncλ = getOrElse 174 | 175 | /** 176 | * TODO: Add comment 177 | */ 178 | export const orElse = (onLeft: (a: A) => AsyncEitherλ) => (p2: AsyncEitherλ): AsyncEitherλ => AsyncModule.λU.chain (EitherModule.λ.fold (onLeft, AsyncEitherModule.λ.Right), p2) 179 | -------------------------------------------------------------------------------- /src/algebraic/types/AsyncEither/Functor.ts: -------------------------------------------------------------------------------- 1 | import type { AsyncEitherλ } from './AsyncEither'; 2 | import Either from '@algebraic/types/Either'; 3 | import Async from '@algebraic/types/Async'; 4 | 5 | export { map, mapU }; 6 | 7 | /** 8 | * TODO: Add comment 9 | * 10 | * map :: (b -> c) -> AsyncEither b -> AsyncEither c 11 | */ 12 | const map = (p1: (b: B) => C) => ( 13 | p2: AsyncEitherλ 14 | ): AsyncEitherλ => mapU (p1, p2); 15 | 16 | /** 17 | * TODO: Add comment 18 | * 19 | * map :: (b -> c) -> AsyncEither b -> AsyncEither c 20 | */ 21 | const mapU = ( 22 | p1: (b: B) => C, 23 | p2: AsyncEitherλ 24 | ): AsyncEitherλ => Async.λU.map (Either.λ.map (p1), p2); 25 | -------------------------------------------------------------------------------- /src/algebraic/types/AsyncEither/index.ts: -------------------------------------------------------------------------------- 1 | import type { ApplicativeOf2 } from '@algebraic/defs/Applicative'; 2 | import type { ApplyOf2 } from '@algebraic/defs/Apply'; 3 | import type { FunctorOf2 } from '@algebraic/defs/Functor'; 4 | import { Left, of, Right } from './Applicative'; 5 | import { ap } from './Apply'; 6 | import { map, mapU } from './Functor'; 7 | import { chain, chainU, chainStrict } from './Chain'; 8 | import { AsyncEither$λ } from './AsyncEither'; 9 | import { 10 | fromResult, 11 | tryCatch, 12 | foldUnion, 13 | bindTo, 14 | bindToStrict, 15 | bindOf, 16 | fromEither, 17 | chainFirstStrict, 18 | chainFirst, 19 | getOrElse, 20 | getOrElseStrict, 21 | orElse 22 | } from './Functions'; 23 | import { fold } from './Functions'; 24 | import { ChainOf2 } from '@algebraic/defs/Chain'; 25 | import { mapLeft } from './Functions'; 26 | 27 | type AsyncEitherModule = { 28 | λ: { 29 | Left: typeof Left; 30 | Right: typeof Right; 31 | fromResult: typeof fromResult; 32 | fromEither: typeof fromEither; 33 | fold: typeof fold; 34 | foldUnion: typeof foldUnion; 35 | of: typeof of; 36 | tryCatch: typeof tryCatch; 37 | mapLeft: typeof mapLeft; 38 | chainStrict: typeof chainStrict; 39 | chain: typeof chain; 40 | chainFirst: typeof chainFirst; 41 | chainFirstStrict: typeof chainFirstStrict; 42 | bindTo: typeof bindTo; 43 | bindToStrict: typeof bindToStrict; 44 | bindOf: typeof bindOf; 45 | getOrElse: typeof getOrElse; 46 | getOrElseStrict: typeof getOrElseStrict; 47 | orElse: typeof orElse; 48 | }; 49 | } & ApplicativeOf2 & 50 | FunctorOf2 & 51 | ChainOf2 & 52 | ApplyOf2; 53 | 54 | const AsyncEitherModule: AsyncEitherModule = { 55 | λ: { 56 | kind: AsyncEither$λ, 57 | ap, 58 | of, 59 | map, 60 | Left, 61 | Right, 62 | fromResult, 63 | fromEither, 64 | fold, 65 | foldUnion, 66 | tryCatch, 67 | chain, 68 | chainFirst, 69 | chainFirstStrict, 70 | mapLeft, 71 | chainStrict, 72 | bindTo, 73 | bindToStrict, 74 | bindOf, 75 | getOrElse, 76 | getOrElseStrict, 77 | orElse 78 | }, 79 | λU: { 80 | kind: AsyncEither$λ, 81 | map: mapU, 82 | chain: chainU, 83 | }, 84 | }; 85 | 86 | export default AsyncEitherModule; 87 | -------------------------------------------------------------------------------- /src/algebraic/types/AsyncResult/Applicative.ts: -------------------------------------------------------------------------------- 1 | import type { AsyncResultλ } from './AsyncResult'; 2 | import Result from '@algebraic/types/Result'; 3 | import Async from '@algebraic/types/Async'; 4 | import { NonEmptyArrayλ } from '../NonEmptyArray/NonEmptyArray'; 5 | export { Success as of, Success, Failure }; 6 | 7 | /** 8 | * TODO: Add comment 9 | */ 10 | const Success = (p1: B): AsyncResultλ => 11 | Async.λ.of (Result.λ.of (p1)); 12 | 13 | /** 14 | * TODO: Add comment 15 | */ 16 | const Failure = ( 17 | p1: NonEmptyArrayλ 18 | ): AsyncResultλ => Async.λ.of (Result.λ.Failure (p1)); 19 | -------------------------------------------------------------------------------- /src/algebraic/types/AsyncResult/Apply.ts: -------------------------------------------------------------------------------- 1 | import type { Resultλ } from '@algebraic/types/Result/Result'; 2 | import type { AsyncResultλ } from './AsyncResult'; 3 | import Result from '@algebraic/types/Result'; 4 | import Async from '@algebraic/types/Async'; 5 | 6 | export { ap }; 7 | 8 | const ap = (p1: AsyncResultλ C>) => ( 9 | p2: AsyncResultλ 10 | ): AsyncResultλ => 11 | Async.λ.ap ( 12 | Async.λ.map ((h: Resultλ C>) => (ga: Resultλ) => 13 | Result.λ.ap (h) (ga) 14 | ) (p1) 15 | ) (p2); 16 | -------------------------------------------------------------------------------- /src/algebraic/types/AsyncResult/AsyncResult.ts: -------------------------------------------------------------------------------- 1 | import type { Resultλ } from '@algebraic/types/Result/Result'; 2 | import type { Asyncλ } from '@algebraic/types/Async/Async'; 3 | 4 | export { AsyncResult$λ }; 5 | export type { AsyncResultλ }; 6 | 7 | const AsyncResult$λ = 'AsyncResult'; 8 | type AsyncResult$λ = typeof AsyncResult$λ; 9 | 10 | declare module '../../../hkt' { 11 | interface Type2Kind2 { 12 | readonly [AsyncResult$λ]: AsyncResultλ; 13 | } 14 | } 15 | 16 | type AsyncResultλ = Asyncλ>; 17 | -------------------------------------------------------------------------------- /src/algebraic/types/AsyncResult/Chain.ts: -------------------------------------------------------------------------------- 1 | import type { AsyncResultλ } from './AsyncResult'; 2 | import AsyncModule from '../Async'; 3 | import ResultModule from '../Result'; 4 | import pipe from 'ramda/src/pipe'; 5 | import AsyncResultModule from '.'; 6 | 7 | export { chain, chainU, chainStrict, chainStrictU }; 8 | 9 | /** 10 | * TODO: Add comment 11 | * 12 | * chainStrict :: (b -> c) -> AsyncResult b -> AsyncResult c 13 | */ 14 | const chainStrict = (p1: (b: B) => AsyncResultλ) => ( 15 | p2: AsyncResultλ 16 | ): AsyncResultλ => chainStrictU (p1, p2); 17 | 18 | /** 19 | * TODO: Add comment 20 | * 21 | * chainStrict :: (b -> c) -> AsyncResult b -> AsyncResult c 22 | */ 23 | const chainStrictU = ( 24 | p1: (b: B) => AsyncResultλ, 25 | p2: AsyncResultλ 26 | ): AsyncResultλ => 27 | pipe ( 28 | () => p2, 29 | AsyncModule.λ.chain (ResultModule.λ.fold (AsyncResultModule.λ.Failure, p1)) 30 | ) (); 31 | 32 | /** 33 | * TODO: Add comment 34 | */ 35 | const chain = (p1: (b: B) => AsyncResultλ) => ( 36 | p2: AsyncResultλ 37 | ): AsyncResultλ => chainU (p1, p2); 38 | 39 | /** 40 | * TODO: Add comment 41 | */ 42 | const chainU = ( 43 | p1: (b: B) => AsyncResultλ, 44 | p2: AsyncResultλ 45 | ): AsyncResultλ => 46 | AsyncModule.λU.chain ( 47 | ResultModule.λ.fold, AsyncResultλ> ( 48 | AsyncResultModule.λ.Failure, 49 | p1 50 | ), 51 | p2 52 | ); 53 | -------------------------------------------------------------------------------- /src/algebraic/types/AsyncResult/Functions.ts: -------------------------------------------------------------------------------- 1 | import { AsyncResultλ } from './AsyncResult'; 2 | import { isFailure } from '@algebraic/types/Result/Functions'; 3 | import AsyncEitherModule from '.'; 4 | import { Resultλ } from '@algebraic/types/Result/Result'; 5 | import { NonEmptyArrayλ } from '@algebraic/types/NonEmptyArray/NonEmptyArray'; 6 | import Result from '../Result'; 7 | import { Asyncλ } from '../Async/Async'; 8 | import AsyncModule from '../Async'; 9 | import { pipe } from '@algebraic/common/pipe'; 10 | import { chain } from './Chain'; 11 | import { map, mapU } from './Functor'; 12 | import { bindTo as cBindTo } from '@algebraic/common/bindTo'; 13 | import { bindOf as cBindOf } from '@algebraic/common/bindOf'; 14 | import { Eitherλ } from '../Either/Either'; 15 | import { isLeft } from '../Either/Functions'; 16 | import ResultModule from '../Result'; 17 | 18 | export { 19 | fromResult, 20 | fromEither, 21 | fold, 22 | foldStrict, 23 | tryCatch, 24 | chainFirst, 25 | chainFirstStrict, 26 | mapFailure, 27 | bindTo, 28 | bindToStrict, 29 | bindOf, 30 | }; 31 | 32 | /** 33 | * TODO: Add comment 34 | * @param p1 35 | */ 36 | const fromResult = (p1: Resultλ): AsyncResultλ => 37 | isFailure (p1) 38 | ? AsyncEitherModule.λ.Failure (p1.λ.value) 39 | : AsyncEitherModule.λ.Success (p1.λ.value); 40 | 41 | /** 42 | * TODO: Add comment 43 | * @param p1 44 | */ 45 | const fromEither = (p1: Eitherλ): AsyncResultλ => 46 | isLeft (p1) 47 | ? AsyncEitherModule.λ.Failure ([p1.λ.value]) 48 | : AsyncEitherModule.λ.Success (p1.λ.value); 49 | 50 | /** 51 | * TODO: Add comment 52 | * @param p1 53 | */ 54 | const fold = ( 55 | onLeft: (a: NonEmptyArrayλ) => C, 56 | onRight: (b: B) => D 57 | ) => (p1: AsyncResultλ): Asyncλ => () => 58 | p1 ().then (Result.λ.fold (onLeft, onRight)); 59 | 60 | /** 61 | * TODO: Add comment 62 | * @param p1 63 | */ 64 | const foldStrict = ( 65 | onLeft: (a: NonEmptyArrayλ) => C, 66 | onRight: (b: B) => C 67 | ) => (p1: AsyncResultλ): Asyncλ => () => 68 | p1 ().then (Result.λ.fold (onLeft, onRight)); 69 | 70 | /** 71 | * TODO: Add comment 72 | */ 73 | const tryCatch = ( 74 | p1: () => Promise, 75 | onRejected: (reason: unknown) => A 76 | ): AsyncResultλ => () => 77 | p1 ().then (Result.λ.Success, (reason) => 78 | Result.λ.Failure ([onRejected (reason)]) 79 | ); 80 | 81 | /** 82 | * TODO: Add comment 83 | */ 84 | const mapFailure = ( 85 | p1: (a: NonEmptyArrayλ) => NonEmptyArrayλ 86 | ) => (p2: AsyncResultλ): AsyncResultλ => 87 | AsyncModule.λU.map (Result.λ.mapFailure (p1), p2); 88 | 89 | /** 90 | * TODO: Add comment 91 | */ 92 | const bindTo = ( 93 | p1: Exclude, 94 | p2: (a: Param) => AsyncResultλ 95 | ) => ( 96 | p3: AsyncResultλ 97 | ): AsyncResultλ< 98 | A | C, 99 | { 100 | [K in keyof Previous | Property]: K extends keyof Previous 101 | ? Previous[K] 102 | : B; 103 | } 104 | > => 105 | pipe ( 106 | p3, 107 | chain ((a) => 108 | pipe ( 109 | p2 (a), 110 | map ((b) => cBindTo (a, p1, b)) 111 | ) 112 | ) 113 | ); 114 | 115 | /** 116 | * TODO: Add comment 117 | */ 118 | const bindToStrict = ( 119 | p1: Exclude, 120 | p2: (a: Param) => AsyncResultλ 121 | ) => ( 122 | p3: AsyncResultλ 123 | ): AsyncResultλ< 124 | A, 125 | { 126 | [K in keyof Previous | Property]: K extends keyof Previous 127 | ? Previous[K] 128 | : B; 129 | } 130 | > => bindTo (p1, p2) (p3); 131 | 132 | /** 133 | * TODO: Add comment 134 | */ 135 | const bindOf = (p1: Property) => ( 136 | p2: AsyncResultλ 137 | ): AsyncResultλ => 138 | mapU ((a) => cBindOf (p1, a), p2); 139 | 140 | /** 141 | * TODO: Add comment 142 | */ 143 | const chainFirst = (p1: (b: B) => AsyncResultλ) => ( 144 | p2: AsyncResultλ 145 | ) => 146 | pipe ( 147 | p2, 148 | chain ((b) => 149 | pipe ( 150 | p1 (b), 151 | map (() => b) 152 | ) 153 | ) 154 | ); 155 | 156 | /** 157 | * TODO: Add comment 158 | */ 159 | const chainFirstStrict: ( 160 | p1: (b: B) => AsyncResultλ 161 | ) => (p2: AsyncResultλ) => AsyncResultλ = chainFirst; 162 | 163 | /** 164 | * TODO: Add comment 165 | */ 166 | export const getOrElse = (onFailure: (a: NonEmptyArrayλ) => Asyncλ) => (p2: AsyncResultλ): Asyncλ => 167 | pipe ( 168 | p2, 169 | AsyncModule.λ.chain ( 170 | ResultModule.λ.fold, Asyncλ> (onFailure, AsyncModule.λ.of) 171 | ) 172 | ) 173 | 174 | /** 175 | * TODO: Add comment 176 | */ 177 | export const getOrElseStrict: (onFailure: (a: NonEmptyArrayλ) => Asyncλ) => (p2: AsyncResultλ) => Asyncλ = getOrElse 178 | 179 | /** 180 | * TODO: Add comment 181 | */ 182 | export const orElse = (onFailure: (a: NonEmptyArrayλ) => AsyncResultλ) => (p2: AsyncResultλ): AsyncResultλ => AsyncModule.λU.chain (ResultModule.λ.fold (onFailure, AsyncEitherModule.λ.Success), p2) 183 | -------------------------------------------------------------------------------- /src/algebraic/types/AsyncResult/Functor.ts: -------------------------------------------------------------------------------- 1 | import type { AsyncResultλ } from './AsyncResult'; 2 | import Result from '@algebraic/types/Result'; 3 | import Async from '@algebraic/types/Async'; 4 | 5 | export { map, mapU }; 6 | 7 | /** 8 | * TODO: Add comment 9 | * 10 | * map :: (b -> c) -> AsyncResult b -> AsyncResult c 11 | */ 12 | const map = (p1: (b: B) => C) => ( 13 | p2: AsyncResultλ 14 | ): AsyncResultλ => mapU (p1, p2); 15 | 16 | /** 17 | * TODO: Add comment 18 | * 19 | * map :: (b -> c) -> AsyncResult b -> AsyncResult c 20 | */ 21 | const mapU = ( 22 | p1: (b: B) => C, 23 | p2: AsyncResultλ 24 | ): AsyncResultλ => Async.λU.map (Result.λ.map (p1), p2); 25 | -------------------------------------------------------------------------------- /src/algebraic/types/AsyncResult/index.ts: -------------------------------------------------------------------------------- 1 | import type { ApplicativeOf2 } from '@algebraic/defs/Applicative'; 2 | import type { ApplyOf2 } from '@algebraic/defs/Apply'; 3 | import type { FunctorOf2 } from '@algebraic/defs/Functor'; 4 | import { Failure, of, Success } from './Applicative'; 5 | import { ap } from './Apply'; 6 | import { map, mapU } from './Functor'; 7 | import { chain, chainU, chainStrict } from './Chain'; 8 | import { AsyncResult$λ } from './AsyncResult'; 9 | import { 10 | fromResult, 11 | tryCatch, 12 | bindTo, 13 | bindToStrict, 14 | bindOf, 15 | fromEither, 16 | foldStrict, 17 | chainFirst, 18 | chainFirstStrict, 19 | getOrElse, 20 | getOrElseStrict, 21 | mapFailure, 22 | orElse 23 | } from './Functions'; 24 | import { fold } from './Functions'; 25 | import { ChainOf2 } from '@algebraic/defs/Chain'; 26 | 27 | type AsyncResultModule = { 28 | λ: { 29 | Failure: typeof Failure; 30 | Success: typeof Success; 31 | fromEither: typeof fromEither; 32 | fromResult: typeof fromResult; 33 | foldStrict: typeof foldStrict; 34 | fold: typeof fold; 35 | of: typeof of; 36 | tryCatch: typeof tryCatch; 37 | mapFailure: typeof mapFailure; 38 | chainStrict: typeof chainStrict; 39 | chain: typeof chain; 40 | chainFirst: typeof chainFirst; 41 | chainFirstStrict: typeof chainFirstStrict; 42 | bindTo: typeof bindTo; 43 | bindToStrict: typeof bindToStrict; 44 | bindOf: typeof bindOf; 45 | getOrElse: typeof getOrElse; 46 | getOrElseStrict: typeof getOrElseStrict; 47 | orElse: typeof orElse; 48 | 49 | }; 50 | } & ApplicativeOf2 & 51 | FunctorOf2 & 52 | ChainOf2 & 53 | ApplyOf2; 54 | 55 | const AsyncResultModule: AsyncResultModule = { 56 | λ: { 57 | kind: AsyncResult$λ, 58 | ap, 59 | of, 60 | map, 61 | Failure, 62 | Success, 63 | fromResult, 64 | fromEither, 65 | fold, 66 | foldStrict, 67 | tryCatch, 68 | chain, 69 | chainFirst, 70 | chainFirstStrict, 71 | mapFailure, 72 | chainStrict, 73 | bindTo, 74 | bindToStrict, 75 | bindOf, 76 | getOrElse, 77 | getOrElseStrict, 78 | orElse 79 | }, 80 | λU: { 81 | kind: AsyncResult$λ, 82 | map: mapU, 83 | chain: chainU, 84 | }, 85 | }; 86 | 87 | export default AsyncResultModule; 88 | -------------------------------------------------------------------------------- /src/algebraic/types/Either/Applicative.ts: -------------------------------------------------------------------------------- 1 | import type { Eitherλ } from './Either'; 2 | import { Either$λ } from './Either'; 3 | 4 | export { Right as of, Right, Left }; 5 | 6 | /** 7 | * TODO: Add comment 8 | */ 9 | const Right = (p1: B): Eitherλ => ({ 10 | λ: { 11 | id: 'Right', 12 | kind: Either$λ, 13 | typeB: undefined as any, 14 | value: p1, 15 | }, 16 | }); 17 | 18 | /** 19 | * TODO: Add comment 20 | */ 21 | const Left = (p1: A): Eitherλ => ({ 22 | λ: { 23 | id: 'Left', 24 | kind: Either$λ, 25 | typeA: undefined as any, 26 | value: p1, 27 | }, 28 | }); 29 | 30 | -------------------------------------------------------------------------------- /src/algebraic/types/Either/Apply.ts: -------------------------------------------------------------------------------- 1 | import { Left, Right } from './Applicative'; 2 | import type { Eitherλ } from './Either'; 3 | import { isLeft } from './Functions'; 4 | 5 | export { ap }; 6 | 7 | /** 8 | * TODO: Add comment 9 | * @param p1 10 | */ 11 | const ap = (p1: Eitherλ C>) => ( 12 | p2: Eitherλ 13 | ): Eitherλ => 14 | isLeft (p1) 15 | ? Left (p1.λ.value) 16 | : isLeft (p2) 17 | ? Left (p2.λ.value) 18 | : Right (p1.λ.value (p2.λ.value)); 19 | 20 | -------------------------------------------------------------------------------- /src/algebraic/types/Either/Chain.ts: -------------------------------------------------------------------------------- 1 | import { isLeft } from './Functions'; 2 | import type { Eitherλ } from './Either'; 3 | 4 | export { chainStrict, chainStrictU, chain, chainU }; 5 | 6 | /** 7 | * TODO: Add comment 8 | * 9 | * chainStrict :: (b -> c) -> Either b -> Either c 10 | */ 11 | const chainStrict = (p1: (b: B) => Eitherλ) => 12 | (p2: Eitherλ): Eitherλ => 13 | 14 | chainStrictU (p1, p2) 15 | 16 | /** 17 | * TODO: Add comment 18 | * 19 | * chainStrictU :: (b -> c) -> Either b -> Either c 20 | */ 21 | const chainStrictU = (p1: (b: B) => Eitherλ, p2: Eitherλ): Eitherλ => 22 | 23 | chainU (p1, p2) 24 | 25 | /** 26 | * TODO: Add comment 27 | */ 28 | const chain = (p1: (b: B) => Eitherλ) => (p2: Eitherλ): Eitherλ => 29 | 30 | chainU (p1, p2) 31 | 32 | /** 33 | * TODO: Add comment 34 | */ 35 | const chainU = (p1: (b: B) => Eitherλ, p2: Eitherλ): Eitherλ => 36 | 37 | isLeft (p2) ? p2 : p1 (p2.λ.value) -------------------------------------------------------------------------------- /src/algebraic/types/Either/Either.ts: -------------------------------------------------------------------------------- 1 | export { Either$λ }; 2 | export type { Eitherλ, Rightλ, Leftλ }; 3 | 4 | const Either$λ = 'Either'; 5 | type Either$λ = typeof Either$λ; 6 | type Eitherλ = Leftλ | Rightλ; 7 | 8 | declare module '../../../hkt' { 9 | interface Type2Kind2 { 10 | readonly [Either$λ]: Eitherλ; 11 | } 12 | } 13 | 14 | /** 15 | * TODO: Add comment 16 | */ 17 | interface Leftλ { 18 | λ: { 19 | id: 'Left'; 20 | kind: Either$λ; 21 | typeA: A; 22 | value: A; 23 | }; 24 | } 25 | 26 | /** 27 | * TODO: Add comment 28 | */ 29 | interface Rightλ { 30 | λ: { 31 | id: 'Right'; 32 | kind: Either$λ; 33 | typeB: B; 34 | value: B; 35 | }; 36 | } 37 | 38 | 39 | -------------------------------------------------------------------------------- /src/algebraic/types/Either/Functions.ts: -------------------------------------------------------------------------------- 1 | import type { Eitherλ, Rightλ, Leftλ } from './Either'; 2 | import EitherModule from '.'; 3 | import { Resultλ } from '../Result/Result'; 4 | import { NonEmptyArrayλ } from '@algebraic/types/NonEmptyArray/NonEmptyArray'; 5 | import ResultModule from '../Result'; 6 | import { pipe } from '@algebraic/common/pipe'; 7 | import { chain } from './Chain'; 8 | import { map } from './Functor'; 9 | import { bindTo as cBindTo } from '@algebraic/common/bindTo'; 10 | import { bindOf as cBindOf } from '@algebraic/common/bindOf'; 11 | 12 | export { 13 | isLeft, 14 | isRight, 15 | fold, 16 | foldUnion, 17 | mapLeft, 18 | mapLeftU, 19 | fromResult, 20 | bindTo, 21 | bindToStrict, 22 | bindOf, 23 | chainFirst, 24 | chainFirstStrict, 25 | }; 26 | 27 | /** 28 | * TODO: Add comment 29 | * @param p1 30 | */ 31 | const isLeft = (p1: Eitherλ): p1 is Leftλ => p1.λ.id === 'Left'; 32 | 33 | /** 34 | * TODO: Add comment 35 | * @param p1 36 | */ 37 | const isRight = (p1: Eitherλ): p1 is Rightλ => 38 | p1.λ.id === 'Right'; 39 | 40 | /** 41 | * TODO: Add comment 42 | * @param p1 43 | */ 44 | const fold = (onLeft: (a: A) => C, onRight: (b: B) => C) => ( 45 | p1: Eitherλ 46 | ) => (isLeft (p1) ? onLeft (p1.λ.value) : onRight (p1.λ.value)); 47 | 48 | /** 49 | * TODO: Add comment 50 | * @param p1 51 | */ 52 | const foldUnion = (p1: Eitherλ): A | B => p1.λ.value; 53 | 54 | /** 55 | * TODO: Add comment 56 | * @param p1 57 | */ 58 | const mapLeft = (p1: (a: A) => C) => ( 59 | p2: Eitherλ 60 | ): Eitherλ => mapLeftU (p1, p2); 61 | 62 | /** 63 | * TODO: Add comment 64 | * @param p1 65 | */ 66 | const mapLeftU = (p1: (a: A) => C, p2: Eitherλ): Eitherλ => 67 | isLeft (p2) ? EitherModule.λ.Left (p1 (p2.λ.value)) : p2; 68 | 69 | /** 70 | * TODO: Add comment 71 | * @param p1 72 | */ 73 | const fromResult = (p1: Resultλ): Eitherλ, B> => 74 | ResultModule.λ.isFailure (p1) 75 | ? EitherModule.λ.Left (p1.λ.value) 76 | : EitherModule.λ.Right (p1.λ.value); 77 | 78 | /** 79 | * TODO: Add comment 80 | */ 81 | const bindTo = ( 82 | p1: Exclude, 83 | p2: (a: Param) => Eitherλ 84 | ) => ( 85 | p3: Eitherλ 86 | ): Eitherλ< 87 | A | C, 88 | { 89 | [K in keyof Previous | Property]: K extends keyof Previous 90 | ? Previous[K] 91 | : B; 92 | } 93 | > => 94 | pipe ( 95 | p3, 96 | chain ((a) => 97 | pipe ( 98 | p2 (a), 99 | map ((b) => cBindTo (a, p1, b)) 100 | ) 101 | ) 102 | ); 103 | 104 | /** 105 | * TODO: Add comment 106 | */ 107 | const bindToStrict = ( 108 | p1: Exclude, 109 | p2: (a: Param) => Eitherλ 110 | ) => ( 111 | p3: Eitherλ 112 | ): Eitherλ< 113 | A, 114 | { 115 | [K in keyof Previous | Property]: K extends keyof Previous 116 | ? Previous[K] 117 | : B; 118 | } 119 | > => bindTo (p1, p2) (p3); 120 | 121 | /** 122 | * TODO: Add comment 123 | */ 124 | const bindOf = (p1: Property) => ( 125 | p2: Eitherλ 126 | ): Eitherλ => 127 | pipe ( 128 | p2, 129 | map ((a) => cBindOf (p1, a)) 130 | ); 131 | 132 | /** 133 | * TODO: Add comment 134 | */ 135 | const chainFirst = (p1: (b: B) => Eitherλ) => ( 136 | p2: Eitherλ 137 | ) => 138 | pipe ( 139 | p2, 140 | chain ((b) => 141 | pipe ( 142 | p1 (b), 143 | map (() => b) 144 | ) 145 | ) 146 | ); 147 | 148 | /** 149 | * TODO: Add comment 150 | */ 151 | const chainFirstStrict: ( 152 | p1: (b: B) => Eitherλ 153 | ) => (p2: Eitherλ) => Eitherλ = chainFirst; 154 | 155 | /** 156 | * TODO: Add comment 157 | */ 158 | export const getOrElse = (onLeft: (a: A) => B) => ( 159 | p2: Eitherλ 160 | ): C | B => (isLeft (p2) ? onLeft (p2.λ.value) : p2.λ.value); 161 | 162 | /** 163 | * TODO: Add comment 164 | */ 165 | export const getOrElseStrict: ( 166 | onLeft: (a: A) => B 167 | ) => (p2: Eitherλ) => B = getOrElse; 168 | 169 | /** 170 | * TODO: Add comment 171 | */ 172 | export const orElse = (onLeft: (a: A) => Eitherλ) => (p2: Eitherλ): Eitherλ => (isLeft (p2) ? onLeft (p2.λ.value) : p2) 173 | 174 | 175 | /** 176 | * TODO: Add comment 177 | */ 178 | export const orElseStrict: (onLeft: (a: A) => Eitherλ) => (p2: Eitherλ) => Eitherλ = orElse -------------------------------------------------------------------------------- /src/algebraic/types/Either/Functor.ts: -------------------------------------------------------------------------------- 1 | import type { Eitherλ } from './Either'; 2 | import { Left, Right } from './Applicative'; 3 | import { isLeft } from './Functions'; 4 | 5 | export { map, mapU }; 6 | 7 | /** 8 | * TODO: Add comment 9 | * 10 | * map :: (b -> c) -> Either b -> Either c 11 | */ 12 | const map = (p1: (b: B) => C) => 13 | (p2: Eitherλ): Eitherλ => 14 | 15 | mapU (p1, p2) 16 | 17 | /** 18 | * TODO: Add comment 19 | * 20 | * map :: (b -> c) -> Either b -> Either c 21 | */ 22 | const mapU = (p1: (b: B) => C, p2: Eitherλ): Eitherλ => 23 | 24 | isLeft (p2) ? Left (p2.λ.value) : Right (p1 (p2.λ.value)); 25 | 26 | -------------------------------------------------------------------------------- /src/algebraic/types/Either/index.ts: -------------------------------------------------------------------------------- 1 | import type { ApplicativeOf2 } from '@algebraic/defs/Applicative'; 2 | import type { ApplyOf2 } from '@algebraic/defs/Apply'; 3 | import type { FunctorOf2 } from '@algebraic/defs/Functor'; 4 | import { of, Right, Left } from './Applicative'; 5 | import { ap } from './Apply'; 6 | import { Either$λ } from './Either'; 7 | import { map, mapU } from './Functor'; 8 | import { chain, chainU, chainStrict, chainStrictU } from './Chain'; 9 | import { 10 | fold, 11 | foldUnion, 12 | mapLeft, 13 | fromResult, 14 | bindTo, 15 | bindToStrict, 16 | bindOf, 17 | chainFirst, 18 | chainFirstStrict, 19 | getOrElse, 20 | getOrElseStrict, 21 | orElse, 22 | orElseStrict, 23 | } from './Functions'; 24 | import { ChainOf2 } from '@algebraic/defs/Chain'; 25 | 26 | type EitherModule = ApplicativeOf2 & 27 | FunctorOf2 & 28 | ChainOf2 & 29 | ApplyOf2 & { 30 | λ: { 31 | Left: typeof Left; 32 | Right: typeof Right; 33 | fold: typeof fold; 34 | foldUnion: typeof foldUnion; 35 | mapLeft: typeof mapLeft; 36 | chainStrict: typeof chainStrict; 37 | fromResult: typeof fromResult; 38 | bindTo: typeof bindTo; 39 | bindToStrict: typeof bindToStrict; 40 | bindOf: typeof bindOf; 41 | chainFirst: typeof chainFirst; 42 | chainFirstStrict: typeof chainFirstStrict; 43 | getOrElse: typeof getOrElse; 44 | getOrElseStrict: typeof getOrElseStrict; 45 | orElse: typeof orElse; 46 | orElseStrict: typeof orElseStrict; 47 | }; 48 | λU: { 49 | chainStrict: typeof chainStrictU; 50 | }; 51 | }; 52 | 53 | const EitherModule: EitherModule = { 54 | λ: { 55 | kind: Either$λ, 56 | ap, 57 | of, 58 | map, 59 | Left, 60 | Right, 61 | fold, 62 | foldUnion, 63 | chain, 64 | bindTo, 65 | bindToStrict, 66 | bindOf, 67 | mapLeft, 68 | chainStrict, 69 | fromResult, 70 | chainFirst, 71 | chainFirstStrict, 72 | getOrElse, 73 | getOrElseStrict, 74 | orElse, 75 | orElseStrict 76 | }, 77 | λU: { 78 | kind: Either$λ, 79 | map: mapU, 80 | chain: chainU, 81 | chainStrict: chainStrictU, 82 | }, 83 | }; 84 | 85 | export default EitherModule; 86 | -------------------------------------------------------------------------------- /src/algebraic/types/Maybe/Applicative.ts: -------------------------------------------------------------------------------- 1 | 2 | import { Maybe$λ } from './Maybe'; 3 | import type { Maybeλ } from './Maybe'; 4 | 5 | export { Just as of, Just, Nothing }; 6 | 7 | /** 8 | * TODO: Add comment 9 | */ 10 | const Just = (p1: A): Maybeλ => ({ 11 | λ: { 12 | id: 'Just', 13 | kind: Maybe$λ, 14 | typeA: undefined as any, 15 | value: p1, 16 | }, 17 | }); 18 | 19 | /** 20 | * TODO: Add comment 21 | */ 22 | const Nothing: Maybeλ = { 23 | λ: { 24 | id: 'Nothing', 25 | kind: Maybe$λ, 26 | typeA: undefined as never, 27 | } 28 | }; 29 | 30 | -------------------------------------------------------------------------------- /src/algebraic/types/Maybe/Apply.ts: -------------------------------------------------------------------------------- 1 | import type { Maybeλ } from './Maybe'; 2 | import { isNothing } from './Functions'; 3 | import { Nothing, Just } from './Applicative'; 4 | 5 | export { ap }; 6 | 7 | const ap = (p1: Maybeλ<(a: A) => B>) => (p2: Maybeλ): Maybeλ => 8 | isNothing (p1) 9 | ? Nothing 10 | : isNothing (p2) 11 | ? Nothing 12 | : Just (p1.λ.value (p2.λ.value)); 13 | -------------------------------------------------------------------------------- /src/algebraic/types/Maybe/Chain.ts: -------------------------------------------------------------------------------- 1 | import { Nothing } from './Applicative'; 2 | import { isNothing } from './Functions'; 3 | import { Maybeλ } from './Maybe'; 4 | 5 | export { chain, chainU }; 6 | 7 | /** 8 | * TODO: Add comment 9 | * 10 | * chain :: (a -> b) -> Maybe a -> Maybe b 11 | */ 12 | const chain = (p1: (b: A) => Maybeλ) => 13 | (p2: Maybeλ): Maybeλ => 14 | 15 | chainU (p1, p2) 16 | 17 | 18 | /** 19 | * TODO: Add comment 20 | * 21 | * chain :: (a -> b) -> Maybe a -> Maybe b 22 | */ 23 | const chainU = (p1: (b: A) => Maybeλ, p2: Maybeλ): Maybeλ => 24 | 25 | isNothing (p2) ? Nothing : p1 (p2.λ.value) -------------------------------------------------------------------------------- /src/algebraic/types/Maybe/Functions.ts: -------------------------------------------------------------------------------- 1 | import type { Justλ, Maybeλ, Nothingλ } from './Maybe'; 2 | import { Nothing, Just } from './Applicative'; 3 | import { pipe } from '@algebraic/common/pipe'; 4 | import { chain } from './Chain'; 5 | import { map } from './Functor'; 6 | import { bindTo as cBindTo } from '@algebraic/common/bindTo'; 7 | import { bindOf as cBindOf } from '@algebraic/common/bindOf'; 8 | 9 | export { 10 | isNothing, 11 | isJust, 12 | fromMaybe, 13 | fromNullable, 14 | bindTo, 15 | bindOf, 16 | chainFirst, 17 | }; 18 | 19 | /** 20 | * TODO: Add comment 21 | * @param p1 22 | */ 23 | const isNothing = (p1: Maybeλ): p1 is Nothingλ => p1.λ.id === 'Nothing'; 24 | 25 | /** 26 | * TODO: Add comment 27 | * @param p1 28 | */ 29 | const isJust = (p1: Maybeλ): p1 is Justλ => p1.λ.id === 'Just'; 30 | 31 | /** 32 | * TODO: Add Comment 33 | * @param p1 34 | */ 35 | const fromNullable = (a: A): Maybeλ> => 36 | a == null ? Nothing : Just (a as NonNullable); 37 | 38 | const fromMaybe = (p1: A) => (p2: Maybeλ): A => 39 | isNothing (p2) ? p1 : p2.λ.value; 40 | 41 | /** 42 | * TODO: Add comment 43 | */ 44 | const bindTo = ( 45 | p1: Exclude, 46 | p2: (a: Param) => Maybeλ 47 | ) => ( 48 | p3: Maybeλ 49 | ): Maybeλ< 50 | { 51 | [K in keyof Previous | Property]: K extends keyof Previous 52 | ? Previous[K] 53 | : A; 54 | } 55 | > => 56 | pipe ( 57 | p3, 58 | chain ((a) => 59 | pipe ( 60 | p2 (a), 61 | map ((b) => cBindTo (a, p1, b)) 62 | ) 63 | ) 64 | ); 65 | 66 | /** 67 | * TODO: Add comment 68 | */ 69 | const bindOf = (p1: Property) => ( 70 | p2: Maybeλ 71 | ): Maybeλ<{ [K in Property]: Value }> => 72 | pipe ( 73 | p2, 74 | map ((a) => cBindOf (p1, a)) 75 | ); 76 | 77 | /** 78 | * TODO: Add comment 79 | */ 80 | const chainFirst = (p1: (a: A) => Maybeλ) => (p2: Maybeλ) => 81 | pipe ( 82 | p2, 83 | chain ((b) => 84 | pipe ( 85 | p1 (b), 86 | map (() => b) 87 | ) 88 | ) 89 | ); 90 | -------------------------------------------------------------------------------- /src/algebraic/types/Maybe/Functor.ts: -------------------------------------------------------------------------------- 1 | import type { Maybeλ } from './Maybe'; 2 | import { Just, Nothing } from './Applicative'; 3 | import { isNothing } from './Functions'; 4 | 5 | export { map, mapU }; 6 | 7 | /** 8 | * TODO: Add comment 9 | * 10 | * map :: (a -> b) -> Maybe a -> Maybe b 11 | */ 12 | const map = (p1: (a: A) => B) => 13 | (p2: Maybeλ): Maybeλ => 14 | 15 | mapU (p1, p2) 16 | 17 | /** 18 | * TODO: Add comment 19 | * 20 | * map :: (a -> b) -> Maybe a -> Maybe b 21 | */ 22 | const mapU = (p1: (a: A) => B, p2: Maybeλ): Maybeλ => 23 | 24 | isNothing (p2) ? Nothing : Just (p1 (p2.λ.value)); 25 | -------------------------------------------------------------------------------- /src/algebraic/types/Maybe/Maybe.ts: -------------------------------------------------------------------------------- 1 | export { Maybe$λ }; 2 | export type { Maybeλ, Justλ, Nothingλ }; 3 | 4 | const Maybe$λ = 'Maybe'; 5 | type Maybe$λ = typeof Maybe$λ; 6 | type Maybeλ = Nothingλ | Justλ; 7 | 8 | declare module '../../../hkt' { 9 | interface Type2Kind1 { 10 | readonly [Maybe$λ]: Maybeλ; 11 | } 12 | } 13 | 14 | /** 15 | * TODO: Add comment 16 | */ 17 | interface Nothingλ { 18 | λ: { 19 | id: 'Nothing'; 20 | kind: Maybe$λ; 21 | typeA: never; 22 | }; 23 | } 24 | /** 25 | * TODO: Add comment 26 | */ 27 | interface Justλ { 28 | λ: { 29 | id: 'Just'; 30 | kind: Maybe$λ; 31 | typeA: A; 32 | value: A; 33 | }; 34 | } 35 | 36 | 37 | -------------------------------------------------------------------------------- /src/algebraic/types/Maybe/index.ts: -------------------------------------------------------------------------------- 1 | import type { ApplicativeOf1 } from '@algebraic/defs/Applicative'; 2 | import { ApplyOf1 } from '@algebraic/defs/Apply'; 3 | import { FunctorOf1 } from '@algebraic/defs/Functor'; 4 | import { Just, Nothing, of } from './Applicative'; 5 | import { ap } from './Apply'; 6 | import { map, mapU } from './Functor'; 7 | import { Maybe$λ } from './Maybe'; 8 | import { fromNullable, bindTo, bindOf, chainFirst } from './Functions'; 9 | import { ChainOf1 } from '@algebraic/defs/Chain'; 10 | import { chain, chainU } from './Chain'; 11 | 12 | type MaybeModule = ApplicativeOf1 & 13 | ApplyOf1 & 14 | ChainOf1 & 15 | FunctorOf1 & { 16 | λ: { 17 | Nothing: typeof Nothing; 18 | Just: typeof Just; 19 | fromNullable: typeof fromNullable; 20 | bindTo: typeof bindTo; 21 | bindOf: typeof bindOf; 22 | chainFirst: typeof chainFirst; 23 | }; 24 | }; 25 | 26 | const MaybeModule: MaybeModule = { 27 | λ: { 28 | kind: Maybe$λ, 29 | of, 30 | map, 31 | ap, 32 | chain, 33 | bindTo, 34 | bindOf, 35 | Just, 36 | Nothing, 37 | fromNullable, 38 | chainFirst, 39 | }, 40 | λU: { 41 | kind: Maybe$λ, 42 | map: mapU, 43 | chain: chainU, 44 | }, 45 | }; 46 | 47 | export default MaybeModule; 48 | -------------------------------------------------------------------------------- /src/algebraic/types/NonEmptyArray/Functor.ts: -------------------------------------------------------------------------------- 1 | import { NonEmptyArrayλ } from './NonEmptyArray'; 2 | 3 | export { map, mapU }; 4 | 5 | /** 6 | * TODO: Add comment 7 | * 8 | * map :: (a -> b) -> NonEmptyArray a -> NonEmptyArray b 9 | */ 10 | const map = (p1: (a: A) => B) => 11 | (p2: NonEmptyArrayλ): NonEmptyArrayλ => 12 | 13 | mapU (p1, p2) 14 | 15 | 16 | /** 17 | * TODO: Add comment 18 | * 19 | * map :: (a -> b) -> NonEmptyArray a -> NonEmptyArray b 20 | */ 21 | const mapU = (p1: (a: A) => B, p2: NonEmptyArrayλ): NonEmptyArrayλ => 22 | 23 | p2.map (p1) as NonEmptyArrayλ; 24 | -------------------------------------------------------------------------------- /src/algebraic/types/NonEmptyArray/NonEmptyArray.ts: -------------------------------------------------------------------------------- 1 | export { NonEmptyArray$λ }; 2 | export type { NonEmptyArrayλ }; 3 | 4 | const NonEmptyArray$λ = 'NonEmptyArray'; 5 | type NonEmptyArray$λ = typeof NonEmptyArray$λ; 6 | 7 | declare module '../../../hkt' { 8 | interface Type2Kind1 { 9 | readonly [NonEmptyArray$λ]: NonEmptyArrayλ; 10 | } 11 | } 12 | 13 | /** 14 | * TODO: Add comment 15 | */ 16 | type NonEmptyArrayλ = [A, ...A[]]; 17 | -------------------------------------------------------------------------------- /src/algebraic/types/NonEmptyArray/index.ts: -------------------------------------------------------------------------------- 1 | import { FunctorOf1 } from "@algebraic/defs/Functor"; 2 | import { map, mapU } from "./Functor"; 3 | import { NonEmptyArray$λ } from "./NonEmptyArray"; 4 | 5 | type NonEmptyArrayModule = FunctorOf1; 6 | 7 | const NonEmptyArrayModule: NonEmptyArrayModule = { 8 | λ: { 9 | kind: NonEmptyArray$λ, 10 | map, 11 | }, 12 | λU: { 13 | kind: NonEmptyArray$λ, 14 | map: mapU, 15 | }, 16 | }; 17 | 18 | export default NonEmptyArrayModule; 19 | -------------------------------------------------------------------------------- /src/algebraic/types/Result/Applicative.ts: -------------------------------------------------------------------------------- 1 | import type { NonEmptyArrayλ } from '../NonEmptyArray/NonEmptyArray'; 2 | import type { Resultλ } from './Result'; 3 | import { Result$λ } from './Result'; 4 | 5 | export { Success as of, Success, Failure }; 6 | 7 | /** 8 | * TODO: Add comment 9 | */ 10 | const Success = (p1: B): Resultλ => ({ 11 | λ: { 12 | id: 'Success', 13 | kind: Result$λ, 14 | type: undefined as never, 15 | value: p1, 16 | }, 17 | }); 18 | 19 | /** 20 | * TODO: Add comment 21 | */ 22 | const Failure = ( 23 | p1: NonEmptyArrayλ 24 | ): Resultλ => ({ 25 | λ: { 26 | id: 'Failure', 27 | kind: Result$λ, 28 | value: p1, 29 | type: undefined as never, 30 | }, 31 | }); 32 | -------------------------------------------------------------------------------- /src/algebraic/types/Result/Apply.ts: -------------------------------------------------------------------------------- 1 | import { Failure, Success } from './Applicative'; 2 | import { isFailure } from './Functions'; 3 | import type { Resultλ } from './Result'; 4 | 5 | export { ap }; 6 | 7 | const ap = (p1: Resultλ C>) => ( 8 | p2: Resultλ 9 | ): Resultλ => 10 | isFailure (p1) 11 | ? isFailure (p2) 12 | ? Failure (p1.λ.value.concat (p2.λ.value) as any) 13 | : p1 14 | : isFailure (p2) 15 | ? p2 16 | : Success (p1.λ.value (p2.λ.value)); 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/algebraic/types/Result/Chain.ts: -------------------------------------------------------------------------------- 1 | import { isFailure } from './Functions'; 2 | import type { Resultλ } from './Result'; 3 | 4 | export { chainStrict, chainStrictU, chain, chainU }; 5 | 6 | /** 7 | * TODO: Add comment 8 | * 9 | * chainStrict :: (b -> c) -> Result b -> Result c 10 | */ 11 | const chainStrict = (p1: (b: B) => Resultλ) => 12 | (p2: Resultλ): Resultλ => 13 | 14 | chainStrictU (p1, p2) 15 | 16 | /** 17 | * TODO: Add comment 18 | * 19 | * chainStrictU :: (b -> c) -> Result b -> Result c 20 | */ 21 | const chainStrictU = (p1: (b: B) => Resultλ, p2: Resultλ): Resultλ => 22 | 23 | chainU (p1, p2) 24 | 25 | /** 26 | * TODO: Add comment 27 | */ 28 | const chain = (p1: (b: B) => Resultλ) => (p2: Resultλ): Resultλ => 29 | 30 | chainU (p1, p2) 31 | 32 | /** 33 | * TODO: Add comment 34 | */ 35 | const chainU = (p1: (b: B) => Resultλ, p2: Resultλ): Resultλ => 36 | 37 | isFailure (p2) ? p2 : p1 (p2.λ.value) -------------------------------------------------------------------------------- /src/algebraic/types/Result/Functions.ts: -------------------------------------------------------------------------------- 1 | import type { Failureλ, Successλ, Resultλ } from './Result'; 2 | import { NonEmptyArrayλ } from '@algebraic/types/NonEmptyArray/NonEmptyArray'; 3 | import { pipe } from '@algebraic/common/pipe'; 4 | import { chain } from './Chain'; 5 | import { map } from './Functor'; 6 | import { bindTo as cBindTo } from '@algebraic/common/bindTo'; 7 | import { bindOf as cBindOf } from '@algebraic/common/bindOf'; 8 | 9 | export { 10 | isFailure, 11 | isSuccess, 12 | isSuccessOf, 13 | fold, 14 | bindTo, 15 | bindToStrict, 16 | bindOf, 17 | chainFirst, 18 | chainFirstStrict, 19 | }; 20 | 21 | /** 22 | * TODO: Add comment 23 | * @param p1 24 | */ 25 | const isFailure = (p1: Resultλ): p1 is Failureλ => 26 | p1.λ.id === 'Failure'; 27 | 28 | /** 29 | * TODO: Add comment 30 | * @param p1 31 | */ 32 | const isSuccess = (p1: Resultλ): p1 is Successλ => 33 | p1.λ.id === 'Success'; 34 | 35 | /** 36 | * TODO: Add comment 37 | * @param p1 38 | */ 39 | const isSuccessOf = (p1: Resultλ, p2: any): p1 is Successλ => 40 | isSuccess (p1) && (p1 as any).λ.value.toString () === p2.toString (); 41 | 42 | /** 43 | * TODO: Add comment 44 | * @param p1 45 | */ 46 | const fold = ( 47 | onFailure: (a: NonEmptyArrayλ) => C, 48 | onSucess: (b: B) => D 49 | ) => (p1: Resultλ) => 50 | isFailure (p1) ? onFailure (p1.λ.value) : onSucess (p1.λ.value); 51 | 52 | /** 53 | * TODO: Add comment 54 | * @param p1 55 | */ 56 | const foldStrict = ( 57 | onFailure: (a: NonEmptyArrayλ) => C, 58 | onSucess: (b: B) => C 59 | ) => (p1: Resultλ) => 60 | isFailure (p1) ? onFailure (p1.λ.value) : onSucess (p1.λ.value); 61 | 62 | /** 63 | * TODO: Add comment 64 | */ 65 | const bindTo = ( 66 | p1: Exclude, 67 | p2: (a: Param) => Resultλ 68 | ) => ( 69 | p3: Resultλ 70 | ): Resultλ< 71 | A | C, 72 | { 73 | [K in keyof Previous | Property]: K extends keyof Previous 74 | ? Previous[K] 75 | : B; 76 | } 77 | > => 78 | pipe ( 79 | p3, 80 | chain ((a) => 81 | pipe ( 82 | p2 (a), 83 | map ((b) => cBindTo (a, p1, b)) 84 | ) 85 | ) 86 | ); 87 | 88 | /** 89 | * TODO: Add comment 90 | */ 91 | const bindToStrict = ( 92 | p1: Exclude, 93 | p2: (a: Param) => Resultλ 94 | ) => ( 95 | p3: Resultλ 96 | ): Resultλ< 97 | A, 98 | { 99 | [K in keyof Previous | Property]: K extends keyof Previous 100 | ? Previous[K] 101 | : B; 102 | } 103 | > => bindTo (p1, p2) (p3); 104 | 105 | /** 106 | * TODO: Add comment 107 | */ 108 | const bindOf = (p1: Property) => ( 109 | p2: Resultλ 110 | ): Resultλ => 111 | pipe ( 112 | p2, 113 | map ((a) => cBindOf (p1, a)) 114 | ); 115 | 116 | /** 117 | * TODO: Add comment 118 | */ 119 | const chainFirst = (p1: (b: B) => Resultλ) => ( 120 | p2: Resultλ 121 | ) => 122 | pipe ( 123 | p2, 124 | chain ((b) => 125 | pipe ( 126 | p1 (b), 127 | map (() => b) 128 | ) 129 | ) 130 | ); 131 | 132 | /** 133 | * TODO: Add comment 134 | */ 135 | const chainFirstStrict: ( 136 | p1: (b: B) => Resultλ 137 | ) => (p2: Resultλ) => Resultλ = chainFirst; 138 | 139 | /** 140 | * TODO: Add comment 141 | */ 142 | export const getOrElse = (onFailure: (a: NonEmptyArrayλ) => B) => ( 143 | p2: Resultλ 144 | ): C | B => (isFailure (p2) ? onFailure (p2.λ.value) : p2.λ.value); 145 | 146 | /** 147 | * TODO: Add comment 148 | */ 149 | export const getOrElseStrict: ( 150 | onFailure: (a: NonEmptyArrayλ) => B 151 | ) => (p2: Resultλ) => B = getOrElse; 152 | 153 | /** 154 | * TODO: Add comment 155 | */ 156 | export const orElse = (onFailure: (a: NonEmptyArrayλ) => Resultλ) => (p2: Resultλ): Resultλ => (isFailure (p2) ? onFailure (p2.λ.value) : p2) 157 | -------------------------------------------------------------------------------- /src/algebraic/types/Result/Functor.ts: -------------------------------------------------------------------------------- 1 | import type { NonEmptyArrayλ } from '../NonEmptyArray/NonEmptyArray'; 2 | import { Failure, Success } from './Applicative'; 3 | import { isFailure } from './Functions'; 4 | import type { Resultλ } from './Result'; 5 | 6 | export { map, mapU, mapFailure }; 7 | 8 | /** 9 | * TODO: Add comment 10 | * 11 | * map :: (b -> c) -> Result b -> Result c 12 | */ 13 | const map = (p1: (b: B) => C) => ( 14 | p2: Resultλ 15 | ): Resultλ => mapU (p1, p2); 16 | 17 | /** 18 | * TODO: Add comment 19 | * 20 | * map :: (b -> c) -> Result b -> Result c 21 | */ 22 | const mapU = ( 23 | p1: (b: B) => C, 24 | p2: Resultλ 25 | ): Resultλ => 26 | isFailure (p2) ? Failure (p2.λ.value) : Success (p1 (p2.λ.value)); 27 | 28 | /** 29 | * TODO: Add comment 30 | */ 31 | const mapFailure = ( 32 | p1: (b: NonEmptyArrayλ) => NonEmptyArrayλ 33 | ) => (p2: Resultλ): Resultλ => 34 | isFailure (p2) ? Failure (p1 (p2.λ.value)) : Success (p2.λ.value); 35 | -------------------------------------------------------------------------------- /src/algebraic/types/Result/Result.ts: -------------------------------------------------------------------------------- 1 | import type { NonEmptyArrayλ } from '../NonEmptyArray/NonEmptyArray'; 2 | 3 | export { Result$λ }; 4 | export type { Resultλ, Successλ, Failureλ }; 5 | 6 | const Result$λ = 'Result'; 7 | type Result$λ = typeof Result$λ; 8 | type Resultλ = Failureλ | Successλ; 9 | 10 | declare module '../../../hkt' { 11 | interface Type2Kind2 { 12 | readonly [Result$λ]: Resultλ; 13 | } 14 | } 15 | 16 | /** 17 | * TODO: Add comment 18 | */ 19 | 20 | interface Failureλ { 21 | λ: { 22 | id: 'Failure'; 23 | kind: Result$λ; 24 | type: A; 25 | value: NonEmptyArrayλ; 26 | }; 27 | } 28 | 29 | /** 30 | * TODO: Add comment 31 | */ 32 | 33 | interface Successλ { 34 | λ: { 35 | id: 'Success'; 36 | kind: Result$λ; 37 | type: B; 38 | value: B; 39 | }; 40 | } 41 | -------------------------------------------------------------------------------- /src/algebraic/types/Result/index.ts: -------------------------------------------------------------------------------- 1 | import type { ApplicativeOf2 } from '@algebraic/defs/Applicative'; 2 | import type { ApplyOf2 } from '@algebraic/defs/Apply'; 3 | import type { FunctorOf2 } from '@algebraic/defs/Functor'; 4 | import { Failure, of, Success } from './Applicative'; 5 | import { ap } from './Apply'; 6 | import { map, mapU, mapFailure } from './Functor'; 7 | import { Result$λ } from './Result'; 8 | import { ChainOf2 } from '@algebraic/defs/Chain'; 9 | import { chainU, chain, chainStrict, chainStrictU } from './Chain'; 10 | import { 11 | fold, 12 | isFailure, 13 | isSuccess, 14 | bindTo, 15 | bindToStrict, 16 | bindOf, 17 | chainFirst, 18 | chainFirstStrict, 19 | getOrElse, 20 | getOrElseStrict, 21 | orElse, 22 | } from './Functions'; 23 | 24 | type ResultModule = ApplicativeOf2 & 25 | FunctorOf2 & 26 | ApplyOf2 & 27 | ChainOf2 & { 28 | λ: { 29 | mapFailure: typeof mapFailure; 30 | Failure: typeof Failure; 31 | Success: typeof Success; 32 | fold: typeof fold; 33 | chainStrict: typeof chainStrict; 34 | bindTo: typeof bindTo; 35 | bindToStrict: typeof bindToStrict; 36 | bindOf: typeof bindOf; 37 | isFailure: typeof isFailure; 38 | isSuccess: typeof isSuccess; 39 | chainFirst: typeof chainFirst; 40 | chainFirstStrict: typeof chainFirstStrict; 41 | getOrElse: typeof getOrElse; 42 | getOrElseStrict: typeof getOrElseStrict; 43 | orElse: typeof orElse; 44 | }; 45 | λU: { 46 | chainStrict: typeof chainStrictU; 47 | }; 48 | }; 49 | 50 | const ResultModule: ResultModule = { 51 | λ: { 52 | kind: Result$λ, 53 | ap, 54 | bindOf, 55 | bindTo, 56 | bindToStrict, 57 | chain, 58 | chainFirst, 59 | chainFirstStrict, 60 | chainStrict, 61 | Failure, 62 | fold, 63 | isFailure, 64 | isSuccess, 65 | map, 66 | mapFailure, 67 | of, 68 | Success, 69 | getOrElse, 70 | getOrElseStrict, 71 | orElse 72 | }, 73 | λU: { 74 | kind: Result$λ, 75 | map: mapU, 76 | chain: chainU, 77 | chainStrict: chainStrictU, 78 | }, 79 | }; 80 | 81 | export default ResultModule; 82 | -------------------------------------------------------------------------------- /src/common/identity.ts: -------------------------------------------------------------------------------- 1 | export { identity }; 2 | 3 | /** 4 | * TODO: Add Comment 5 | * 6 | * identity :: a -> a 7 | */ 8 | const identity = (p1: A): A => p1 -------------------------------------------------------------------------------- /src/common/index.ts: -------------------------------------------------------------------------------- 1 | export { identity } from './identity' -------------------------------------------------------------------------------- /src/hkt/index.ts: -------------------------------------------------------------------------------- 1 | type HKT1 = { 2 | λ: { 3 | kind: ID; 4 | typeA: TypeA; 5 | }; 6 | }; 7 | 8 | type HKT2 = HKT1< 9 | ID, 10 | TypeA 11 | > & { 12 | λ: { 13 | typeB: TypeB; 14 | }; 15 | }; 16 | 17 | interface Type2Kind1 {} 18 | interface Type2Kind2 {} 19 | 20 | type Types1 = keyof Type2Kind1; 21 | type Types2 = keyof Type2Kind2; 22 | type Types = Types1 | Types2; 23 | 24 | type Kind1 = Type extends Types1 25 | ? Type2Kind1[Type] 26 | : any; 27 | type Kind2 = Type extends Types2 28 | ? Type2Kind2[Type] 29 | : any; 30 | 31 | export { 32 | Types, 33 | Types1, 34 | Types2, 35 | Type2Kind1, 36 | Type2Kind2, 37 | HKT1, 38 | HKT2, 39 | Kind1, 40 | Kind2, 41 | }; 42 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export * as Algebraic from '@algebraic/index' 2 | export * as Runtime from '@runtime/index' -------------------------------------------------------------------------------- /src/runtime/defs/index.ts: -------------------------------------------------------------------------------- 1 | import { Resultλ } from '@algebraic/types/Result/Result'; 2 | export { 3 | Schema, 4 | TypeOf, 5 | Check, 6 | InvalidCheck, 7 | Childable, 8 | Checkable, 9 | CheckableWith, 10 | }; 11 | 12 | interface Schema { 13 | _: { 14 | type: Type; 15 | primitive: Primitive; 16 | }; 17 | } 18 | 19 | interface Childable { 20 | _: { 21 | child: Child; 22 | }; 23 | } 24 | 25 | type TypeOf = A['_']['primitive']; 26 | 27 | interface Checkable { 28 | _: { 29 | checkInt: Check; 30 | }; 31 | Δ: { 32 | check: (a: unknown) => Resultλ>; 33 | }; 34 | } 35 | 36 | interface CheckableWith { 37 | _: { 38 | checkInt: Check; 39 | }; 40 | Δ: { 41 | check: (a: unknown) => Resultλ>; 42 | checkWith: (a: Check[]) => A; 43 | }; 44 | } 45 | 46 | interface Check { 47 | (a: unknown, path: string, child?: any): Resultλ>; 48 | } 49 | 50 | interface InvalidCheck { 51 | message: string; 52 | path: string; 53 | code: string; 54 | } 55 | -------------------------------------------------------------------------------- /src/runtime/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Array } from '@runtime/types/Array/Array'; 2 | export { default as Boolean } from '@runtime/types/Boolean/Boolean'; 3 | export { default as Literal } from '@runtime/types/Literal/Literal'; 4 | export { default as Number } from '@runtime/types/Number/Number'; 5 | export { default as Partial } from '@runtime/types/Partial/Partial'; 6 | export { default as Record } from '@runtime/types/Record/Record'; 7 | export { default as String } from '@runtime/types/String/String'; 8 | export { default as Tuple } from '@runtime/types/Tuple/Tuple'; 9 | export { default as Union } from '@runtime/types/Union/Union'; 10 | export { default as Intersect } from '@runtime/types/Intersect/Intersect'; 11 | -------------------------------------------------------------------------------- /src/runtime/introspection.ts: -------------------------------------------------------------------------------- 1 | import { ArrayΔ$ } from '@runtime/types/Array/Array'; 2 | import { LiteralΔ$ } from '@runtime/types/Literal/Literal'; 3 | import { UnionΔ$, UnionΔ } from '@runtime/types/Union/Union'; 4 | import { IntersectΔ$, IntersectΔ } from '@runtime/types/Intersect/Intersect'; 5 | import { Schema, Checkable } from '@runtime/defs'; 6 | import { RecordΔ, RecordΔ$ } from '@runtime/types/Record/Record'; 7 | import { TupleΔ$, TupleΔ } from '@runtime/types/Tuple/Tuple'; 8 | import { PartialΔ$, PartialΔ } from '@runtime/types/Partial/Partial'; 9 | 10 | export { introspect }; 11 | 12 | const introspect = (a: any): string => { 13 | if (a?._.type === ArrayΔ$) return introspectArray (a); 14 | if (a?._.type === LiteralΔ$) return introspectLiteral (a); 15 | if (a?._.type === UnionΔ$) return introspectUnion (a); 16 | if (a?._.type === IntersectΔ$) return introspectIntersect (a); 17 | if (a?._.type === RecordΔ$) return introspectRecord (a); 18 | if (a?._.type === TupleΔ$) return introspectTuple (a); 19 | if (a?._.type === PartialΔ$) return introspectPartial (a); 20 | return (a?._.type && a._.type.toString ().toLowerCase ().slice (7, -1)) || ``; 21 | }; 22 | 23 | const introspectArray = (a: any) => 24 | `${a.isReadOnly ? `readonly` : ``} ${introspect (a._.child)}[]`; 25 | 26 | const introspectLiteral = (a: any) => `${a._.child}`; 27 | 28 | const introspectUnion = )[]>( 29 | a: UnionΔ 30 | ) => `(${a._.child.map (introspect).join (' | ')})`; 31 | 32 | const introspectIntersect = )[]>( 33 | a: UnionΔ 34 | ) => `(${a._.child.map (introspect).join (' & ')})`; 35 | 36 | const introspectRecord = (a: RecordΔ<{ [key: string]: Schema }>) => 37 | `{ ${Object.keys (a._.child) 38 | .map ((k) => `${k}: ${introspect (a._.child[k])};`) 39 | .join (' ')} }`; 40 | 41 | const introspectPartial = (a: PartialΔ<{ [key: string]: Schema }>) => 42 | `{ ${Object.keys (a._.child) 43 | .map ((k) => `${k}?: ${introspect (a._.child[k])};`) 44 | .join (' ')} }`; 45 | 46 | const introspectTuple = (a: TupleΔ<(Schema & Checkable)[]>) => 47 | `[${a._.child.map (introspect).join (', ')}]`; 48 | -------------------------------------------------------------------------------- /src/runtime/types/Array/Array.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Schema, 3 | TypeOf, 4 | Childable, 5 | Checkable, 6 | Check, 7 | CheckableWith, 8 | } from '@runtime/defs'; 9 | import { checkInt } from './Checkable'; 10 | import { String } from '@runtime/types/String'; 11 | 12 | export { ArrayΔ, ArrayΔ$ }; 13 | const ArrayΔ$ = Symbol ('Array'); 14 | type ArrayΔ$ = typeof ArrayΔ$; 15 | 16 | /** 17 | * TODO: Add comment 18 | */ 19 | type ArrayΔ = Schema< 20 | ArrayΔ$, 21 | IsReadOnly extends true ? readonly TypeOf[] : TypeOf[] 22 | > & 23 | CheckableWith> & 24 | Childable & { 25 | _: { 26 | isReadOnly?: IsReadOnly; 27 | }; 28 | Δ: { 29 | asReadOnly: () => ArrayΔ; 30 | }; 31 | }; 32 | 33 | const Array = < 34 | A extends Schema & Checkable, 35 | IsReadOnly extends boolean = false 36 | >( 37 | child: A, 38 | isReadOnly = false as IsReadOnly, 39 | withChecks?: Check>[] 40 | ): ArrayΔ => ({ 41 | _: { 42 | type: ArrayΔ$, 43 | primitive: undefined as any, 44 | child, 45 | isReadOnly, 46 | checkInt: checkInt (child, isReadOnly, withChecks), 47 | }, 48 | Δ: { 49 | check: (a) => checkInt (child, isReadOnly, withChecks) (a, ''), 50 | checkWith: (p1) => Array (child, isReadOnly, p1), 51 | asReadOnly: () => 52 | Array (child, true, withChecks as Check>[] | undefined), 53 | }, 54 | }); 55 | 56 | export default Array; 57 | -------------------------------------------------------------------------------- /src/runtime/types/Array/Checkable.ts: -------------------------------------------------------------------------------- 1 | import ResultModule from '@algebraic/types/Result'; 2 | import { sequence } from '@algebraic/common/sequence'; 3 | import { Check, Checkable, Schema, InvalidCheck } from '@runtime/defs'; 4 | import { introspect } from '@runtime/introspection'; 5 | import rPipe from 'ramda/src/pipe'; 6 | import Array, { ArrayΔ } from './Array'; 7 | import { Resultλ } from '@algebraic/types/Result/Result'; 8 | 9 | export { checkInt }; 10 | 11 | const buildPath = (indice: number, parentPath?: string) => 12 | parentPath ? `${parentPath}[${indice}]` : `[${indice}]`; 13 | 14 | const isArray = (): Check< 15 | ArrayΔ 16 | > => (a, path, child) => 17 | globalThis.Array.isArray (a) && a.length > 0 18 | ? ResultModule.λ.Success (a as ArrayΔ['_']['primitive']) 19 | : ResultModule.λ.Failure ([ 20 | { 21 | code: 'IS_ARRAY', 22 | message: `Expected ${introspect ( 23 | child 24 | )} but found (${a} :: ${typeof a})`, 25 | path, 26 | }, 27 | ]); 28 | 29 | const doWithChecks = ( 30 | path: string, 31 | withChecks?: Check>[] 32 | ) => (payload: ArrayΔ['_']['primitive']) => 33 | withChecks 34 | ? withChecks.map ((check) => check (payload, path)) 35 | : [ 36 | ResultModule.λ.Success< 37 | InvalidCheck, 38 | ArrayΔ['_']['primitive'] 39 | > (payload), 40 | ]; 41 | 42 | const doChildChecks = < 43 | A extends Schema & Checkable, 44 | IsReadOnly extends boolean 45 | >( 46 | payload: ArrayΔ['_']['primitive'], 47 | path: string, 48 | child: ArrayΔ['_']['child'] 49 | ) => ( 50 | withChecks: Resultλ['_']['primitive']>[] 51 | ) => 52 | sequence (ResultModule) ([ 53 | ...withChecks, 54 | ...doChildChecksCondition (withChecks, payload, path, child), 55 | ]); 56 | 57 | const doChildChecksCondition = < 58 | A extends Schema & Checkable, 59 | IsReadOnly extends boolean 60 | >( 61 | withChecks: Resultλ['_']['primitive']>[], 62 | payload: ArrayΔ['_']['primitive'], 63 | path: string, 64 | child: ArrayΔ['_']['child'] 65 | ) => 66 | withChecks.some ((c) => c.λ.id === 'Success') 67 | ? (payload as any[]).map ((v, i) => 68 | child._.checkInt (v, buildPath (i, path), (child as any)?._?.child) 69 | ) 70 | : []; 71 | 72 | const checkInt = , IsReadOnly extends boolean>( 73 | child: ArrayΔ['_']['child'], 74 | isReadOnly: IsReadOnly, 75 | withChecks?: Check>[] 76 | ): Check> => (a: unknown, path: string) => 77 | rPipe ( 78 | () => isArray () (a, path, Array (child, isReadOnly)), 79 | ResultModule.λ.map ((res) => doWithChecks (path, withChecks) (res)), 80 | ResultModule.λ.chain ((res) => 81 | doChildChecks (a as any[], path, child) (res) 82 | ), 83 | ResultModule.λ.map ((res) => res[0]) 84 | ) (); 85 | -------------------------------------------------------------------------------- /src/runtime/types/Array/checks/isGreaterThan.ts: -------------------------------------------------------------------------------- 1 | import Result from '@algebraic/types/Result'; 2 | import { Check, Schema } from '@runtime/defs'; 3 | import { ArrayΔ } from '../Array'; 4 | 5 | export { isGreaterThan }; 6 | 7 | const isGreaterThan = (p1: number): Check> => ( 8 | a, 9 | path 10 | ) => 11 | globalThis.Array.isArray (a) && a.length > p1 12 | ? Result.λ.Success ([a]) 13 | : Result.λ.Failure ([ 14 | { 15 | code: 'IS_ARRAY_GREATER_THAN', 16 | message: `Expected array to be greater than ${p1}.`, 17 | path, 18 | }, 19 | ]); 20 | -------------------------------------------------------------------------------- /src/runtime/types/Boolean/Boolean.ts: -------------------------------------------------------------------------------- 1 | import { Schema, Checkable } from '@runtime/defs'; 2 | import { checkInt } from './Checkable'; 3 | 4 | export { BooleanΔ, BooleanΔ$ }; 5 | const BooleanΔ$ = Symbol ('Boolean'); 6 | type BooleanΔ$ = typeof BooleanΔ$; 7 | 8 | /** 9 | * TODO: Add comment 10 | */ 11 | type BooleanΔ = Schema & Checkable; 12 | 13 | const Boolean: BooleanΔ = { 14 | _: { 15 | type: BooleanΔ$, 16 | primitive: undefined as any, 17 | checkInt 18 | }, 19 | Δ: { 20 | check: (a) => checkInt (a, ''), 21 | } 22 | } 23 | 24 | export default Boolean; 25 | -------------------------------------------------------------------------------- /src/runtime/types/Boolean/Checkable.ts: -------------------------------------------------------------------------------- 1 | import ResultModule from '@algebraic/types/Result'; 2 | import { Check } from '@runtime/defs'; 3 | import { BooleanΔ } from './Boolean'; 4 | export { checkInt }; 5 | 6 | const isBoolean: Check = (a, path) => 7 | typeof a === 'boolean' 8 | ? ResultModule.λ.Success (a) 9 | : ResultModule.λ.Failure ([ 10 | { 11 | code: 'IS_BOOLEAN', 12 | message: `Expected boolean but found (${a} :: ${typeof a})`, 13 | path, 14 | }, 15 | ]); 16 | 17 | const checkInt = isBoolean; 18 | -------------------------------------------------------------------------------- /src/runtime/types/Intersect/Checkable.ts: -------------------------------------------------------------------------------- 1 | import ResultModule from '@algebraic/types/Result'; 2 | import { Resultλ } from '@algebraic/types/Result/Result'; 3 | import { introspect } from 'src/runtime/introspection'; 4 | import { Checkable, InvalidCheck, Schema } from '@runtime/defs'; 5 | import rPipe from 'ramda/src/pipe'; 6 | import Intersect, { IntersectΔ } from './Intersect'; 7 | import { pipe } from '@algebraic/common/pipe'; 8 | import { sequence } from '@algebraic/common/sequence'; 9 | export { checkInt }; 10 | 11 | const doChildChecks = )[]>( 12 | a: unknown, 13 | path: string, 14 | child: IntersectΔ['_']['child'] 15 | ) => child.map ((c) => c._.checkInt (a, path, child)); 16 | 17 | const suceedOrFail = )[]>( 18 | a: IntersectΔ['_']['primitive'], 19 | path: string, 20 | child: IntersectΔ['_']['child'] 21 | ) => ( 22 | childResults: Resultλ[] 23 | ): Resultλ['_']['primitive']> => { 24 | const failedChilds = childResults.filter ((i) => i.λ.id === 'Failure') 25 | return failedChilds.length >= 1 26 | ? ResultModule.λ.Failure ([ 27 | { 28 | code: 'IS_INTERSECT', 29 | message: `Expected ${introspect ( 30 | Intersect (...child) 31 | )} but found (${typeof a === 'object' ? JSON.stringify (a) : a} :: ${typeof a})`, 32 | path, 33 | }, 34 | ...failedChilds.map (i => i.λ.value) 35 | ]) 36 | : ResultModule.λ.Success (a) 37 | } 38 | ; 39 | 40 | const checkInt = )[]>( 41 | child: IntersectΔ['_']['child'] 42 | ) => (a: unknown, path: string) => 43 | rPipe ( 44 | (a: unknown, path: string) => doChildChecks (a, path, child), 45 | suceedOrFail (a as any, path, child) 46 | ) (a, path); 47 | -------------------------------------------------------------------------------- /src/runtime/types/Intersect/Intersect.ts: -------------------------------------------------------------------------------- 1 | import { Checkable, Childable, Schema, TypeOf } from '@runtime/defs'; 2 | import { checkInt } from './Checkable'; 3 | 4 | export { IntersectΔ, IntersectΔ$, IntersectPrimitiveΔ$ }; 5 | const IntersectΔ$ = Symbol ('Intersect'); 6 | type IntersectΔ$ = typeof IntersectΔ$; 7 | 8 | /** 9 | * TODO: Add comment 10 | */ 11 | type IntersectΔ)[]> = Schema< 12 | IntersectΔ$, 13 | IntersectPrimitiveΔ$ 14 | > & 15 | Checkable> & 16 | Childable; 17 | 18 | const Intersect = )[]>( 19 | ...child: A 20 | ): IntersectΔ => ({ 21 | _: { 22 | type: IntersectΔ$, 23 | primitive: undefined as any, 24 | child, 25 | checkInt: checkInt (child), 26 | }, 27 | Δ: { 28 | check: (a) => checkInt (child) (a, ''), 29 | }, 30 | }); 31 | 32 | type S = Schema; 33 | type IntersectPrimitiveΔ$ = A extends [ 34 | infer U1, 35 | infer U2, 36 | infer U3, 37 | infer U4, 38 | infer U5, 39 | infer U6, 40 | infer U7, 41 | infer U8, 42 | infer U9, 43 | infer U10 44 | ] 45 | ? U1 extends S 46 | ? U2 extends S 47 | ? U3 extends S 48 | ? U4 extends S 49 | ? U5 extends S 50 | ? U6 extends S 51 | ? U7 extends S 52 | ? U8 extends S 53 | ? U9 extends S 54 | ? U10 extends S 55 | ? 56 | & TypeOf 57 | & TypeOf 58 | & TypeOf 59 | & TypeOf 60 | & TypeOf 61 | & TypeOf 62 | & TypeOf 63 | & TypeOf 64 | & TypeOf 65 | & TypeOf 66 | : unknown 67 | : unknown 68 | : unknown 69 | : unknown 70 | : unknown 71 | : unknown 72 | : unknown 73 | : unknown 74 | : unknown 75 | : unknown 76 | : A extends [ 77 | infer U1, 78 | infer U2, 79 | infer U3, 80 | infer U4, 81 | infer U5, 82 | infer U6, 83 | infer U7, 84 | infer U8, 85 | infer U9 86 | ] 87 | ? U1 extends S 88 | ? U2 extends S 89 | ? U3 extends S 90 | ? U4 extends S 91 | ? U5 extends S 92 | ? U6 extends S 93 | ? U7 extends S 94 | ? U8 extends S 95 | ? U9 extends S 96 | ? 97 | & TypeOf 98 | & TypeOf 99 | & TypeOf 100 | & TypeOf 101 | & TypeOf 102 | & TypeOf 103 | & TypeOf 104 | & TypeOf 105 | & TypeOf 106 | : unknown 107 | : unknown 108 | : unknown 109 | : unknown 110 | : unknown 111 | : unknown 112 | : unknown 113 | : unknown 114 | : unknown 115 | : A extends [ 116 | infer U1, 117 | infer U2, 118 | infer U3, 119 | infer U4, 120 | infer U5, 121 | infer U6, 122 | infer U7, 123 | infer U8 124 | ] 125 | ? U1 extends S 126 | ? U2 extends S 127 | ? U3 extends S 128 | ? U4 extends S 129 | ? U5 extends S 130 | ? U6 extends S 131 | ? U7 extends S 132 | ? U8 extends S 133 | ? 134 | & TypeOf 135 | & TypeOf 136 | & TypeOf 137 | & TypeOf 138 | & TypeOf 139 | & TypeOf 140 | & TypeOf 141 | & TypeOf 142 | : unknown 143 | : unknown 144 | : unknown 145 | : unknown 146 | : unknown 147 | : unknown 148 | : unknown 149 | : unknown 150 | : A extends [ 151 | infer U1, 152 | infer U2, 153 | infer U3, 154 | infer U4, 155 | infer U5, 156 | infer U6, 157 | infer U7 158 | ] 159 | ? U1 extends S 160 | ? U2 extends S 161 | ? U3 extends S 162 | ? U4 extends S 163 | ? U5 extends S 164 | ? U6 extends S 165 | ? U7 extends S 166 | ? 167 | & TypeOf 168 | & TypeOf 169 | & TypeOf 170 | & TypeOf 171 | & TypeOf 172 | & TypeOf 173 | & TypeOf 174 | : unknown 175 | : unknown 176 | : unknown 177 | : unknown 178 | : unknown 179 | : unknown 180 | : unknown 181 | : A extends [infer U1, infer U2, infer U3, infer U4, infer U5, infer U6] 182 | ? U1 extends S 183 | ? U2 extends S 184 | ? U3 extends S 185 | ? U4 extends S 186 | ? U5 extends S 187 | ? U6 extends S 188 | ? 189 | & TypeOf 190 | & TypeOf 191 | & TypeOf 192 | & TypeOf 193 | & TypeOf 194 | & TypeOf 195 | : unknown 196 | : unknown 197 | : unknown 198 | : unknown 199 | : unknown 200 | : unknown 201 | : A extends [infer U1, infer U2, infer U3, infer U4, infer U5] 202 | ? U1 extends S 203 | ? U2 extends S 204 | ? U3 extends S 205 | ? U4 extends S 206 | ? U5 extends S 207 | ? TypeOf & TypeOf & TypeOf & TypeOf & TypeOf 208 | : unknown 209 | : unknown 210 | : unknown 211 | : unknown 212 | : unknown 213 | : A extends [infer U1, infer U2, infer U3, infer U4] 214 | ? U1 extends S 215 | ? U2 extends S 216 | ? U3 extends S 217 | ? U4 extends S 218 | ? TypeOf & TypeOf & TypeOf & TypeOf 219 | : unknown 220 | : unknown 221 | : unknown 222 | : unknown 223 | : A extends [infer U1, infer U2, infer U3] 224 | ? U1 extends S 225 | ? U2 extends S 226 | ? U3 extends S 227 | ? TypeOf & TypeOf & TypeOf 228 | : unknown 229 | : unknown 230 | : unknown 231 | : A extends [infer U1, infer U2] 232 | ? U1 extends S 233 | ? U2 extends S 234 | ? TypeOf & TypeOf 235 | : unknown 236 | : unknown 237 | : A extends [infer U1] 238 | ? U1 extends S 239 | ? TypeOf 240 | : unknown 241 | : A; 242 | 243 | export default Intersect; 244 | -------------------------------------------------------------------------------- /src/runtime/types/Literal/Checkable.ts: -------------------------------------------------------------------------------- 1 | import ResultModule from '@algebraic/types/Result'; 2 | import { Check } from '@runtime/defs'; 3 | import { LiteralΔ } from './Literal'; 4 | export { checkInt }; 5 | 6 | const isLiteral: Check> = (a, path, child) => 7 | a === child 8 | ? ResultModule.λ.Success (a) 9 | : ResultModule.λ.Failure ([ 10 | { 11 | code: 'IS_LITERAL', 12 | message: `Expected literal (${child} :: ${typeof child}) but found (${a} :: ${typeof a})`, 13 | path, 14 | }, 15 | ]); 16 | 17 | const checkInt = (a: unknown, path: string, child: any) => 18 | isLiteral (a, path, child); 19 | -------------------------------------------------------------------------------- /src/runtime/types/Literal/Literal.ts: -------------------------------------------------------------------------------- 1 | import { Schema, Childable, Checkable } from '@runtime/defs'; 2 | import { checkInt } from './Checkable'; 3 | 4 | export { LiteralΔ, LiteralΔ$, LiteralPrimitivesΔ$, Null, Undefined }; 5 | const LiteralΔ$ = Symbol ('Literal'); 6 | type LiteralΔ$ = typeof LiteralΔ$; 7 | type LiteralPrimitivesΔ$ = undefined | null | boolean | number | string; 8 | 9 | /** 10 | * TODO: Add comment 11 | */ 12 | type LiteralΔ = 13 | Schema & 14 | Checkable> & 15 | Childable 16 | 17 | const Literal = (child: A): LiteralΔ => ({ 18 | _: { 19 | type: LiteralΔ$, 20 | primitive: undefined as any, 21 | child, 22 | checkInt: (a, path) => checkInt (a, path, child), 23 | }, 24 | Δ: { 25 | check: (a) => checkInt (a, '', child) 26 | } 27 | }); 28 | 29 | const Null = Literal (null); 30 | const Undefined = Literal (undefined); 31 | 32 | export default Literal; 33 | -------------------------------------------------------------------------------- /src/runtime/types/Number/Checkable.ts: -------------------------------------------------------------------------------- 1 | import { Check } from '@runtime/defs'; 2 | import { NumberΔ } from './Number'; 3 | import ResultModule from '@algebraic/types/Result'; 4 | import rPipe from 'ramda/src/pipe'; 5 | import { sequence } from '@algebraic/common/sequence'; 6 | export { checkInt }; 7 | 8 | const isNumber: Check = (a, path) => 9 | typeof a === 'number' 10 | ? ResultModule.λ.Success (a) 11 | : ResultModule.λ.Failure ([ 12 | { 13 | code: 'IS_NUMBER', 14 | message: `Expected Number but found (${a} :: ${typeof a})`, 15 | path, 16 | }, 17 | ]); 18 | 19 | const doWithChecks = rPipe ( 20 | (payload: unknown, path: string, withChecks: Check[]) => 21 | sequence (ResultModule) (withChecks.map ((check) => check (payload, path))), 22 | ResultModule.λ.map ((s) => s[0]) 23 | ); 24 | 25 | const checkInt = (withChecks?: Check[]) => ( 26 | a: unknown, 27 | path: string 28 | ) => 29 | rPipe ( 30 | () => isNumber (a, path), 31 | (res) => 32 | withChecks && res.λ.id === 'Success' 33 | ? doWithChecks (a, path, withChecks) 34 | : isNumber (a, path) 35 | ) (); 36 | -------------------------------------------------------------------------------- /src/runtime/types/Number/Number.ts: -------------------------------------------------------------------------------- 1 | import { Schema, CheckableWith, Check } from '@runtime/defs'; 2 | import { checkInt } from './Checkable'; 3 | 4 | export { NumberΔ, NumberΔ$ }; 5 | const NumberΔ$ = Symbol ('Number'); 6 | type NumberΔ$ = typeof NumberΔ$; 7 | 8 | /** 9 | * TODO: Add comment 10 | */ 11 | type NumberΔ = Schema & CheckableWith; 12 | 13 | const Number = (withChecks?: Check[]): NumberΔ => ({ 14 | _: { 15 | type: NumberΔ$, 16 | primitive: undefined as any, 17 | checkInt: checkInt (withChecks), 18 | }, 19 | Δ: { 20 | check: (a) => checkInt (withChecks) (a, ''), 21 | checkWith: Number 22 | } 23 | }); 24 | 25 | export default Number (); 26 | -------------------------------------------------------------------------------- /src/runtime/types/Number/checks/isGreaterThan.ts: -------------------------------------------------------------------------------- 1 | import { Check } from '@runtime/defs'; 2 | import { NumberΔ } from '../Number'; 3 | import Result from '@algebraic/types/Result'; 4 | 5 | export { isGreaterThan }; 6 | 7 | const isGreaterThan = (p1: number): Check => (a, path) => 8 | typeof a === 'number' && a > p1 9 | ? Result.λ.Success (a) 10 | : Result.λ.Failure ([ 11 | { 12 | code: 'IS_NUMBER_GREATER_THAN', 13 | message: `Expected number to be greater than ${p1}.`, 14 | path, 15 | }, 16 | ]); 17 | -------------------------------------------------------------------------------- /src/runtime/types/Partial/Checkable.ts: -------------------------------------------------------------------------------- 1 | import ResultModule from '@algebraic/types/Result'; 2 | import { introspect } from '@runtime/introspection'; 3 | import { sequence } from '@algebraic/common/sequence'; 4 | import { Check, Checkable, Schema, InvalidCheck } from '@runtime/defs'; 5 | import rPipe from 'ramda/src/pipe'; 6 | import Partial, { PartialΔ } from './Partial'; 7 | import { Resultλ } from '@algebraic/types/Result/Result'; 8 | export { checkInt }; 9 | 10 | const buildPath = (previousPath: string, currentPath: string) => 11 | previousPath.length > 0 ? `${previousPath}.${currentPath}` : `${currentPath}`; 12 | 13 | const isPartial = (): Check< 14 | PartialΔ 15 | > => (a, path, child) => 16 | typeof a === 'object' 17 | ? ResultModule.λ.Success (a as any) 18 | : ResultModule.λ.Failure ([ 19 | { 20 | code: 'IS_PARTIAL', 21 | message: `Expected ${introspect ( 22 | Partial (child) 23 | )} but found (${a} :: ${typeof a})`, 24 | path, 25 | }, 26 | ]); 27 | 28 | const doChildChecks = ( 29 | a: any, 30 | path: string, 31 | child: { [key: string]: Checkable } 32 | ): Resultλ => 33 | sequence (ResultModule) ( 34 | Object.keys (child).map ((c) => { 35 | return a[c] === undefined || a[c] === null 36 | ? ResultModule.λ.Success (a) 37 | : child[c]._.checkInt (a[c], buildPath (path, c), child); 38 | }) 39 | ); 40 | 41 | const checkInt = ( 42 | a: unknown, 43 | path: string, 44 | child: any 45 | ) => 46 | rPipe ( 47 | (a: unknown, path: string, child: any) => isPartial () (a, path, child), 48 | ResultModule.λ.chain (() => doChildChecks (a, path, child)), 49 | ResultModule.λ.map (() => a as A) 50 | ) (a, path, child); 51 | -------------------------------------------------------------------------------- /src/runtime/types/Partial/Partial.ts: -------------------------------------------------------------------------------- 1 | import { Checkable, Childable, Schema, TypeOf } from '@runtime/defs'; 2 | import { checkInt } from './Checkable'; 3 | 4 | export { PartialΔ, PartialΔ$ }; 5 | const PartialΔ$ = Symbol ('Partial'); 6 | type PartialΔ$ = typeof PartialΔ$; 7 | 8 | /** 9 | * TODO: Add comment 10 | */ 11 | type PartialΔ = Schema< 12 | PartialΔ$, 13 | { [K in keyof A]?: TypeOf } 14 | > & 15 | Checkable> & 16 | Childable; 17 | 18 | const Partial = ( 19 | child: A 20 | ): PartialΔ => ({ 21 | _: { 22 | type: PartialΔ$, 23 | primitive: undefined as any, 24 | child, 25 | checkInt: (a, path) => checkInt (a, path, child), 26 | }, 27 | Δ: { 28 | check: (a) => checkInt (a, '', child), 29 | }, 30 | }); 31 | 32 | export default Partial; 33 | -------------------------------------------------------------------------------- /src/runtime/types/Record/Checkable.ts: -------------------------------------------------------------------------------- 1 | import ResultModule from '@algebraic/types/Result'; 2 | import { introspect } from 'src/runtime/introspection'; 3 | import { sequence } from '@algebraic/common/sequence'; 4 | import { Check, Checkable, Schema } from '@runtime/defs'; 5 | import rPipe from 'ramda/src/pipe'; 6 | import Record, { RecordΔ } from './Record'; 7 | export { checkInt }; 8 | 9 | const buildPath = (previousPath: string, currentPath: string) => 10 | previousPath.length > 0 ? `${previousPath}.${currentPath}` : `${currentPath}`; 11 | 12 | const isRecord = (): Check> => ( 13 | a, 14 | path, 15 | child 16 | ) => 17 | typeof a === 'object' 18 | ? ResultModule.λ.Success (a as A) 19 | : ResultModule.λ.Failure ([ 20 | { 21 | code: 'IS_RECORD', 22 | message: `Expected ${introspect ( 23 | Record (child) 24 | )} but found (${a} :: ${typeof a})`, 25 | path, 26 | }, 27 | ]); 28 | 29 | const doChildChecks = ( 30 | a: any, 31 | path: string, 32 | child: { [key: string]: Checkable } 33 | ) => 34 | sequence (ResultModule) ( 35 | Object.keys (child).map ((c) => 36 | child[c]._.checkInt (a[c], buildPath (path, c), child) 37 | ) 38 | ); 39 | 40 | const checkInt = ( 41 | a: unknown, 42 | path: string, 43 | child: any 44 | ) => 45 | rPipe ( 46 | (a: unknown, path: string, child: any) => isRecord () (a, path, child), 47 | ResultModule.λ.chain (() => doChildChecks (a, path, child)), 48 | ResultModule.λ.map (() => a as A) 49 | ) (a, path, child); 50 | -------------------------------------------------------------------------------- /src/runtime/types/Record/Record.ts: -------------------------------------------------------------------------------- 1 | import { Checkable, Childable, Schema, TypeOf } from '@runtime/defs'; 2 | import { checkInt } from './Checkable'; 3 | 4 | export { RecordΔ, RecordΔ$ }; 5 | const RecordΔ$ = Symbol ('Record'); 6 | type RecordΔ$ = typeof RecordΔ$; 7 | 8 | /** 9 | * TODO: Add comment 10 | */ 11 | type RecordΔ = Schema< 12 | RecordΔ$, 13 | { [K in keyof A]: TypeOf } 14 | > & 15 | Checkable> & 16 | Childable; 17 | 18 | const Record = (child: A): RecordΔ => ({ 19 | _: { 20 | type: RecordΔ$, 21 | primitive: undefined as any, 22 | child, 23 | checkInt: (a, path) => checkInt (a, path, child), 24 | }, 25 | Δ: { 26 | check: (a) => checkInt (a, '', child), 27 | }, 28 | }); 29 | 30 | export default Record; 31 | -------------------------------------------------------------------------------- /src/runtime/types/String/Checkable.ts: -------------------------------------------------------------------------------- 1 | import { Check } from '@runtime/defs'; 2 | import { StringΔ } from './String'; 3 | import ResultModule from '@algebraic/types/Result'; 4 | import rPipe from 'ramda/src/pipe'; 5 | import { sequence } from '@algebraic/common/sequence'; 6 | export { checkInt }; 7 | 8 | const isString: Check = (a, path) => 9 | typeof a === 'string' 10 | ? ResultModule.λ.Success (a) 11 | : ResultModule.λ.Failure ([ 12 | { 13 | code: 'IS_STRING', 14 | message: `Expected string but found (${a} :: ${typeof a})`, 15 | path, 16 | }, 17 | ]); 18 | 19 | const doWithChecks = rPipe ( 20 | (payload: unknown, path: string, withChecks: Check[]) => 21 | sequence (ResultModule) (withChecks.map ((check) => check (payload, path))), 22 | ResultModule.λ.map ((s) => s[0]) 23 | ); 24 | 25 | const checkInt = (withChecks?: Check[]) => ( 26 | a: unknown, 27 | path: string 28 | ) => 29 | rPipe ( 30 | () => isString (a, path), 31 | (res) => 32 | withChecks && res.λ.id === 'Success' 33 | ? doWithChecks (a, path, withChecks) 34 | : isString (a, path) 35 | ) (); 36 | -------------------------------------------------------------------------------- /src/runtime/types/String/String.ts: -------------------------------------------------------------------------------- 1 | import { Schema, CheckableWith, Check } from '@runtime/defs'; 2 | import { checkInt } from './Checkable'; 3 | 4 | export { StringΔ, StringΔ$ }; 5 | const StringΔ$ = Symbol ('String'); 6 | type StringΔ$ = typeof StringΔ$; 7 | 8 | /** 9 | * TODO: Add comment 10 | */ 11 | type StringΔ = Schema & CheckableWith; 12 | 13 | const String = (withChecks?: Check[]): StringΔ => ({ 14 | _: { 15 | type: StringΔ$, 16 | primitive: undefined as any, 17 | checkInt: checkInt (withChecks) 18 | }, 19 | Δ: { 20 | check: (a) => checkInt (withChecks) (a, ''), 21 | checkWith: String 22 | } 23 | }); 24 | 25 | export default String (); 26 | -------------------------------------------------------------------------------- /src/runtime/types/String/checks/isGreaterThan.ts: -------------------------------------------------------------------------------- 1 | import { Check } from '@runtime/defs'; 2 | import { StringΔ } from '../String'; 3 | import Result from '@algebraic/types/Result'; 4 | 5 | export { isGreaterThan }; 6 | 7 | const isGreaterThan = (p1: number): Check => (a, path) => 8 | typeof a === 'string' && a.length > p1 9 | ? Result.λ.Success (a) 10 | : Result.λ.Failure ([ 11 | { 12 | code: 'IS_STRING_GREATER_THAN', 13 | message: `Expected string to be greater than ${p1}.`, 14 | path, 15 | }, 16 | ]); 17 | -------------------------------------------------------------------------------- /src/runtime/types/String/index.ts: -------------------------------------------------------------------------------- 1 | import String from './String'; 2 | 3 | export { String }; -------------------------------------------------------------------------------- /src/runtime/types/Tuple/Checkable.ts: -------------------------------------------------------------------------------- 1 | import ResultModule from '@algebraic/types/Result'; 2 | import { introspect } from 'src/runtime/introspection'; 3 | import { sequence } from '@algebraic/common/sequence'; 4 | import { Check, Checkable, Schema, InvalidCheck } from '@runtime/defs'; 5 | import rPipe from 'ramda/src/pipe'; 6 | import Tuple, { TupleΔ } from './Tuple'; 7 | import { Resultλ } from '@algebraic/types/Result/Result'; 8 | export { checkInt }; 9 | 10 | const buildPath = (indice: number, parentPath?: string) => 11 | parentPath ? `${parentPath}[${indice}]` : `[${indice}]`; 12 | 13 | const isTuple = )[]>(): Check< 14 | TupleΔ 15 | > => (a, path, child) => 16 | globalThis.Array.isArray (a) && globalThis.Array.isArray (child) && a.length === child.length 17 | ? ResultModule.λ.Success (a as any) 18 | : ResultModule.λ.Failure ([ 19 | { 20 | code: 'IS_TUPLE', 21 | message: `Expected ${introspect ( 22 | Tuple (...child) 23 | )} but found (${a} :: ${typeof a})`, 24 | path, 25 | }, 26 | ]); 27 | 28 | const doChildChecks = )[]>( 29 | path: string, 30 | child: TupleΔ['_']['child'] 31 | ) => (payload: any[]) => 32 | sequence (ResultModule) ( 33 | payload.map ((v, i) => 34 | child[i]._.checkInt (v, buildPath (i, path), (child as any)?.child) 35 | ) 36 | ); 37 | 38 | const checkInt = )[]>( 39 | a: unknown, 40 | path: string, 41 | child: TupleΔ['_']['child'] 42 | ) => 43 | rPipe ( 44 | (a: unknown, path: string, child: any) => isTuple () (a, path, child), 45 | ResultModule.λ.chain (doChildChecks (path, child)) 46 | ) (a, path, child) as Resultλ; 47 | -------------------------------------------------------------------------------- /src/runtime/types/Tuple/Tuple.ts: -------------------------------------------------------------------------------- 1 | import { Checkable, Childable, Schema, TypeOf } from '@runtime/defs'; 2 | import { checkInt } from './Checkable'; 3 | 4 | export { TupleΔ, TupleΔ$, TuplePrimitiveΔ$ }; 5 | const TupleΔ$ = Symbol ('Tuple'); 6 | type TupleΔ$ = typeof TupleΔ$; 7 | 8 | /** 9 | * TODO: Add comment 10 | */ 11 | type TupleΔ)[]> = Schema< 12 | TupleΔ$, 13 | TuplePrimitiveΔ$ 14 | > & 15 | Checkable> & 16 | Childable; 17 | 18 | const Tuple = )[]>( 19 | ...child: A 20 | ): TupleΔ => ({ 21 | _: { 22 | type: TupleΔ$, 23 | primitive: undefined as any, 24 | child, 25 | checkInt, 26 | }, 27 | Δ: { 28 | check: (a) => checkInt (a, '', child), 29 | }, 30 | }); 31 | 32 | type S = Schema; 33 | type TuplePrimitiveΔ$ = A extends [ 34 | infer U1, 35 | infer U2, 36 | infer U3, 37 | infer U4, 38 | infer U5, 39 | infer U6, 40 | infer U7, 41 | infer U8, 42 | infer U9, 43 | infer U10 44 | ] 45 | ? U1 extends S 46 | ? U2 extends S 47 | ? U3 extends S 48 | ? U4 extends S 49 | ? U5 extends S 50 | ? U6 extends S 51 | ? U7 extends S 52 | ? U8 extends S 53 | ? U9 extends S 54 | ? U10 extends S 55 | ? [ 56 | TypeOf, 57 | TypeOf, 58 | TypeOf, 59 | TypeOf, 60 | TypeOf, 61 | TypeOf, 62 | TypeOf, 63 | TypeOf, 64 | TypeOf, 65 | TypeOf 66 | ] 67 | : unknown 68 | : unknown 69 | : unknown 70 | : unknown 71 | : unknown 72 | : unknown 73 | : unknown 74 | : unknown 75 | : unknown 76 | : unknown 77 | : A extends [ 78 | infer U1, 79 | infer U2, 80 | infer U3, 81 | infer U4, 82 | infer U5, 83 | infer U6, 84 | infer U7, 85 | infer U8, 86 | infer U9 87 | ] 88 | ? U1 extends S 89 | ? U2 extends S 90 | ? U3 extends S 91 | ? U4 extends S 92 | ? U5 extends S 93 | ? U6 extends S 94 | ? U7 extends S 95 | ? U8 extends S 96 | ? U9 extends S 97 | ? [ 98 | TypeOf, 99 | TypeOf, 100 | TypeOf, 101 | TypeOf, 102 | TypeOf, 103 | TypeOf, 104 | TypeOf, 105 | TypeOf, 106 | TypeOf 107 | ] 108 | : unknown 109 | : unknown 110 | : unknown 111 | : unknown 112 | : unknown 113 | : unknown 114 | : unknown 115 | : unknown 116 | : unknown 117 | : A extends [ 118 | infer U1, 119 | infer U2, 120 | infer U3, 121 | infer U4, 122 | infer U5, 123 | infer U6, 124 | infer U7, 125 | infer U8 126 | ] 127 | ? U1 extends S 128 | ? U2 extends S 129 | ? U3 extends S 130 | ? U4 extends S 131 | ? U5 extends S 132 | ? U6 extends S 133 | ? U7 extends S 134 | ? U8 extends S 135 | ? [ 136 | TypeOf, 137 | TypeOf, 138 | TypeOf, 139 | TypeOf, 140 | TypeOf, 141 | TypeOf, 142 | TypeOf, 143 | TypeOf 144 | ] 145 | : unknown 146 | : unknown 147 | : unknown 148 | : unknown 149 | : unknown 150 | : unknown 151 | : unknown 152 | : unknown 153 | : A extends [ 154 | infer U1, 155 | infer U2, 156 | infer U3, 157 | infer U4, 158 | infer U5, 159 | infer U6, 160 | infer U7 161 | ] 162 | ? U1 extends S 163 | ? U2 extends S 164 | ? U3 extends S 165 | ? U4 extends S 166 | ? U5 extends S 167 | ? U6 extends S 168 | ? U7 extends S 169 | ? [ 170 | TypeOf, 171 | TypeOf, 172 | TypeOf, 173 | TypeOf, 174 | TypeOf, 175 | TypeOf, 176 | TypeOf 177 | ] 178 | : unknown 179 | : unknown 180 | : unknown 181 | : unknown 182 | : unknown 183 | : unknown 184 | : unknown 185 | : A extends [infer U1, infer U2, infer U3, infer U4, infer U5, infer U6] 186 | ? U1 extends S 187 | ? U2 extends S 188 | ? U3 extends S 189 | ? U4 extends S 190 | ? U5 extends S 191 | ? U6 extends S 192 | ? [ 193 | TypeOf, 194 | TypeOf, 195 | TypeOf, 196 | TypeOf, 197 | TypeOf, 198 | TypeOf 199 | ] 200 | : unknown 201 | : unknown 202 | : unknown 203 | : unknown 204 | : unknown 205 | : unknown 206 | : A extends [infer U1, infer U2, infer U3, infer U4, infer U5] 207 | ? U1 extends S 208 | ? U2 extends S 209 | ? U3 extends S 210 | ? U4 extends S 211 | ? U5 extends S 212 | ? [TypeOf, TypeOf, TypeOf, TypeOf, TypeOf] 213 | : unknown 214 | : unknown 215 | : unknown 216 | : unknown 217 | : unknown 218 | : A extends [infer U1, infer U2, infer U3, infer U4] 219 | ? U1 extends S 220 | ? U2 extends S 221 | ? U3 extends S 222 | ? U4 extends S 223 | ? [TypeOf, TypeOf, TypeOf, TypeOf] 224 | : unknown 225 | : unknown 226 | : unknown 227 | : unknown 228 | : A extends [infer U1, infer U2, infer U3] 229 | ? U1 extends S 230 | ? U2 extends S 231 | ? U3 extends S 232 | ? [TypeOf, TypeOf, TypeOf] 233 | : unknown 234 | : unknown 235 | : unknown 236 | : A extends [infer U1, infer U2] 237 | ? U1 extends S 238 | ? U2 extends S 239 | ? [TypeOf, TypeOf] 240 | : unknown 241 | : unknown 242 | : A extends [infer U1] 243 | ? U1 extends S 244 | ? [TypeOf] 245 | : unknown 246 | : any; 247 | 248 | export default Tuple; 249 | -------------------------------------------------------------------------------- /src/runtime/types/Union/Checkable.ts: -------------------------------------------------------------------------------- 1 | import ResultModule from '@algebraic/types/Result'; 2 | import { Resultλ } from '@algebraic/types/Result/Result'; 3 | import { introspect } from 'src/runtime/introspection'; 4 | import { Checkable, InvalidCheck, Schema } from '@runtime/defs'; 5 | import rPipe from 'ramda/src/pipe'; 6 | import Union, { UnionΔ } from './Union'; 7 | import { pipe } from '@algebraic/common/pipe'; 8 | import { sequence } from '@algebraic/common/sequence'; 9 | export { checkInt }; 10 | 11 | const doChildChecks = )[]>( 12 | a: unknown, 13 | path: string, 14 | child: UnionΔ['_']['child'] 15 | ) => child.map ((c) => c._.checkInt (a, path, child)); 16 | 17 | const suceedOrFail = )[]>( 18 | a: UnionΔ['_']['primitive'], 19 | path: string, 20 | child: UnionΔ['_']['child'] 21 | ) => ( 22 | childResults: Resultλ[] 23 | ): Resultλ['_']['primitive']> => 24 | childResults.some ((i) => i.λ.id === 'Success') 25 | ? ResultModule.λ.Success (a) 26 | : ResultModule.λ.Failure ([ 27 | { 28 | code: 'IS_UNION', 29 | message: `Expected ${introspect ( 30 | Union (...child) 31 | )} but found (${typeof a === 'object' ? JSON.stringify (a) : a} :: ${typeof a})`, 32 | path, 33 | }, 34 | ]) 35 | ; 36 | 37 | const checkInt = )[]>( 38 | child: UnionΔ['_']['child'] 39 | ) => (a: unknown, path: string) => 40 | rPipe ( 41 | (a: unknown, path: string) => doChildChecks (a, path, child), 42 | suceedOrFail (a as any, path, child) 43 | ) (a, path); 44 | -------------------------------------------------------------------------------- /src/runtime/types/Union/Union.ts: -------------------------------------------------------------------------------- 1 | import { Checkable, Childable, Schema, TypeOf } from '@runtime/defs'; 2 | import { checkInt } from './Checkable'; 3 | 4 | export { UnionΔ, UnionΔ$, UnionPrimitiveΔ$ }; 5 | const UnionΔ$ = Symbol ('Union'); 6 | type UnionΔ$ = typeof UnionΔ$; 7 | 8 | /** 9 | * TODO: Add comment 10 | */ 11 | type UnionΔ)[]> = Schema< 12 | UnionΔ$, 13 | UnionPrimitiveΔ$ 14 | > & 15 | Checkable> & 16 | Childable; 17 | 18 | const Union = )[]>( 19 | ...child: A 20 | ): UnionΔ => ({ 21 | _: { 22 | type: UnionΔ$, 23 | primitive: undefined as any, 24 | child, 25 | checkInt: checkInt (child), 26 | }, 27 | Δ: { 28 | check: (a) => checkInt (child) (a, ''), 29 | }, 30 | }); 31 | 32 | type S = Schema; 33 | type UnionPrimitiveΔ$ = A extends [ 34 | infer U1, 35 | infer U2, 36 | infer U3, 37 | infer U4, 38 | infer U5, 39 | infer U6, 40 | infer U7, 41 | infer U8, 42 | infer U9, 43 | infer U10 44 | ] 45 | ? U1 extends S 46 | ? U2 extends S 47 | ? U3 extends S 48 | ? U4 extends S 49 | ? U5 extends S 50 | ? U6 extends S 51 | ? U7 extends S 52 | ? U8 extends S 53 | ? U9 extends S 54 | ? U10 extends S 55 | ? 56 | | TypeOf 57 | | TypeOf 58 | | TypeOf 59 | | TypeOf 60 | | TypeOf 61 | | TypeOf 62 | | TypeOf 63 | | TypeOf 64 | | TypeOf 65 | | TypeOf 66 | : unknown 67 | : unknown 68 | : unknown 69 | : unknown 70 | : unknown 71 | : unknown 72 | : unknown 73 | : unknown 74 | : unknown 75 | : unknown 76 | : A extends [ 77 | infer U1, 78 | infer U2, 79 | infer U3, 80 | infer U4, 81 | infer U5, 82 | infer U6, 83 | infer U7, 84 | infer U8, 85 | infer U9 86 | ] 87 | ? U1 extends S 88 | ? U2 extends S 89 | ? U3 extends S 90 | ? U4 extends S 91 | ? U5 extends S 92 | ? U6 extends S 93 | ? U7 extends S 94 | ? U8 extends S 95 | ? U9 extends S 96 | ? 97 | | TypeOf 98 | | TypeOf 99 | | TypeOf 100 | | TypeOf 101 | | TypeOf 102 | | TypeOf 103 | | TypeOf 104 | | TypeOf 105 | | TypeOf 106 | : unknown 107 | : unknown 108 | : unknown 109 | : unknown 110 | : unknown 111 | : unknown 112 | : unknown 113 | : unknown 114 | : unknown 115 | : A extends [ 116 | infer U1, 117 | infer U2, 118 | infer U3, 119 | infer U4, 120 | infer U5, 121 | infer U6, 122 | infer U7, 123 | infer U8 124 | ] 125 | ? U1 extends S 126 | ? U2 extends S 127 | ? U3 extends S 128 | ? U4 extends S 129 | ? U5 extends S 130 | ? U6 extends S 131 | ? U7 extends S 132 | ? U8 extends S 133 | ? 134 | | TypeOf 135 | | TypeOf 136 | | TypeOf 137 | | TypeOf 138 | | TypeOf 139 | | TypeOf 140 | | TypeOf 141 | | TypeOf 142 | : unknown 143 | : unknown 144 | : unknown 145 | : unknown 146 | : unknown 147 | : unknown 148 | : unknown 149 | : unknown 150 | : A extends [ 151 | infer U1, 152 | infer U2, 153 | infer U3, 154 | infer U4, 155 | infer U5, 156 | infer U6, 157 | infer U7 158 | ] 159 | ? U1 extends S 160 | ? U2 extends S 161 | ? U3 extends S 162 | ? U4 extends S 163 | ? U5 extends S 164 | ? U6 extends S 165 | ? U7 extends S 166 | ? 167 | | TypeOf 168 | | TypeOf 169 | | TypeOf 170 | | TypeOf 171 | | TypeOf 172 | | TypeOf 173 | | TypeOf 174 | : unknown 175 | : unknown 176 | : unknown 177 | : unknown 178 | : unknown 179 | : unknown 180 | : unknown 181 | : A extends [infer U1, infer U2, infer U3, infer U4, infer U5, infer U6] 182 | ? U1 extends S 183 | ? U2 extends S 184 | ? U3 extends S 185 | ? U4 extends S 186 | ? U5 extends S 187 | ? U6 extends S 188 | ? 189 | | TypeOf 190 | | TypeOf 191 | | TypeOf 192 | | TypeOf 193 | | TypeOf 194 | | TypeOf 195 | : unknown 196 | : unknown 197 | : unknown 198 | : unknown 199 | : unknown 200 | : unknown 201 | : A extends [infer U1, infer U2, infer U3, infer U4, infer U5] 202 | ? U1 extends S 203 | ? U2 extends S 204 | ? U3 extends S 205 | ? U4 extends S 206 | ? U5 extends S 207 | ? TypeOf | TypeOf | TypeOf | TypeOf | TypeOf 208 | : unknown 209 | : unknown 210 | : unknown 211 | : unknown 212 | : unknown 213 | : A extends [infer U1, infer U2, infer U3, infer U4] 214 | ? U1 extends S 215 | ? U2 extends S 216 | ? U3 extends S 217 | ? U4 extends S 218 | ? TypeOf | TypeOf | TypeOf | TypeOf 219 | : unknown 220 | : unknown 221 | : unknown 222 | : unknown 223 | : A extends [infer U1, infer U2, infer U3] 224 | ? U1 extends S 225 | ? U2 extends S 226 | ? U3 extends S 227 | ? TypeOf | TypeOf | TypeOf 228 | : unknown 229 | : unknown 230 | : unknown 231 | : A extends [infer U1, infer U2] 232 | ? U1 extends S 233 | ? U2 extends S 234 | ? TypeOf | TypeOf 235 | : unknown 236 | : unknown 237 | : A extends [infer U1] 238 | ? U1 extends S 239 | ? TypeOf 240 | : unknown 241 | : A; 242 | 243 | export default Union; 244 | -------------------------------------------------------------------------------- /tests/algebraic/Async/Functions.test.ts: -------------------------------------------------------------------------------- 1 | import { pipe } from '@algebraic/common/pipe'; 2 | import { bindOf, bindTo } from '@algebraic/types/Async/Functions'; 3 | import Async from '@algebraic/types/Async'; 4 | 5 | describe ('Async (Functions)', () => { 6 | it ('bindOf', async () => { 7 | const userBind = await pipe (Async.λ.of ('Mike'), bindOf ('firstName')) (); 8 | 9 | expect (userBind).toStrictEqual ({ firstName: 'Mike' }); 10 | }); 11 | 12 | it ('bindTo', async () => { 13 | const userAddBinds = await pipe ( 14 | Async.λ.of ('Mike'), 15 | bindOf ('firstName'), 16 | bindTo ('lastName', () => Async.λ.of ('Lance')) 17 | ) (); 18 | 19 | expect (userAddBinds).toStrictEqual ({ 20 | firstName: 'Mike', 21 | lastName: 'Lance', 22 | }); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /tests/algebraic/AsyncEither/Functions.test.ts: -------------------------------------------------------------------------------- 1 | import { pipe } from '@algebraic/common/pipe'; 2 | import {bindOf, bindTo} from '@algebraic/types/AsyncEither/Functions'; 3 | import AsyncEither from '@algebraic/types/AsyncEither'; 4 | 5 | describe ('AsyncEither (Functions)', () => { 6 | 7 | it ('bindOf', async () => { 8 | const userBind = await pipe ( 9 | AsyncEither.λ.of ('Mike'), 10 | bindOf ('firstName') 11 | ) (); 12 | 13 | expect (userBind).toStrictEqual ({ 14 | λ: { 15 | id: 'Right', 16 | kind: 'Either', 17 | typeB: undefined, 18 | value: { firstName: 'Mike' }, 19 | }, 20 | }); 21 | }); 22 | 23 | it ('bindTo', async () => { 24 | const userAddBinds = await pipe ( 25 | AsyncEither.λ.of ('Mike'), 26 | bindOf ('firstName'), 27 | bindTo ('lastName', () => AsyncEither.λ.Right ('Lance')) 28 | ) (); 29 | 30 | expect (userAddBinds).toStrictEqual ({ 31 | λ: { 32 | id: 'Right', 33 | kind: 'Either', 34 | typeB: undefined, 35 | value: { firstName: 'Mike', lastName: 'Lance' }, 36 | }, 37 | }); 38 | }); 39 | }) -------------------------------------------------------------------------------- /tests/algebraic/AsyncResult/Functions.test.ts: -------------------------------------------------------------------------------- 1 | import { pipe } from '@algebraic/common/pipe'; 2 | import { bindOf, bindTo } from '@algebraic/types/AsyncResult/Functions'; 3 | import AsyncResult from '@algebraic/types/AsyncResult'; 4 | 5 | describe ('AsyncResult (Functions)', () => { 6 | it ('bindOf', async () => { 7 | const userBind = await pipe ( 8 | AsyncResult.λ.of ('Mike'), 9 | bindOf ('firstName') 10 | ) (); 11 | 12 | expect (userBind).toStrictEqual ({ 13 | λ: { 14 | id: 'Success', 15 | kind: 'Result', 16 | type: undefined, 17 | value: { firstName: 'Mike' }, 18 | }, 19 | }); 20 | }); 21 | 22 | it ('bindTo', async () => { 23 | const userAddBinds = await pipe ( 24 | AsyncResult.λ.of ('Mike'), 25 | bindOf ('firstName'), 26 | bindTo ('lastName', () => AsyncResult.λ.Success ('Lance')) 27 | ) (); 28 | 29 | expect (userAddBinds).toStrictEqual ({ 30 | λ: { 31 | id: 'Success', 32 | kind: 'Result', 33 | type: undefined, 34 | value: { firstName: 'Mike', lastName: 'Lance' }, 35 | }, 36 | }); 37 | }); 38 | }); 39 | -------------------------------------------------------------------------------- /tests/algebraic/Either/Functions.test.ts: -------------------------------------------------------------------------------- 1 | import { pipe } from '@algebraic/common/pipe'; 2 | import {bindOf, bindTo} from '@algebraic/types/Either/Functions'; 3 | import Either from '@algebraic/types/Either'; 4 | 5 | describe ('Either (Functions)', () => { 6 | 7 | it ('bindOf', () => { 8 | const userBind = pipe ( 9 | Either.λ.of ('Mike'), 10 | bindOf ('firstName') 11 | ) 12 | 13 | expect (userBind).toStrictEqual ({ 14 | λ: { 15 | id: 'Right', 16 | kind: 'Either', 17 | typeB: undefined, 18 | value: { firstName: 'Mike' }, 19 | }, 20 | }); 21 | }); 22 | 23 | it ('bindTo', () => { 24 | const userAddBinds = pipe ( 25 | Either.λ.of ('Mike'), 26 | bindOf ('firstName'), 27 | bindTo ('lastName', () => Either.λ.Right ('Lance')) 28 | ); 29 | 30 | expect (userAddBinds).toStrictEqual ({ 31 | λ: { 32 | id: 'Right', 33 | kind: 'Either', 34 | typeB: undefined, 35 | value: { firstName: 'Mike', lastName: 'Lance' }, 36 | }, 37 | }); 38 | }); 39 | }) -------------------------------------------------------------------------------- /tests/algebraic/Maybe/Functions.test.ts: -------------------------------------------------------------------------------- 1 | import { pipe } from '@algebraic/common/pipe'; 2 | // import pipe from 'ramda/src/pipe' 3 | import {bindOf, bindTo} from '@algebraic/types/Maybe/Functions'; 4 | import Maybe from '@algebraic/types/Maybe'; 5 | 6 | describe ('Maybe (Functions)', () => { 7 | 8 | it ('bindOf', () => { 9 | const userBind = pipe ( 10 | Maybe.λ.of ('Mike'), 11 | bindOf ('firstName') 12 | ); 13 | 14 | expect (userBind).toStrictEqual ({ 15 | λ: { 16 | id: 'Just', 17 | kind: 'Maybe', 18 | typeA: undefined, 19 | value: { firstName: 'Mike' }, 20 | }, 21 | }); 22 | }); 23 | 24 | it ('bindTo', () => { 25 | const userAddBinds = pipe ( 26 | Maybe.λ.of ('Mike'), 27 | bindOf ('firstName'), 28 | bindTo ('lastName', () => Maybe.λ.Just ('Lance')) 29 | ); 30 | 31 | expect (userAddBinds).toStrictEqual ({ 32 | λ: { 33 | id: 'Just', 34 | kind: 'Maybe', 35 | typeA: undefined, 36 | value: { firstName: 'Mike', lastName: 'Lance' }, 37 | }, 38 | }); 39 | }); 40 | }) -------------------------------------------------------------------------------- /tests/algebraic/Result/Functions.test.ts: -------------------------------------------------------------------------------- 1 | import { pipe } from '@algebraic/common/pipe'; 2 | import {bindOf, bindTo} from '@algebraic/types/Result/Functions'; 3 | import Result from '@algebraic/types/Result'; 4 | 5 | describe ('Result (Functions)', () => { 6 | 7 | it ('bindOf', () => { 8 | const userBind = pipe ( 9 | Result.λ.of ('Mike'), 10 | bindOf ('firstName') 11 | ); 12 | 13 | expect (userBind).toStrictEqual ({ 14 | λ: { 15 | id: 'Success', 16 | kind: 'Result', 17 | type: undefined, 18 | value: { firstName: 'Mike' }, 19 | }, 20 | }); 21 | }); 22 | 23 | it ('bindTo', () => { 24 | const userAddBinds = pipe ( 25 | Result.λ.of ('Mike'), 26 | bindOf ('firstName'), 27 | bindTo ('lastName', () => Result.λ.Success ('Lance')) 28 | ); 29 | 30 | expect (userAddBinds).toStrictEqual ({ 31 | λ: { 32 | id: 'Success', 33 | kind: 'Result', 34 | type: undefined, 35 | value: { firstName: 'Mike', lastName: 'Lance' }, 36 | }, 37 | }); 38 | }); 39 | }) -------------------------------------------------------------------------------- /tests/algebraic/common/sequenceTuple.performance.ts: -------------------------------------------------------------------------------- 1 | import * as Benchmark from 'benchmark' 2 | import EitherModule from '../../../src/algebraic/types/Either'; 3 | import { sequenceTuple } from '../../../src/algebraic/common/sequenceTuple'; 4 | import { isRight } from '../../../src/algebraic/types/Either/Functions'; 5 | 6 | 7 | const suite = new Benchmark.Suite () 8 | 9 | suite 10 | .add ('[ 🧪 ] sequenceTuple (1)', function () { 11 | sequenceTuple (EitherModule) (EitherModule.λ.Right (1)) 12 | }) 13 | .add ('[ 🧪 ] sequenceTuple (2)', function () { 14 | sequenceTuple (EitherModule) (EitherModule.λ.Right (1), EitherModule.λ.Right (2)) 15 | }) 16 | .add ('[ 🧪 ] sequenceTuple (3)', function () { 17 | sequenceTuple (EitherModule) (EitherModule.λ.Right (1), EitherModule.λ.Right (2), EitherModule.λ.Right (3)) 18 | }) 19 | .add ('[ 🧪 ] sequenceTuple (4)', function () { 20 | sequenceTuple (EitherModule) (EitherModule.λ.Right (1), EitherModule.λ.Right (2), EitherModule.λ.Right (3), EitherModule.λ.Right (4)) 21 | }) 22 | .add ('[ 🧪 ] sequenceTuple (5)', function () { 23 | sequenceTuple (EitherModule) (EitherModule.λ.Right (1), EitherModule.λ.Right (2), EitherModule.λ.Right (3), EitherModule.λ.Right (4), EitherModule.λ.Right (5)) 24 | }) 25 | .add ('[ 🧪 ] sequenceTuple (6)', function () { 26 | sequenceTuple (EitherModule) (EitherModule.λ.Right (1), EitherModule.λ.Right (2), EitherModule.λ.Right (3), EitherModule.λ.Right (4), EitherModule.λ.Right (5), EitherModule.λ.Right (6)) 27 | }) 28 | .add ('[ 🧪 ] sequenceTuple (7)', function () { 29 | sequenceTuple (EitherModule) (EitherModule.λ.Right (1), EitherModule.λ.Right (2), EitherModule.λ.Right (3), EitherModule.λ.Right (4), EitherModule.λ.Right (5), EitherModule.λ.Right (6), EitherModule.λ.Right (7)) 30 | }) 31 | .on ('cycle', function (event: any) { 32 | console.log (String (event.target)) 33 | }) 34 | .on ('complete', function (this: any) { 35 | console.log ('[ 🏆 ] The fastest implementation is ' + this.filter ('fastest').map ('name')) 36 | }) 37 | .run ({ async: true }) -------------------------------------------------------------------------------- /tests/algebraic/common/sequenceTuple.test.ts: -------------------------------------------------------------------------------- 1 | import ResultModule from '@algebraic/types/Result'; 2 | import { sequenceTuple } from '@algebraic/common/sequenceTuple'; 3 | import { isSuccess, isFailure } from '@algebraic/types/Result/Functions'; 4 | import { identity } from '@common/identity'; 5 | 6 | const A = ResultModule.λ.Success<'SomeType', boolean> (true); 7 | const B = ResultModule.λ.Success<'Other Type', string> ('B'); 8 | const C = ResultModule.λ.Success<'Other Type', number> (1); 9 | const D = ResultModule.λ.Failure<'C Type', boolean> (['C Type']); 10 | const E = ResultModule.λ.Failure<'D Type', boolean> (['D Type']); 11 | 12 | it ('Should pass when tupling with only Success cases', () => { 13 | const tupleResult = sequenceTuple (ResultModule) (A, B, C); 14 | expect (isSuccess (tupleResult)).toBeTruthy (); 15 | expect (ResultModule.λ.fold (identity, identity) (tupleResult)).toStrictEqual ([ 16 | true, 17 | 'B', 18 | 1, 19 | ]); 20 | }); 21 | 22 | it ('Should pass when tupling with Failure & Success cases', () => { 23 | const tupleResult = sequenceTuple (ResultModule) (A, B, C, D, E); 24 | expect (isFailure (tupleResult)).toBeTruthy (); 25 | expect (ResultModule.λ.fold (identity, identity) (tupleResult)).toStrictEqual ([ 26 | 'C Type', 27 | 'D Type', 28 | ]); 29 | }); 30 | -------------------------------------------------------------------------------- /tests/algebraic/common/tap.test.ts: -------------------------------------------------------------------------------- 1 | import { tap } from '@algebraic/common/tap'; 2 | import ResultModule from '@algebraic/types/Result'; 3 | import pipe from 'ramda/src/pipe'; 4 | import { isSuccessOf } from '@algebraic/types/Result/Functions'; 5 | 6 | it ('Should pass when we update state of database with tap', () => { 7 | let DbInstance = null; 8 | const User = ResultModule.λ.of ({ firstName: 'Mike' }); 9 | const saveToDb = (user: object) => { 10 | DbInstance = user; 11 | }; 12 | const saveUserRes = pipe (() => User, tap (ResultModule) (saveToDb)) (); 13 | expect (isSuccessOf (saveUserRes, { firstName: 'Mike' })).toBeTruthy (); 14 | expect (DbInstance).toStrictEqual ({ firstName: 'Mike' }); 15 | }); 16 | -------------------------------------------------------------------------------- /tests/runtime/1Examples/Sports.test.ts: -------------------------------------------------------------------------------- 1 | import { 2 | String, 3 | Number, 4 | Boolean, 5 | Array, 6 | Record, 7 | Literal, 8 | Tuple, 9 | Union, 10 | } from 'src/runtime/index'; 11 | import { TypeOf } from '@runtime/defs'; 12 | import { isSuccessOf } from '@algebraic/types/Result/Functions'; 13 | import { Result } from '@algebraic/index'; 14 | import { identity } from '@common/identity'; 15 | 16 | const League = Union ( 17 | Literal ('NFL'), 18 | Literal ('MLB'), 19 | Literal ('NBA'), 20 | Literal ('WNBA') 21 | ); 22 | 23 | const Gender = Union (Literal ('Male'), Literal ('Female'), Literal ('Other')); 24 | 25 | const Team = Record ({ 26 | name: String, 27 | yearFounded: Number, 28 | league: League, 29 | type: Literal ('team'), 30 | }); 31 | 32 | const Player = Record ({ 33 | firstName: String, 34 | lastName: String, 35 | salaryOnTeam: Tuple (Number, Team), 36 | age: Number, 37 | isActive: Boolean, 38 | teamsPlayed: Array (Team), 39 | gender: Gender, 40 | type: Literal ('player'), 41 | }); 42 | 43 | type Player = TypeOf; 44 | 45 | it ('Should pass with a valid team', () => { 46 | const teamPayload = { 47 | name: 'Seattle Seahawks', 48 | yearFounded: 1974, 49 | league: 'NFL', 50 | type: 'team', 51 | }; 52 | 53 | const isTeam = Team.Δ.check (teamPayload); 54 | expect (isSuccessOf (isTeam, teamPayload)).toBeTruthy (); 55 | }); 56 | 57 | it ('Should fail with an invalid team', () => { 58 | const teamPayload = { 59 | name: true, 60 | yearFounded: '1974', 61 | league: 'Soccer', 62 | type: 'other', 63 | }; 64 | 65 | const isTeam = Team.Δ.check (teamPayload); 66 | expect (isSuccessOf (isTeam, teamPayload)).toBeFalsy (); 67 | }); 68 | 69 | it ('Should pass with correct error return with an invalid team', () => { 70 | const teamPayload = { 71 | name: null, 72 | yearFounded: '1974', 73 | league: 'Soccer', 74 | type: 'other', 75 | }; 76 | 77 | const isTeam = Team.Δ.check (teamPayload); 78 | const isTeamRes = Result.λ.fold (identity, identity) (isTeam); 79 | expect (isTeamRes).toEqual ([ 80 | { 81 | code: 'IS_STRING', 82 | message: 'Expected string but found (null :: object)', 83 | path: 'name' 84 | }, 85 | { 86 | code: 'IS_NUMBER', 87 | message: 'Expected Number but found (1974 :: string)', 88 | path: 'yearFounded' 89 | }, 90 | { 91 | code: 'IS_UNION', 92 | message: 'Expected (NFL | MLB | NBA | WNBA) but found (Soccer :: string)', 93 | path: 'league' 94 | }, 95 | { 96 | code: 'IS_LITERAL', 97 | message: 'Expected literal (team :: string) but found (other :: string)', 98 | path: 'type' 99 | } 100 | ]); 101 | }); 102 | -------------------------------------------------------------------------------- /tests/runtime/Array/Array.test.ts: -------------------------------------------------------------------------------- 1 | import Array, { ArrayΔ$ } from '@runtime/types/Array/Array'; 2 | import String from '@runtime/types/String/String'; 3 | 4 | import { isSuccessOf } from '@algebraic/types/Result/Functions'; 5 | import { isGreaterThan as isStringGt } from '@runtime/types/String/checks/isGreaterThan'; 6 | import { isGreaterThan as isArrayGt } from '@runtime/types/Array/checks/isGreaterThan'; 7 | 8 | describe ('Array Type', () => { 9 | it ('Symbol identifier exists', () => { 10 | expect (Array (String)._.type).toBe (ArrayΔ$); 11 | }); 12 | 13 | it ('When array is checked with correct child, we expected to pass', () => { 14 | const payload = ['this is a arrayof string']; 15 | const isArray = Array (String).Δ.check (payload); 16 | expect (isSuccessOf (isArray, payload)).toBeTruthy (); 17 | }); 18 | 19 | it ('When readonly array is checked with correct child, we expected to pass', () => { 20 | const payload = ['this is a arrayof string']; 21 | const isArray = Array (String).Δ.asReadOnly ().Δ.check (payload); 22 | expect (isSuccessOf (isArray, payload)).toBeTruthy (); 23 | }); 24 | 25 | it ('When array is checked with incorrect child, we expected to fail', () => { 26 | const payload = undefined; 27 | const isArray = Array (String).Δ.check (payload); 28 | expect (isSuccessOf (isArray, payload)).toBeFalsy (); 29 | }); 30 | 31 | it ('When array is checked with custom check and respect custom check & child, we expected to pass', () => { 32 | const payload = ['string 1', 'string 2', 'string 3']; 33 | const isArray = Array (String) 34 | .Δ.checkWith ([isArrayGt (2)]) 35 | .Δ.check (payload); 36 | expect (isSuccessOf (isArray, payload)).toBeTruthy (); 37 | }); 38 | 39 | it ('When array is checked with custom check and respect custom check & does not respect child, we expected to fail', () => { 40 | const payload = [true, 1, false]; 41 | const isArray = Array (String) 42 | .Δ.checkWith ([isArrayGt (2)]) 43 | .Δ.check (payload); 44 | expect (isSuccessOf (isArray, payload)).toBeFalsy (); 45 | }); 46 | 47 | it ('When array is checked with custom check and does not respect custom check but respect child, we expected to fail', () => { 48 | const payload = ['string 1', 'string 2', 'string 3']; 49 | const isArray = Array (String) 50 | .Δ.checkWith ([isArrayGt (10)]) 51 | .Δ.check (payload); 52 | expect (isSuccessOf (isArray, payload)).toBeFalsy (); 53 | }); 54 | 55 | it ('When array is checked with child custom check and respects, we expected to pass', () => { 56 | const payload = ['string greater than 100']; 57 | const isArray = Array (String.Δ.checkWith ([isStringGt (10)])).Δ.check ( 58 | payload 59 | ); 60 | expect (isSuccessOf (isArray, payload)).toBeTruthy (); 61 | }); 62 | 63 | it ('When array is checked with child custom check and does not respect its, we expected to fail', () => { 64 | const payload = ['string less than 100']; 65 | const isArray = Array (String.Δ.checkWith ([isStringGt (100)])).Δ.check ( 66 | payload 67 | ); 68 | expect (isSuccessOf (isArray, payload)).toBeFalsy (); 69 | }); 70 | 71 | it ('When array and child are checked with custom check and respect custom check of both, we expected to pass', () => { 72 | const payload = ['true', 'true', 'true']; 73 | const isArray = Array (String.Δ.checkWith ([isStringGt (3)])) 74 | .Δ.checkWith ([isArrayGt (2)]) 75 | .Δ.check (payload); 76 | expect (isSuccessOf (isArray, payload)).toBeTruthy (); 77 | }); 78 | 79 | it ('When array and child are checked with custom check and disrespect custom check of both, we expected to fail', () => { 80 | const payload = ['true', 'true']; 81 | const isArray = Array (String.Δ.checkWith ([isStringGt (10)])) 82 | .Δ.checkWith ([isArrayGt (2)]) 83 | .Δ.check (payload); 84 | expect (isSuccessOf (isArray, payload)).toBeFalsy (); 85 | }); 86 | }); 87 | -------------------------------------------------------------------------------- /tests/runtime/Boolean/Boolean.test.ts: -------------------------------------------------------------------------------- 1 | import Boolean, { BooleanΔ$ } from '@runtime/types/Boolean/Boolean'; 2 | import { isSuccessOf } from '@algebraic/types/Result/Functions'; 3 | 4 | describe ('Boolean Type', () => { 5 | it ('Symbol identifier exists', () => { 6 | expect (Boolean._.type).toBe (BooleanΔ$); 7 | }); 8 | 9 | it ('When Boolean is check, we expected to pass', () => { 10 | const payload = true; 11 | const isBoolean = Boolean.Δ.check (payload); 12 | expect (isSuccessOf (isBoolean, payload)).toBeTruthy (); 13 | }); 14 | 15 | it ('When something that is not a Boolean is checked, we expected to fail', () => { 16 | const payload = 'this is a boolean'; 17 | const isBoolean = Boolean.Δ.check (payload); 18 | expect (isSuccessOf (isBoolean, payload)).toBeFalsy (); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /tests/runtime/Intersect/Intersect.test.ts: -------------------------------------------------------------------------------- 1 | import { isSuccessOf } from '@algebraic/types/Result/Functions'; 2 | import Intersect, { IntersectΔ$ } from '@runtime/types/Intersect/Intersect'; 3 | import Record from '@runtime/types/Record/Record'; 4 | import String from '@runtime/types/String/String'; 5 | 6 | describe ('Intersect Type', () => { 7 | it ('Symbol identifier exists', () => { 8 | expect (Intersect (Record ({a: String}), Record ({b: String}))._.type).toBe (IntersectΔ$); 9 | }); 10 | 11 | it ('When Intersect is checked with null, we expected to fail', () => { 12 | const payload = undefined; 13 | const isIntersect = Intersect (Record ({a: String}), Record ({b: String})).Δ.check (payload); 14 | expect (isSuccessOf (isIntersect, payload)).toBeFalsy (); 15 | }); 16 | 17 | it ('When Intersect is checked respecting all childs, we expected to suceed', () => { 18 | const payload = { firstName: 'Mike', lastName: 'Tyson' }; 19 | const isIntersect = Intersect (Record ({firstName: String}), Record ({lastName: String})).Δ.check (payload); 20 | 21 | expect (isSuccessOf (isIntersect, payload)).toBeTruthy (); 22 | }); 23 | 24 | it ('When Intersect is checked respecting only one child, we expected to fail', () => { 25 | const payload = { firstName: 1, lastName: 'Tyson' }; 26 | const isIntersect = Intersect (Record ({firstName: String}), Record ({lastName: String})).Δ.check (payload); 27 | 28 | expect (isSuccessOf (isIntersect, payload)).toBeFalsy (); 29 | }); 30 | 31 | it ('When Intersect is checked respecting only second child, we expected to fail', () => { 32 | const payload = { firstName: 1, lastName: true }; 33 | const isIntersect = Intersect (Record ({firstName: String}), Record ({lastName: String})).Δ.check (payload); 34 | 35 | expect (isSuccessOf (isIntersect, payload)).toBeFalsy (); 36 | }); 37 | }); -------------------------------------------------------------------------------- /tests/runtime/Literal/Literal.test.ts: -------------------------------------------------------------------------------- 1 | import Literal, { LiteralΔ$ } from '@runtime/types/Literal/Literal'; 2 | import { isSuccessOf } from '@algebraic/types/Result/Functions'; 3 | 4 | describe ('Literal Type', () => { 5 | it ('Symbol identifier exists', () => { 6 | const payload = 'some lit value'; 7 | expect (Literal (payload)._.type).toBe (LiteralΔ$); 8 | }); 9 | 10 | it ('When Literal is check, we expected to pass', () => { 11 | const payload = 100; 12 | const isLiteral = Literal (payload).Δ.check (payload); 13 | expect (isSuccessOf (isLiteral, payload)).toBeTruthy (); 14 | }); 15 | 16 | it ('When something that is not a Literal is checked, we expected to fail', () => { 17 | const payload = 'this is a Literal'; 18 | const isLiteral = Literal (payload).Δ.check (true); 19 | expect (isSuccessOf (isLiteral, payload)).toBeFalsy (); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /tests/runtime/Number/Number.test.ts: -------------------------------------------------------------------------------- 1 | import Number, { NumberΔ$ } from '@runtime/types/Number/Number'; 2 | import { isGreaterThan } from '@runtime/types/Number/checks/isGreaterThan'; 3 | import { isSuccessOf } from '@algebraic/types/Result/Functions'; 4 | 5 | describe ('Number Type', () => { 6 | it ('Symbol identifier exists', () => { 7 | expect (Number._.type).toBe (NumberΔ$); 8 | }); 9 | 10 | it ('When Number is check, we expected to pass', () => { 11 | const payload = 100; 12 | const isNumber = Number.Δ.check (payload); 13 | expect (isSuccessOf (isNumber, payload)).toBeTruthy (); 14 | }); 15 | 16 | it ('When something that is not a Number is checked, we expected to fail', () => { 17 | const payload = 'this is not a number'; 18 | const isNumber = Number.Δ.check (payload); 19 | expect (isSuccessOf (isNumber, payload)).toBeFalsy (); 20 | }); 21 | 22 | it ('When number is checked with custom check, we expected to pass', () => { 23 | const payload = 10; 24 | const isNumber = Number.Δ.checkWith ([isGreaterThan (1)]).Δ.check (payload); 25 | expect (isSuccessOf (isNumber, payload)).toBeTruthy (); 26 | }); 27 | 28 | it ('When number is checked with custom check that does not respect the rules, we expected to fail', () => { 29 | const payload = 1; 30 | const isNumber = Number.Δ.checkWith ([isGreaterThan (10)]).Δ.check (payload); 31 | expect (isSuccessOf (isNumber, payload)).toBeFalsy (); 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /tests/runtime/Partial/Partial.test.ts: -------------------------------------------------------------------------------- 1 | import Partial, { PartialΔ$ } from '@runtime/types/Partial/Partial'; 2 | import String from '@runtime/types/String/String'; 3 | import Number from '@runtime/types/Number/Number'; 4 | 5 | import { isSuccessOf } from '@algebraic/types/Result/Functions'; 6 | import { isGreaterThan as isStringGt } from '@runtime/types/String/checks/isGreaterThan'; 7 | import { isGreaterThan as isNumberGt } from '@runtime/types/Number/checks/isGreaterThan'; 8 | 9 | describe ('Partial Type', () => { 10 | it ('Symbol identifier exists', () => { 11 | const Person = Partial ({ 12 | firstName: String, 13 | }); 14 | expect (Person._.type).toBe (PartialΔ$); 15 | }); 16 | 17 | it ('When Partial is checked with incorrect payload, we expected to fail', () => { 18 | const payload = undefined; 19 | const isPerson = Partial ({ 20 | firstName: String, 21 | }).Δ.check (payload); 22 | expect (isSuccessOf (isPerson, payload)).toBeFalsy (); 23 | }); 24 | 25 | it ('When Partial is checked with undefined child, we expected to pass', () => { 26 | const payload = { firstName: undefined }; 27 | const isPerson = Partial ({ 28 | firstName: String, 29 | }).Δ.check (payload); 30 | expect (isSuccessOf (isPerson, payload)).toBeTruthy (); 31 | }); 32 | 33 | it ('When Partial is checked with correct child, we expected to pass', () => { 34 | const payload = { firstName: 'Mike' }; 35 | const isPerson = Partial ({ 36 | firstName: String, 37 | }).Δ.check (payload); 38 | expect (isSuccessOf (isPerson, payload)).toBeTruthy (); 39 | }); 40 | 41 | it ('When Partial is checked with incorrect child, we expected to fail', () => { 42 | const payload = { firstName: true }; 43 | const isPerson = Partial ({ 44 | firstName: String, 45 | }).Δ.check (payload); 46 | expect (isSuccessOf (isPerson, payload)).toBeFalsy (); 47 | }); 48 | 49 | it ('When Partial is checked not respecting child custom check, we expected to fail', () => { 50 | const payload = { firstName: 'Mike' }; 51 | const isPerson = Partial ({ 52 | firstName: String.Δ.checkWith ([isStringGt (10)]), 53 | }).Δ.check (payload); 54 | expect (isSuccessOf (isPerson, payload)).toBeFalsy (); 55 | }); 56 | 57 | it ('When Partial is checked respecting child custom check, we expected to pass', () => { 58 | const payload = { firstName: 'Mike Pompeo' }; 59 | const isPerson = Partial ({ 60 | firstName: String.Δ.checkWith ([isStringGt (10)]), 61 | }).Δ.check (payload); 62 | expect (isSuccessOf (isPerson, payload)).toBeTruthy (); 63 | }); 64 | 65 | it ('When Partial is checked respecting first child custom check but not the second, we expected to fail', () => { 66 | const payload = { firstName: 'Mike Pompeo', age: 10 }; 67 | const isPerson = Partial ({ 68 | firstName: String.Δ.checkWith ([isStringGt (10)]), 69 | age: Number.Δ.checkWith ([isNumberGt (18)]), 70 | }).Δ.check (payload); 71 | expect (isSuccessOf (isPerson, payload)).toBeFalsy (); 72 | }); 73 | 74 | it ('When Partial is checked respecting first child custom check but not the second, we expected to fail', () => { 75 | const payload = { firstName: 'Mike', age: 20 }; 76 | const isPerson = Partial ({ 77 | firstName: String.Δ.checkWith ([isStringGt (10)]), 78 | age: Number.Δ.checkWith ([isNumberGt (18)]), 79 | }).Δ.check (payload); 80 | expect (isSuccessOf (isPerson, payload)).toBeFalsy (); 81 | }); 82 | 83 | it ('When Partial is checked respecting all childs with nested levels, we expected to pass', () => { 84 | const payload = { 85 | firstName: 'Mike Pompeo', 86 | age: 20, 87 | boss: { firstName: 'Jonh' }, 88 | }; 89 | const Boss = Partial ({ firstName: String }); 90 | const isPerson = Partial ({ 91 | firstName: String.Δ.checkWith ([isStringGt (10)]), 92 | age: Number.Δ.checkWith ([isNumberGt (18)]), 93 | boss: Boss, 94 | }).Δ.check (payload); 95 | expect (isSuccessOf (isPerson, payload)).toBeTruthy (); 96 | }); 97 | }); 98 | -------------------------------------------------------------------------------- /tests/runtime/Record/Record.test.ts: -------------------------------------------------------------------------------- 1 | import Record, { RecordΔ$ } from '@runtime/types/Record/Record'; 2 | import String from '@runtime/types/String/String'; 3 | import Array from '@runtime/types/Array/Array'; 4 | import Number from '@runtime/types/Number/Number'; 5 | 6 | import { isSuccessOf, isFailure } from '@algebraic/types/Result/Functions'; 7 | import { isGreaterThan as isStringGt } from '@runtime/types/String/checks/isGreaterThan'; 8 | import { isGreaterThan as isNumberGt } from '@runtime/types/Number/checks/isGreaterThan'; 9 | 10 | describe ('Record Type', () => { 11 | it ('Symbol identifier exists', () => { 12 | const Person = Record ({ 13 | firstName: String, 14 | }); 15 | expect (Person._.type).toBe (RecordΔ$); 16 | }); 17 | 18 | it ('When Record is checked with incorrect payload, we expected to fail', () => { 19 | const payload = undefined; 20 | const isPerson = Record ({ 21 | firstName: String, 22 | }).Δ.check (payload); 23 | expect (isSuccessOf (isPerson, payload)).toBeFalsy (); 24 | }); 25 | 26 | it ('When Record is checked with correct child, we expected to pass', () => { 27 | const payload = { firstName: 'Mike' }; 28 | const isPerson = Record ({ 29 | firstName: String, 30 | }).Δ.check (payload); 31 | expect (isSuccessOf (isPerson, payload)).toBeTruthy (); 32 | }); 33 | 34 | it ('When Record is checked with incorrect child, we expected to fail', () => { 35 | const payload = { firstName: true }; 36 | const isPerson = Record ({ 37 | firstName: String, 38 | }).Δ.check (payload); 39 | expect (isSuccessOf (isPerson, payload)).toBeFalsy (); 40 | }); 41 | 42 | it ('When Record is checked not respecting child custom check, we expected to fail', () => { 43 | const payload = { firstName: 'Mike' }; 44 | const isPerson = Record ({ 45 | firstName: String.Δ.checkWith ([isStringGt (10)]), 46 | }).Δ.check (payload); 47 | expect (isSuccessOf (isPerson, payload)).toBeFalsy (); 48 | }); 49 | 50 | it ('When Record is checked respecting child custom check, we expected to pass', () => { 51 | const payload = { firstName: 'Mike Pompeo' }; 52 | const isPerson = Record ({ 53 | firstName: String.Δ.checkWith ([isStringGt (10)]), 54 | }).Δ.check (payload); 55 | expect (isSuccessOf (isPerson, payload)).toBeTruthy (); 56 | }); 57 | 58 | it ('When Record is checked respecting first child custom check but not the second, we expected to fail', () => { 59 | const payload = { firstName: 'Mike Pompeo', age: 10 }; 60 | const isPerson = Record ({ 61 | firstName: String.Δ.checkWith ([isStringGt (10)]), 62 | age: Number.Δ.checkWith ([isNumberGt (18)]), 63 | }).Δ.check (payload); 64 | expect (isSuccessOf (isPerson, payload)).toBeFalsy (); 65 | }); 66 | 67 | it ('When Record is checked respecting first child custom check but not the second, we expected to fail', () => { 68 | const payload = { firstName: 'Mike', age: 20 }; 69 | const isPerson = Record ({ 70 | firstName: String.Δ.checkWith ([isStringGt (10)]), 71 | age: Number.Δ.checkWith ([isNumberGt (18)]), 72 | }).Δ.check (payload); 73 | expect (isSuccessOf (isPerson, payload)).toBeFalsy (); 74 | }); 75 | 76 | it ('When Record is checked respecting all first leval child custom check but not the inner record, we expected to fail', () => { 77 | const payload = { firstName: 'Mike Pompeo', age: 20 }; 78 | const Boss = Record ({ firstName: String }); 79 | const isPerson = Record ({ 80 | firstName: String.Δ.checkWith ([isStringGt (10)]), 81 | age: Number.Δ.checkWith ([isNumberGt (18)]), 82 | boss: Boss, 83 | }).Δ.check (payload); 84 | expect (isSuccessOf (isPerson, payload)).toBeFalsy (); 85 | }); 86 | 87 | it ('When Record is checked respecting all childs with nested levels, we expected to pass', () => { 88 | const payload = { 89 | firstName: 'Mike Pompeo', 90 | age: 20, 91 | boss: { firstName: 'Jonh' }, 92 | }; 93 | const Boss = Record ({ firstName: String }); 94 | const isPerson = Record ({ 95 | firstName: String.Δ.checkWith ([isStringGt (10)]), 96 | age: Number.Δ.checkWith ([isNumberGt (18)]), 97 | boss: Boss, 98 | }).Δ.check (payload); 99 | expect (isSuccessOf (isPerson, payload)).toBeTruthy (); 100 | }); 101 | 102 | it ('When Record is checked with incorrect payload, we expected to have a valid path', () => { 103 | const payload = undefined; 104 | const isPerson = Record ({ 105 | info: Record ({ 106 | name: String, 107 | }), 108 | }).Δ.check (payload); 109 | expect (isSuccessOf (isPerson, payload)).toBeFalsy (); 110 | expect (isFailure (isPerson) ? isPerson.λ.value[0].path : undefined).toBe (''); 111 | }); 112 | 113 | it ('When Record is checked with incorrect property, we expected to have a valid path', () => { 114 | const payload = { info: true }; 115 | const isPerson = Record ({ 116 | info: Record ({ 117 | name: String, 118 | }), 119 | }).Δ.check (payload); 120 | expect (isSuccessOf (isPerson, payload)).toBeFalsy (); 121 | expect (isFailure (isPerson) ? isPerson.λ.value[0].path : undefined).toBe ( 122 | 'info' 123 | ); 124 | }); 125 | 126 | it ('When Record is checked with incorrect deep property, we expected to have a valid path', () => { 127 | const payload = { info: { name: true } }; 128 | const isPerson = Record ({ 129 | info: Record ({ 130 | name: String, 131 | }), 132 | }).Δ.check (payload); 133 | expect (isSuccessOf (isPerson, payload)).toBeFalsy (); 134 | expect (isFailure (isPerson) ? isPerson.λ.value[0].path : undefined).toBe ( 135 | 'info.name' 136 | ); 137 | }); 138 | 139 | it ('When Record is checked with incorrect deep property as array, we expected to have a valid path', () => { 140 | const payload = { info: { name: true } }; 141 | const isPerson = Record ({ 142 | info: Record ({ 143 | name: Array (String), 144 | }), 145 | }).Δ.check (payload); 146 | expect (isSuccessOf (isPerson, payload)).toBeFalsy (); 147 | expect (isFailure (isPerson) ? isPerson.λ.value[0].path : undefined).toBe ( 148 | 'info.name' 149 | ); 150 | }); 151 | 152 | it ('When Record is checked with incorrect specific array indiceon a deep property, we expected to have a valid path', () => { 153 | const payload = { info: { name: ['Mike', 'Julia', true] } }; 154 | const isPerson = Record ({ 155 | info: Record ({ 156 | name: Array (String), 157 | }), 158 | }).Δ.check (payload); 159 | expect (isSuccessOf (isPerson, payload)).toBeFalsy (); 160 | expect (isFailure (isPerson) ? isPerson.λ.value[0].path : undefined).toBe ( 161 | 'info.name[2]' 162 | ); 163 | }); 164 | }); 165 | -------------------------------------------------------------------------------- /tests/runtime/String/String.test.ts: -------------------------------------------------------------------------------- 1 | import String, { StringΔ$ } from '@runtime/types/String/String'; 2 | import { isGreaterThan } from '@runtime/types/String/checks/isGreaterThan'; 3 | import { isSuccessOf } from '@algebraic/types/Result/Functions'; 4 | 5 | describe ('String Type', () => { 6 | it ('Symbol identifier exists', () => { 7 | expect (String._.type).toBe (StringΔ$); 8 | }); 9 | 10 | it ('When string is check, we expected to pass', () => { 11 | const payload = 'this is a string'; 12 | const isString = String.Δ.check (payload); 13 | expect (isSuccessOf (isString, payload)).toBeTruthy (); 14 | }); 15 | 16 | it ('When something that is not a string is checked, we expected to fail', () => { 17 | const payload = true; 18 | const isString = String.Δ.check (payload); 19 | expect (isSuccessOf (isString, payload)).toBeFalsy (); 20 | }); 21 | 22 | it ('When string is checked with custom check, we expected to pass', () => { 23 | const payload = 'this is a string'; 24 | const isString = String.Δ.checkWith ([isGreaterThan (1)]).Δ.check (payload); 25 | expect (isSuccessOf (isString, payload)).toBeTruthy (); 26 | }); 27 | 28 | it ('When string is checked with custom check that does not respect the rules, we expected to fail', () => { 29 | const payload = 'this is a string'; 30 | const isString = String.Δ.checkWith ([isGreaterThan (100)]).Δ.check (payload); 31 | expect (isSuccessOf (isString, payload)).toBeFalsy (); 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /tests/runtime/Tuple/Tuple.test.ts: -------------------------------------------------------------------------------- 1 | import Tuple, { TupleΔ$ } from '@runtime/types/Tuple/Tuple'; 2 | import Number from '@runtime/types/Number/Number'; 3 | import String from '@runtime/types/String/String'; 4 | import { isSuccessOf } from '@algebraic/types/Result/Functions'; 5 | import { isGreaterThan as isStringGt } from '@runtime/types/String/checks/isGreaterThan'; 6 | import { isGreaterThan as isNumberGt } from '@runtime/types/Number/checks/isGreaterThan'; 7 | 8 | describe ('Tuple Type', () => { 9 | it ('Symbol identifier exists', () => { 10 | expect (Tuple (String, Number)._.type).toBe (TupleΔ$); 11 | }); 12 | 13 | it ('When Tuple is checked not respecting any child, we expected to fail', () => { 14 | const payload = undefined; 15 | const isTuple = Tuple (String, Number).Δ.check (payload); 16 | expect (isSuccessOf (isTuple, payload)).toBeFalsy (); 17 | }); 18 | 19 | it ('When Tuple is checked respecting first child but not the second, we expected to fail', () => { 20 | const payload = ['this is a string', null]; 21 | const isTuple = Tuple (String, Number).Δ.check (payload); 22 | expect (isSuccessOf (isTuple, payload)).toBeFalsy (); 23 | }); 24 | 25 | it ('When Tuple is checked respecting second child but not the first, we expected to fail', () => { 26 | const payload = [true, 1]; 27 | const isTuple = Tuple (String, Number).Δ.check (payload); 28 | expect (isSuccessOf (isTuple, payload)).toBeFalsy (); 29 | }); 30 | 31 | it ('When Tuple is checked respecting all childs, we expected to pass', () => { 32 | const payload = ['this is string', 1]; 33 | const isTuple = Tuple (String, Number).Δ.check (payload); 34 | expect (isSuccessOf (isTuple, payload)).toBeTruthy (); 35 | }); 36 | 37 | it ('When Tuple is checked respecting first child with custom check but not the second, we expected to fail', () => { 38 | const payload = ['this is a string', 5]; 39 | const isTuple = Tuple ( 40 | String.Δ.checkWith ([isStringGt (1)]), 41 | Number.Δ.checkWith ([isNumberGt (10)]) 42 | ).Δ.check (payload); 43 | expect (isSuccessOf (isTuple, payload)).toBeFalsy (); 44 | }); 45 | 46 | it ('When Tuple is checked respecting second child with custom check but not the first, we expected to fail', () => { 47 | const payload = ['this is a string', 5]; 48 | const isTuple = Tuple ( 49 | String.Δ.checkWith ([isStringGt (100)]), 50 | Number.Δ.checkWith ([isNumberGt (1)]) 51 | ).Δ.check (payload); 52 | expect (isSuccessOf (isTuple, payload)).toBeFalsy (); 53 | }); 54 | 55 | it ('When Tuple is checked respecting all childs with custom check, we expected to pass', () => { 56 | const payload = ['this is a string', 11]; 57 | const isTuple = Tuple ( 58 | String.Δ.checkWith ([isStringGt (10)]), 59 | Number.Δ.checkWith ([isNumberGt (10)]) 60 | ).Δ.check (payload); 61 | expect (isSuccessOf (isTuple, payload)).toBeTruthy (); 62 | }); 63 | }); 64 | -------------------------------------------------------------------------------- /tests/runtime/Union/Union.test.ts: -------------------------------------------------------------------------------- 1 | import Union, { UnionΔ$ } from '@runtime/types/Union/Union'; 2 | import Number from '@runtime/types/Number/Number'; 3 | import String from '@runtime/types/String/String'; 4 | import { isSuccessOf } from '@algebraic/types/Result/Functions'; 5 | import { isGreaterThan as isStringGt } from '@runtime/types/String/checks/isGreaterThan'; 6 | import { isGreaterThan as isNumberGt } from '@runtime/types/Number/checks/isGreaterThan'; 7 | 8 | describe ('Union Type', () => { 9 | it ('Symbol identifier exists', () => { 10 | expect (Union (String, Number)._.type).toBe (UnionΔ$); 11 | }); 12 | 13 | it ('When Union is checked respecting first child, we expected to pass', () => { 14 | const payload = 'this is a string'; 15 | const isUnion = Union (String, Number).Δ.check (payload); 16 | expect (isSuccessOf (isUnion, payload)).toBeTruthy (); 17 | }); 18 | 19 | it ('When Union is checked respecting second child, we expected to pass', () => { 20 | const payload = 1; 21 | const isUnion = Union (String, Number).Δ.check (payload); 22 | expect (isSuccessOf (isUnion, payload)).toBeTruthy (); 23 | }); 24 | 25 | it ('When Union is checked not respecting any child, we expected to fail', () => { 26 | const payload = undefined; 27 | const isUnion = Union (String, Number).Δ.check (payload); 28 | expect (isSuccessOf (isUnion, payload)).toBeFalsy (); 29 | }); 30 | 31 | it ('When Union is checked respecting first child with custom check, we expected to pass', () => { 32 | const payload = 'this is a string'; 33 | const isUnion = Union (String.Δ.checkWith ([isStringGt (1)]), Number).Δ.check ( 34 | payload 35 | ); 36 | expect (isSuccessOf (isUnion, payload)).toBeTruthy (); 37 | }); 38 | 39 | it ('When Union is checked respecting second child with custom check, we expected to pass', () => { 40 | const payload = 10; 41 | const isUnion = Union (String, Number.Δ.checkWith ([isNumberGt (1)])).Δ.check ( 42 | payload 43 | ); 44 | expect (isSuccessOf (isUnion, payload)).toBeTruthy (); 45 | }); 46 | 47 | it ('When Union is checked disrespecting first child with custom check, we expected to fail', () => { 48 | const payload = 'this is a string'; 49 | const isUnion = Union (String.Δ.checkWith ([isStringGt (100)]), Number).Δ.check ( 50 | payload 51 | ); 52 | expect (isSuccessOf (isUnion, payload)).toBeFalsy (); 53 | }); 54 | 55 | it ('When Union is checked disrespecting second child with custom check, we expected to fail', () => { 56 | const payload = 10; 57 | const isUnion = Union (String, Number.Δ.checkWith ([isNumberGt (100)])).Δ.check ( 58 | payload 59 | ); 60 | expect (isSuccessOf (isUnion, payload)).toBeFalsy (); 61 | }); 62 | }); 63 | -------------------------------------------------------------------------------- /tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "noImplicitThis": false, 4 | "lib": ["ESNext", "DOM"], 5 | "incremental": true, 6 | "target": "es5" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */, 7 | "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */, 8 | "declaration": true /* Generates corresponding '.d.ts' file. */, 9 | "declarationMap": true /* Generates a sourcemap for each corresponding '.d.ts' file. */, 10 | "outDir": "cjs/" /* Redirect output structure to the directory. */, 11 | "inlineSourceMap": true, 12 | "removeComments": true /* Do not emit comments to output. */, 13 | "strict": true /* Enable all strict type-checking options. */, 14 | "moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */, 15 | "allowSyntheticDefaultImports": true /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */, 16 | "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, 17 | "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */, 18 | "baseUrl": "./", 19 | "paths": { 20 | "@algebraic/*": ["src/algebraic/*"], 21 | "@runtime/*": ["src/runtime/*"], 22 | "@common/*": ["src/common/*"], 23 | "@hkt": ["src/hkt/index.ts"] 24 | } 25 | }, 26 | "include": ["src/**/*.ts"], 27 | "exclude": ["node_modules/"] 28 | } 29 | -------------------------------------------------------------------------------- /tsconfig.esm.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.build.json", 3 | "compilerOptions": { 4 | "noEmit": false, 5 | "outDir": "esm/", 6 | "target": "es5" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */, 7 | "module": "es6" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tsconfig.jest.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": ["tests/**/*.ts"], 4 | } 5 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.build.json", 3 | "include": ["src/**/*.ts", "tests/**/*.ts"], 4 | "exclude": ["node_modules/"] 5 | } 6 | --------------------------------------------------------------------------------