├── .editorconfig ├── .gitignore ├── .npmignore ├── LICENSE ├── README.md ├── errors.log ├── package-lock.json ├── package.json ├── src ├── array │ ├── AppendNumObj.ts │ ├── ArrPrototypeMethods.ts │ ├── ArrayProp.ts │ ├── ConcatNumObjs.ts │ ├── DifferenceTuples.ts │ ├── FixedSizeArray.ts │ ├── IncIndexNumbObj.ts │ ├── IsArrayType.ts │ ├── IsTuple.ts │ ├── Length.ts │ ├── ListFrom.ts │ ├── ListTo.ts │ ├── Reverse.ts │ ├── Tail.ts │ ├── TupleFrom.ts │ ├── TupleHasIndex.ts │ ├── TupleLastElem.ts │ ├── TupleLastIndex.ts │ ├── TupleProp.ts │ ├── TupleTail.ts │ ├── TupleTo.ts │ ├── Vector.ts │ └── index.ts ├── boolean │ ├── And.ts │ ├── DefinitelyNo.ts │ ├── DefinitelyYes.ts │ ├── Determinate.ts │ ├── Falsy.ts │ ├── Indeterminate.ts │ ├── IsFalsy.ts │ ├── IsTruthy.ts │ ├── Not.ts │ ├── Or.ts │ └── index.ts ├── cast │ ├── BoolToString.ts │ ├── ListToNumObj.ts │ ├── NumObjToList.ts │ ├── NumberToNumber.ts │ ├── NumberToString.ts │ ├── StringToNumber.ts │ ├── ToBool.ts │ ├── TupleIndicesToUnion.ts │ ├── TupleToList.ts │ ├── TupleToObject.ts │ ├── TupleToUnion.ts │ └── index.ts ├── comp │ ├── Gt.ts │ ├── Gte.ts │ ├── Lt.ts │ ├── Lte.ts │ ├── Max.ts │ ├── Min.ts │ ├── NumbersEqual.ts │ ├── StringsEqual.ts │ └── index.ts ├── function │ ├── Argument.ts │ ├── Arguments.ts │ ├── Bind.ts │ ├── Fn.ts │ ├── IsValidArg.ts │ ├── NumberOfArgs.ts │ ├── Unbind.ts │ └── index.ts ├── index.ts ├── number │ ├── Add.ts │ ├── Dec.ts │ ├── DivFloor.ts │ ├── Inc.ts │ ├── Modulo.ts │ ├── Mult.ts │ ├── Pow.ts │ ├── Subtract.ts │ └── index.ts ├── object │ ├── DeconstructUnionHelper.ts │ ├── DeepAssert.ts │ ├── DeepMutable.ts │ ├── DeepPartial.ts │ ├── DeepReadonly.ts │ ├── DeepRequired.ts │ ├── DeepWiden.ts │ ├── FunctionPropNames.ts │ ├── FunctionProps.ts │ ├── HasKey.ts │ ├── IntersectValueOf.ts │ ├── IntersectionObjectKeys.ts │ ├── IntersectionObjects.ts │ ├── Jsonified.ts │ ├── Keyed.ts │ ├── KeyedSafe.ts │ ├── LiteralPropNames.ts │ ├── LiteralProps.ts │ ├── MatchingPropNames.ts │ ├── MatchingProps.ts │ ├── Mutable.ts │ ├── NonFunctionPropNames.ts │ ├── NonFunctionProps.ts │ ├── NonMatchingPropNames.ts │ ├── NonMatchingProps.ts │ ├── ObjectHasElem.ts │ ├── ObjectHasKey.ts │ ├── ObjectHasKeySafe.ts │ ├── ObjectHasNumberIndex.ts │ ├── ObjectHasStringIndex.ts │ ├── ObjectNumberKeys.ts │ ├── ObjectProp.ts │ ├── ObjectValsToUnion.ts │ ├── Omit.ts │ ├── OptionalPropNames.ts │ ├── OptionalProps.ts │ ├── Overwrite.ts │ ├── Prototype.ts │ ├── PrototypeHas.ts │ ├── PrototypeMethods.ts │ ├── RequiredPropNames.ts │ ├── RequiredProps.ts │ ├── Simplify.ts │ ├── Spread.ts │ ├── SpreadProps.ts │ ├── StripIndex.ts │ ├── Swap.ts │ └── index.ts ├── ramda │ ├── ApplyFns.ts │ ├── Compose.ts │ ├── Curried.ts │ ├── FromPairsFn.ts │ ├── MapFn.ts │ ├── MergeAllFn.ts │ ├── PathFn.ts │ ├── PathOrFn.ts │ ├── Pipe.ts │ ├── ZipObjectFn.ts │ ├── bind.ts │ ├── curry.ts │ └── index.ts ├── tuple │ ├── AppendList.ts │ ├── ConcatLists.ts │ ├── DecIndex.ts │ ├── DifferenceLists.ts │ ├── IncIndex.ts │ ├── LengthList.ts │ ├── ListTail.ts │ ├── Prepend.ts │ ├── ReverseList.ts │ ├── Unshift.ts │ ├── ZeroIndex.ts │ └── index.ts ├── type │ ├── Awaited.ts │ ├── Const.ts │ ├── DiscriminateUnion.ts │ ├── Flatten.ts │ ├── Id.ts │ ├── InstanceOf.ts │ ├── Matches.ts │ ├── PrototypeOf.ts │ ├── TypesEqual.ts │ ├── Widen.ts │ ├── Xor.ts │ └── index.ts ├── union │ ├── IsUnion.ts │ ├── UnionContained.ts │ ├── UnionEmpty.ts │ ├── UnionHasKey.ts │ ├── UnionToIntersection.ts │ ├── UnionToObject.ts │ ├── UnionsOverlap.ts │ └── index.ts └── util │ ├── Bool.ts │ ├── If.ts │ ├── Intersection.ts │ ├── List.ts │ ├── NoInfer.ts │ ├── NumObj.ts │ ├── Obj.ts │ ├── The.ts │ ├── Unknown.ts │ ├── index.ts │ └── the.ts ├── tests ├── array.test.ts ├── boolean.test.ts ├── cast.test.ts ├── comp.test.ts ├── crap.ts ├── fixtures.ts ├── function.test.ts ├── index.ts ├── number.test.ts ├── object.test.ts ├── ramda.test.ts ├── repros.test.ts ├── stdlib.test.ts ├── syntax.test.ts ├── tuple.test.ts ├── type.test.ts ├── union.test.ts └── util.test.ts ├── tsc.log ├── tsconfig.build.json └── tsconfig.json /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | end_of_line = lf 9 | insert_final_newline = true 10 | 11 | # Matches multiple files with brace expansion notation 12 | # Set default charset 13 | [*.ts] 14 | charset = utf-8 15 | indent_style = space 16 | indent_size = 2 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | /node_modules 3 | /lib 4 | /out 5 | /docs 6 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | /node_modules 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Thomas Crockett 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Typical 2 | 3 | Typical is a playground of type-level operations for TypeScript. 4 | It is mostly experimental and not ready to use yet. 5 | For a lib usable today, try one of the [other](https://github.com/tycho01/typical/#similar-projects) type libraries. 6 | 7 | 14 | 15 | ### [Docs](http://tycho01.github.io/typical/index.html) 16 | 17 | ### Background? 18 | 19 | Typical has had a long-term focus, exploring what we can do with types. 20 | The end goal is to enable type-safe functional programming with e.g. [ramda](http://ramdajs.com/docs/) and [partial lenses](https://github.com/calmm-js/partial.lenses/). Existing [typings](https://github.com/types/npm-ramda/) provide some level of type safety, but not enough. 21 | Front-end engineering is a [royal](https://github.com/reactjs/redux/blob/master/examples/todos/src/actions/index.js) [pain](https://github.com/ngrx/platform/blob/master/example-app/app/books/actions/book.ts), and functional libraries would [save us](https://github.com/calmm-js/kral-todomvc/blob/master/src/todos-meta.js#L17-L24) given proper type inference. 22 | 23 | ### Contributing 24 | 25 | - [issues](https://github.com/tycho01/typical/issues/) 26 | - [`tsc` output](https://github.com/tycho01/typical/blob/master/tsc.log) 27 | - [test output](https://github.com/tycho01/typical/blob/master/errors.log) 28 | 29 | These can be rerun with `npm test`. 30 | 31 | ### Similar projects 32 | 33 | - [`ts-toolbelt`](https://github.com/pirix-gh/ts-toolbelt), a more mature type lib 34 | - [`type-zoo`](https://github.com/pelotom/type-zoo), a modest type lib usable today 35 | - [`typelevel-ts`](https://github.com/gcanti/typelevel-ts), a type lib by [@gcanti](https://github.com/gcanti), author of several FP libs in TS 36 | - [`typepark`](https://github.com/kgtkr/typepark), a new type collection offering tuple manipulation and `Pipe` 37 | - [`type-plus`](https://github.com/unional/type-plus), additional types and types adjusted utilities for TS 38 | -------------------------------------------------------------------------------- /errors.log: -------------------------------------------------------------------------------- 1 | 2 | 3 | array 4 | Vector 5 | ✓ the<{ 0: number, 1: number, 2: number, length: 3 }, Vector> 6 | ✓ the, { 0: number, 1: number, 2: number, length: 3 } | { 0: string, 1: string, 2: string, length: 3 }> 7 | ✓ the<{ 0: number | string, 1: number | string, 2: number | string, length: 3 }, Vector> 8 | ✓ the<{ 0: number, 1: number, length: 2 } | { 0: number, 1: number, 2: number, length: 3 }, Vector> 9 | ArrayProp 10 | ✓ the<0, ArrayProp>> 11 | ✓ the<0 | 1, ArrayProp>> 12 | ✓ the<0 | 1, ArrayProp | Array<1>>> 13 | TupleProp 14 | ✓ the<0, TupleProp<[0], 0>> 15 | ✓ the<0, TupleProp<[0], 1>> 16 | ✓ the> 17 | TupleHasIndex 18 | ✓ the<'1', TupleHasIndex> 19 | ✓ the<'0', TupleHasIndex> 20 | ✓ the<'0'|'1', TupleHasIndex> 21 | ✓ the<'0'|'1', TupleHasIndex> 22 | × the<'1', TupleHasIndex<{a:1}, 'a'>> 23 | × the<'0', TupleHasIndex<{a:1}, 'b'>> 24 | × the<'1', TupleHasIndex<{ 1: "hi" }, 1>> 25 | × the<'0', TupleHasIndex<{ 1: "hi" }, -1>> 26 | IsArrayType 27 | ✓ the<'1', IsArrayType> 28 | ✓ the<'1', IsArrayType> 29 | ✓ the<'0', IsArrayType<{ length: 2 }>> 30 | AppendNumObj 31 | ✓ the<{ 0: 'a', 1: 'b', 2: 'c' }, AppendNumObj<{ 0: 'a', 1: 'b' }, 'c'>> 32 | ConcatNumObjs 33 | ✓ the<{ 0: 'a', 1: 'b', 2: 'c', 3: 'd' }, ConcatNumObjs<{ 0: 'a', 1: 'b' }, { 0: 'c', 1: 'd' }>> 34 | Length 35 | ✓ the<3, Length>> 36 | ✓ the<3, Length> 37 | ✓ the<0, Length> 38 | ✓ the<2, Length<{ 0: 'a', 1: 'b' }>> 39 | ✓ the<0|3, Length> 40 | IncIndexNumbObj 41 | ✓ the<{ 2: 'a', 3: 'b', length: 2 }, IncIndexNumbObj<{ 0: 'a', 1: 'b' }, 2>> 42 | ListFrom 43 | ✓ the<{ 0: 'c', 1: 'd', length: 2 }, ListFrom<{ 0: 'a', 1: 'b', 2: 'c', 3: 'd', length: 4 }, 2>> 44 | ListTo 45 | ✓ the<{ 0: 'a', 1: 'b', length: 2 }, ListTo<{ 0: 'a', 1: 'b', 2: 'c', 3: 'd', length: 4 }, 2>> 46 | Reverse 47 | ✓ the<{ 0: 'b', 1: 'a', length: 2 }, Reverse<['a', 'b']>> 48 | TupleLastElem 49 | ✓ the<'c', TupleLastElem> 50 | TupleLastIndex 51 | ✓ the<2, TupleLastIndex> 52 | ✓ the<-1, TupleLastIndex> 53 | IsTuple 54 | ✓ the<'1', IsTuple<[0]>> 55 | ✓ the<'0', IsTuple> 56 | 57 | boolean 58 | Not 59 | ✓ the<'1', Not<'0'>> 60 | ✓ the<'0', Not<'1'>> 61 | - the> 62 | - the<'0', Not<'true'>> 63 | - the<'1', Not<'false'>> 64 | - the> 65 | ✓ the> 66 | - the<'0', Not> 67 | - the<'1', Not> 68 | And 69 | ✓ the<'1', And<'1', '1'>> 70 | ✓ the<'0', And<'0', '1'>> 71 | Or 72 | ✓ the<'1', Or<'1', '0'>> 73 | ✓ the<'0', Or<'0', '0'>> 74 | UnionHasKey 75 | ✓ the<'1', UnionHasKey> 76 | ✓ the<'1', UnionHasKey> 77 | ✓ the<'1', UnionHasKey | UnionHasKey> 78 | ✓ the<'1', And, UnionHasKey>> 79 | Indeterminate 80 | ✓ the<'1', Indeterminate> 81 | ✓ the<'0', Indeterminate<'0'>> 82 | ✓ the<'0', Indeterminate<'1'>> 83 | Determinate 84 | ✓ the<'0', Determinate> 85 | ✓ the<'1', Determinate<'0'>> 86 | ✓ the<'1', Determinate<'1'>> 87 | DefinitelyYes 88 | ✓ the<'0', DefinitelyYes> 89 | ✓ the<'0', DefinitelyYes<'0'>> 90 | ✓ the<'1', DefinitelyYes<'1'>> 91 | DefinitelyNo 92 | ✓ the<'0', DefinitelyNo> 93 | ✓ the<'1', DefinitelyNo<'0'>> 94 | ✓ the<'0', DefinitelyNo<'1'>> 95 | IsTruthy 96 | ✓ the<'1', IsTruthy> 97 | ✓ the<'0', IsTruthy> 98 | ✓ the<'1', IsTruthy<123>> 99 | ✓ the<'0', IsTruthy<0>> 100 | ✓ the, Bool> 101 | IsFalsy 102 | ✓ the<'0', IsFalsy> 103 | ✓ the<'1', IsFalsy> 104 | ✓ the<'0', IsFalsy<123>> 105 | ✓ the<'1', IsFalsy<0>> 106 | ✓ the, Bool> 107 | 108 | cast 109 | NumberToString 110 | ✓ the<'3', NumberToString[3]> 111 | ✓ the<'3', NumberToString['3']> 112 | × the<'3', NumberToString<3>> 113 | ✓ the 114 | StringToNumber 115 | ✓ the<3, StringToNumber['3']> 116 | ✓ the<3, StringToNumber[3]> 117 | ✓ the 118 | TupleToUnion 119 | ✓ the<"a" | "b" | "c", TupleToUnion> 120 | TupleIndicesToUnion 121 | ✓ the<0 | 1 | 2, TupleIndicesToUnion> 122 | TupleToObject 123 | ✓ the<{ 0: "a"; 1: "b"; 2: "c"; }, TupleToObject> 124 | TupleToList 125 | ✓ the<{ 0: "a"; 1: "b"; 2: "c"; length: 3; }, TupleToList> 126 | NumObjToList 127 | ✓ the<{ 0: 'a', 1: 'b', length: 2 }, NumObjToList<{ 0: 'a', 1: 'b' }>> 128 | ✓ the<{ 0: 'a', 1: 'b', 2: 'c', length: 3 }, NumObjToList>> 129 | ListToNumObj 130 | ✓ the<{ 0: 'a', 1: 'b' }, ListToNumObj<{ 0: 'a', 1: 'b', length: 2 }>> 131 | BoolToString 132 | ✓ the<'1', BoolToString> 133 | 134 | comp 135 | StringsEqual 136 | ✓ the<'1', StringsEqual<'a', 'a'>> 137 | ✓ the<'0', StringsEqual<'a', 'b'>> 138 | NumbersEqual 139 | ✓ the<'1', NumbersEqual<123, 123>> 140 | ✓ the<'0', NumbersEqual<123, 456>> 141 | × the<'1', NumbersEqual<123, '123'>> 142 | × the<'1', NumbersEqual<'123', 123>> 143 | ✓ the<'0', NumbersEqual<0, 5>> 144 | ✓ the<'0', NumbersEqual<5, 0>> 145 | Gt 146 | ✓ the<'1', Gt<3, 2>> 147 | ✓ the<'0', Gt<2, 3>> 148 | ✓ the<'0', Gt<3, 3>> 149 | Lt 150 | ✓ the<'0', Lt<3, 2>> 151 | ✓ the<'1', Lt<2, 3>> 152 | ✓ the<'0', Lt<3, 3>> 153 | Gte 154 | ✓ the<'1', Gte<3, 2>> 155 | ✓ the<'0', Gte<2, 3>> 156 | ✓ the<'1', Gte<3, 3>> 157 | Lte 158 | ✓ the<'0', Lte<3, 2>> 159 | ✓ the<'1', Lte<2, 3>> 160 | ✓ the<'1', Lte<3, 3>> 161 | Max 162 | ✓ the<6, Max<3, 6>> 163 | ✓ the<5, Max<5, 2>> 164 | Min 165 | ✓ the<3, Min<3, 6>> 166 | ✓ the<2, Min<5, 2>> 167 | 168 | function 169 | Fn 170 | ✓ the<(v: number) => string, Fn<[number], string>> 171 | Arguments 172 | ✓ the<[boolean, string], Arguments<((a: boolean, s: S) => number)>> 173 | Argument 174 | ✓ the<1, Argument<0, (a: 1, b: × => 8>> 175 | ✓ the<2, Argument<1, (a: 1, ...args: 2[]) => 8>> 176 | ✓ the<2, Argument<1, (a: 1, b: 2, ...args: 3[]) => 8>> 177 | 178 | number 179 | Inc 180 | ✓ the<2, Inc[1]> 181 | Dec 182 | ✓ the<1, Dec[2]> 183 | Add 184 | ✓ the<5, Add<3, 2>> 185 | Subtract 186 | ✓ the<1, Subtract<3, 2>> 187 | Mult 188 | ✓ the<6, Mult<3, 2>> 189 | Pow 190 | ✓ the<9, Pow<3, 2>> 191 | ✓ the<8, Pow<2, 3>> 192 | DivFloor 193 | ✓ the<2, DivFloor<5, 2>> 194 | Modulo 195 | ✓ the<1, Modulo<5, 2>> 196 | 197 | object 198 | Keyed 199 | ✓ the<{a:'a',b:'b'}, Keyed<{a:1,b:2}>> 200 | KeyedSafe 201 | ✓ the<{a:'a',b:'b'} & Obj, KeyedSafe<{a:1} & {b:2}>> 202 | ObjectHasKey 203 | ✓ the<'1', ObjectHasKey<{a:1}, 'a'>> 204 | ✓ the<'0', ObjectHasKey<{a:1}, 'b'>> 205 | ✓ the<'0'|'1', ObjectHasKey<{a?:1}, 'a'>> 206 | × the<'1', ObjectHasKey> 207 | × the<'0', ObjectHasKey> 208 | ✓ the<'0', ObjectHasKey<{ a: 1 }, "toString">> 209 | HasKey 210 | ✓ the<'0', HasKey> 211 | ✓ the<'1', HasKey> 212 | ✓ the<'0', HasKey> 213 | ✓ the<'1', HasKey<{ a: 1 }, 'a'>> 214 | ✓ the<'0', HasKey<{ a: 1 }, 'b'>> 215 | ObjectHasKeySafe 216 | ✓ the<'1', ObjectHasKeySafe<{ a: 1 }, 'a'>> 217 | ✓ the<'0', ObjectHasKeySafe<{ a: 1 }, 'b'>> 218 | ✓ the<'1', ObjectHasKeySafe<{ a: 1 }, 'a' | 'b'>> 219 | ✓ the<'1', ObjectHasKeySafe<{ a: 1, toString(): string }, 'a'>> 220 | ✓ the<'0', ObjectHasKeySafe<{ a: 1, toString(): string }, 'b'>> 221 | ✓ the<'1', ObjectHasKeySafe<{ a: 1, toString(): string }, 'a' | 'b'>> 222 | ✓ the<'0', ObjectHasKeySafe<{ a: 1 }, 'toString'>> 223 | ✓ the<'1', ObjectHasKeySafe<{ a: 1 }, 'toString' | 'a'>> 224 | ✓ the<'0', ObjectHasKeySafe<{ a: 1 }, 'toString' | 'b'>> 225 | ✓ the<'1', ObjectHasKeySafe<{ a: 1 }, 'toString' | 'a' | 'b'>> 226 | ✓ the<'1', ObjectHasKeySafe<{ a: 1, toString(): string }, 'toString'>> 227 | ✓ the<'1', ObjectHasKeySafe<{ a: 1, toString(): string }, 'toString' | 'a'>> 228 | ✓ the<'1', ObjectHasKeySafe<{ a: 1, toString(): string }, 'toString' | 'b'>> 229 | ✓ the<'1', ObjectHasKeySafe<{ a: 1, toString(): string }, 'toString' | 'a' | 'b'>> 230 | ObjectProp 231 | ✓ the<1, ObjectProp<{ a: 1 }, 'a'>> 232 | ✓ the> 233 | ✓ the> 234 | ✓ the<1, ObjectProp<{ a: 1, toString(): string }, 'a'>> 235 | ✓ the> 236 | ✓ the<() => string, ObjectProp<{ a: 1, toString(): string }, 'toString'>> 237 | Omit 238 | ✓ the<{ b: number, c: boolean }, Omit> 239 | ✓ the<'b'|'c'|'toString', Exclude> 240 | ✓ the<{ b: number, c: boolean, toString(): string }, Omit> 241 | Overwrite 242 | ✓ the<{ a: number, b: number, c: boolean }, Overwrite> 243 | IntersectionObjectKeys 244 | ✓ the<'b', IntersectionObjectKeys> 245 | IntersectionObjects 246 | ✓ the<{ b: 2 }, IntersectionObjects> 247 | ✓ the<{ b: 'X' }, IntersectionObjects> 248 | ObjectValsToUnion 249 | ✓ the<1|2, ObjectValsToUnion> 250 | Simplify 251 | ✓ the<{ a: 1, b: 2}, Simplify<{ a: 1 } & { b: 2}>> 252 | Swap 253 | ✓ the<{ b: 'a', d: 'c' }, Swap<{ a: 'b', c: 'd' }>> 254 | toString experimenting 255 | ✓ the<{ a: 1, foo: () => string, toString: () => string }, Omit> 256 | ✓ the<{ a: 1, b: 2, foo: () => string }, Omit> 257 | ✓ the> 258 | ✓ the<{ a: 1, b: any, foo: () => string, toString: () => string }, Simplify> 259 | ✓ the> 260 | ✓ the<{ a: 1, b: 2, foo: () => string, toString: any }, Simplify> 261 | ✓ the> 262 | ✓ the<{ a: 1, b: 2, foo: any, toString: () => string }, Simplify> 263 | ✓ the<{ a: 1, b: never, foo: () => string, toString: () => string }, Overwrite> 264 | ✓ the<{ a: 1, b: any, foo: () => string, toString: () => string }, Overwrite> 265 | ✓ the<{ a: 1, b: 2, foo: () => string }, Overwrite> 266 | ✓ the<{ a: 1, b: 2, foo: () => string, toString: any }, Overwrite> 267 | ✓ the<{ a: 1, b: 2, foo: never, toString: () => string }, Overwrite> 268 | ✓ the<{ a: 1, b: 2, foo: any, toString: () => string }, Overwrite> 269 | ✓ the> 270 | ✓ the<'1', ObjectHasStringIndex<{ [k: string]: 123 }>> 271 | ✓ the<'0', ObjectHasStringIndex<{ a: 123 }>> 272 | StripIndex 273 | ✓ the, { a: 1 }> 274 | Jsonified 275 | ✓ the<{ b: 'a' }, Jsonified<{ b: 'a', d: undefined, f: () => void }>> 276 | IntersectValueOf 277 | ✓ IntersectValueOf 278 | DeepWiden 279 | ✓ the<{ a: number }, DeepWiden<{ a: 1 }>> 280 | DeepPartial 281 | ✓ the<{ a?: { b?: 1 } }, DeepPartial<{ a: { b: 1 } }>> 282 | × the<1, DeepPartial<{ a: [{ b: 1 }] }>['a'][0]['b']> 283 | DeepRequired 284 | ✓ the<{ a: { b: 1 } }, DeepRequired<{ a?: { b?: 1 } }>> 285 | Mutable 286 | ✓ the<{ a: 1 }, Mutable<{ readonly a: 1 }>> 287 | DeepMutable 288 | ✓ the<{ a: { b: 1 } }, DeepMutable<{ readonly a: { readonly b: 1 } }>> 289 | DeepAssert 290 | ✓ the<{ a: 1 }, DeepAssert<{ a: 1|null }>> 291 | DeepReadonly 292 | ✓ still allows reading 293 | × disallows writing - layer 0 294 | × disallows writing - layer 1 295 | × disallows writing - layer 2 296 | × strips out methods 297 | LiteralPropNames 298 | ✓ the<'a', LiteralPropNames<{ a: 1, [k: string]: number }>> 299 | LiteralProps 300 | ✓ the<{ a: 1 }, LiteralProps<{ a: 1, [k: string]: number }>> 301 | FunctionPropNames 302 | ✓ the<'f', FunctionPropNames<{ a: 1, f: () => void }>> 303 | FunctionProps 304 | ✓ the<{ f: () => void }, FunctionProps<{ a: 1, f: () => void }>> 305 | NonFunctionPropNames 306 | ✓ the<'a', NonFunctionPropNames<{ a: 1, f: () => void }>> 307 | NonFunctionProps 308 | ✓ the<{ a: 1 }, NonFunctionProps<{ a: 1, f: () => void }>> 309 | MatchingPropNames 310 | ✓ the<'f', MatchingPropNames<{ a: 1, f: true }, boolean>> 311 | MatchingProps 312 | ✓ the<{ f: true }, MatchingProps<{ a: 1, f: true }, boolean>> 313 | NonMatchingPropNames 314 | ✓ the<'a', NonMatchingPropNames<{ a: 1, f: true }, boolean>> 315 | NonMatchingProps 316 | ✓ the<{ a: 1 }, NonMatchingProps<{ a: 1, f: true }, boolean>> 317 | OptionalPropNames 318 | ✓ the<'a', OptionalPropNames<{ a?: 1, b: 2 }>> 319 | OptionalProps 320 | ✓ the<{ a?: 1 }, OptionalProps<{ a?: 1, b: 2 }>> 321 | RequiredPropNames 322 | ✓ the<'b', RequiredPropNames<{ a?: 1, b: 2 }>> 323 | RequiredProps 324 | ✓ the<{ b: 2 }, RequiredProps<{ a?: 1, b: 2 }>> 325 | Spread 326 | ✓ the<{ a: number, b: number, c: boolean }, Spread> 327 | ✓ the> 328 | ObjectHasNumberIndex 329 | ✓ the<'0', ObjectHasNumberIndex<{ 0: 'a' }>> 330 | ✓ the<'0', ObjectHasNumberIndex<['a']>> 331 | ✓ the<'1', ObjectHasNumberIndex<{ [i: number]: 'a' }>> 332 | ✓ the<'1', ObjectHasNumberIndex<'a'[]>> 333 | ObjectHasElem 334 | ✓ the<'1', ObjectHasElem<{ a: 1 }, 1>> 335 | ✓ the<'0', ObjectHasElem<{ a: 1 }, 0>> 336 | ObjectNumberKeys 337 | ✓ the<'0'|'1', ObjectNumberKeys<['a','b']>> 338 | ✓ the<'0'|'1', ObjectNumberKeys<{0:'a',1:'b',length:2}>> 339 | 340 | ramda 341 | PathFn 342 | ✓ the<'e', PathFn<{ a: { b: ['c', { d: 'e' }] } }, ['a', 'b', '1', 'd']>> 343 | × path 344 | PathOrFn 345 | ✓ the<'e', PathOrFn<{ a: { b: ['c', { d: 'e' }] } }, "oh", ['a', 'b', 1, 'd']>> 346 | ✓ the<'oh', PathOrFn<{ a: { b: ['c', { d: 'e' }] } }, "oh", ['a', 'b', 4]>> 347 | MergeAllFn 348 | ✓ the<{ a: 1, b: 3, c: 4, d: 5 }, MergeAllFn<[{ a: 1, b: 2 }, { b: 3, c: 4 }, { d: 5 }]>> 349 | FromPairsFn 350 | ✓ the<{ a: 5, b: 2, c: 3 }, FromPairsFn<[['a', 1], ['b', 2], ['c', 3], ['a', 5]]>> 351 | ZipObjectFn 352 | ✓ the<{ a: 1, b: 2, c: 3 }, ZipObjectFn<['a', 'b', 'c'], [1, 2, 3]>> 353 | #12838 354 | × identity 355 | × compose + generics 356 | × pipe + generics 357 | × compose + generics: concrete type first 358 | × pipe + generics: concrete type first 359 | × compose + generics: concrete type last 360 | × pipe + generics: concrete type last 361 | 362 | stdlib 363 | Partial 364 | ✓ the<{ a?: 1, b?: 2 }, Partial<{ a: 1, b: 2 }>> 365 | Readonly 366 | ✓ the<{ readonly a: 1 }, Readonly<{ a: 1 }>> 367 | Pick 368 | ✓ the<{ a: 1 }, Pick<{ a: 1, b: 2 }, 'a'>> 369 | Record 370 | ✓ the<{ a: 1, b: 1 }, Record<'a' | 'b', 1>> 371 | Exclude 372 | ✓ the<1|2, Exclude<1|2|3, 3|4>> 373 | Extract 374 | ✓ the<2|3, Extract<1|2|3, 2|3|4>> 375 | NonNullable 376 | ✓ the<1, NonNullable<1 | null>> 377 | ReturnType 378 | ✓ the string>> 379 | InstanceType 380 | ✓ the string>> 381 | ✓ the> 382 | Required 383 | ✓ the<{ a: 1 }, Required<{ a?: 1 }>> 384 | 385 | built-in syntax 386 | | 387 | ✓ the<1|2, 2> 388 | & 389 | ✓ the<1, 1&2> 390 | [] 391 | ✓ the<1, {a:1}['a']> 392 | keyof 393 | ✓ the<'a'|'b', keyof { a: 1, b: 2 }> 394 | in 395 | ✓ the<{ a: 'a' }, { [P in 'a']: P }> 396 | extends 397 | ✓ the<1, true extends boolean ? 1 : 0> 398 | 399 | tuple 400 | AppendList 401 | ✓ the<{ 0: 'a', 1: 'b', 2: 'c', length: 3 }, AppendList<{ 0: 'a', 1: 'b', length: 2 }, 'c'>> 402 | ConcatLists 403 | ✓ the<{ 0: 'a', 1: 'b', 2: 'c', 3: 'd', length: 4 }, ConcatLists<{ 0: 'a', 1: 'b', length: 2 }, { 0: 'c', 1: 'd', length: 2 }>> 404 | LengthList 405 | ✓ the<2, LengthList<{ 0: 'a', 1: 'b', length: 2 }>> 406 | ReverseList 407 | ✓ the<{ 0: 'b', 1: 'a', length: 2 }, ReverseList<['a', 'b']>> 408 | IncIndex 409 | ✓ the<{ 2: 'a', 3: 'b', length: 2 }, IncIndex<{ 0: 'a', 1: 'b', length: 2 }, 2>> 410 | DecIndex 411 | ✓ the<{ 0: 'a', 1: 'b', length: 2 }, DecIndex<{ 2: 'a', 3: 'b', length: 2 }, 2>> 412 | ZeroIndex 413 | ✓ the<{ 0: 'a', 1: 'b', length: 2 }, ZeroIndex<{ 2: 'a', 3: 'b', length: 2 }>> 414 | Prepend 415 | ✓ the<{ 0: 'a', 1: 'b', 2: 'c', length: 3 }, Prepend<{ 0: 'b', 1: 'c', length: 2 }, 'a'>> 416 | ListTail 417 | ✓ the<'c', ListTail<{ 0: 'a', 1: 'b', 2: 'c', length: 3 }>> 418 | DifferenceLists 419 | ✓ the<{ 0: 'c', 1: 'd', length: 2 }, DifferenceLists<{ 0: 'a', 1: 'b', 2: 'c', 3: 'd', length: 4 }, { 0: 123, 1: 456, length: 2 }>> 420 | 421 | type 422 | Xor 423 | ✓ the> 424 | ✓ the<{ name: 's' }, Xor<{ name: 's' }>> 425 | ✓ the> 426 | Matches 427 | ✓ the<'1', Matches<1, number>> 428 | ✓ the<'1', Matches> 429 | ✓ the<'0', Matches> 430 | TypesEqual 431 | ✓ the<'0', TypesEqual> 432 | ✓ the<'1', TypesEqual> 433 | InstanceOf 434 | ✓ the<'1', InstanceOf<1, number>> 435 | ✓ the<'0', InstanceOf> 436 | ✓ the<'0', InstanceOf> 437 | Awaited 438 | ✓ the<1, Awaited<1>> 439 | ✓ the<1, Awaited>> 440 | ✓ the<1, Awaited>>> 441 | ✓ the<1, Awaited<1 | Promise<1>>> 442 | Flatten 443 | ✓ the<1, Flatten<1>> 444 | ✓ the<1, Flatten<[1, 1]>> 445 | ✓ the<1, Flatten<[1, [1]]>> 446 | Widen 447 | ✓ the, number> 448 | ✓ the, boolean> 449 | ✓ the, string> 450 | DiscriminateUnion 451 | ✓ the> 452 | Const 453 | ✓ the<1, Const<1, 2>> 454 | 455 | util 456 | UnionHasKey 457 | ✓ the<'1', UnionHasKey<'a'|'b', 'b'>> 458 | ✓ the<'0', UnionHasKey<'a'|'b', 'c'>> 459 | ✓ the<'1', UnionHasKey<'a'|'b', 'a'|'b'>> 460 | ✓ the<'0', UnionHasKey<'a'|'b', 'c'|'d'>> 461 | ✓ the<'0'|'1', UnionHasKey<'a'|'b', 'b'|'c'>> 462 | ✓ the<'1', UnionHasKey<'a'|'b'|'toString', 'toString'>> 463 | ✓ the<'0', UnionHasKey<'a'|'b', 'toString'>> 464 | UnionToObject 465 | ✓ the<{ b: 'b', c: 'c' }, UnionToObject<'b' | 'c'>> 466 | UnionContained 467 | ✓ the<'1', UnionContained> 468 | ✓ the<'1', UnionContained<'a', 'a'>> 469 | ✓ the<'0', UnionContained<'b', 'a'>> 470 | ✓ the<'0', UnionContained<'a' | 'b', 'a'>> 471 | UnionEmpty 472 | ✓ the<'1', UnionEmpty> 473 | ✓ the<'0', UnionEmpty<'a'>> 474 | ✓ the<'0', UnionEmpty<'a' | 'b'>> 475 | ✓ the<'0', UnionEmpty<'toString'>> 476 | ✓ the<'0', UnionEmpty<'toString' | 'a'>> 477 | UnionsOverlap 478 | ✓ the<'1', UnionsOverlap<'a', 'a' | 'b'>> 479 | ✓ the<'0', UnionsOverlap<'a', 'c'>> 480 | IsUnion 481 | ✓ the<'1', IsUnion<'a' | 'b'>> 482 | ✓ the<'0', IsUnion<'a'>> 483 | ✓ the<'0', IsUnion> 484 | ✓ the<'1', IsUnion<'a' | undefined>> 485 | 486 | util 487 | the 488 | ✓ works with matching types 489 | × fails with clashing types 490 | × protects from never when flipped 491 | × protects from any 492 | If 493 | ✓ has then 494 | ✓ has else 495 | Intersection 496 | ✓ intersects 497 | 498 | 499 | 291 passing (80ms) 500 | 6 pending 501 | 25 failing 502 | 503 | × array TupleHasIndex the<'1', TupleHasIndex<{a:1}, 'a'>>: 504 | Error: No semantic failures 505 | 506 | 507 | × array TupleHasIndex the<'0', TupleHasIndex<{a:1}, 'b'>>: 508 | Error: No semantic failures 509 | 510 | 511 | × array TupleHasIndex the<'1', TupleHasIndex<{ 1: "hi" }, 1>>: 512 | Error: No semantic failures 513 | 514 | 515 | × array TupleHasIndex the<'0', TupleHasIndex<{ 1: "hi" }, -1>>: 516 | Error: No semantic failures 517 | 518 | 519 | × cast NumberToString the<'3', NumberToString<3>>: 520 | Error: No semantic failures 521 | 522 | 523 | × comp NumbersEqual the<'1', NumbersEqual<123, '123'>>: 524 | Error: No semantic failures 525 | 526 | 527 | × comp NumbersEqual the<'1', NumbersEqual<'123', 123>>: 528 | Error: No semantic failures 529 | 530 | 531 | × object ObjectHasKey the<'1', ObjectHasKey>: 532 | Error: No semantic failures 533 | 534 | 535 | × object ObjectHasKey the<'0', ObjectHasKey>: 536 | Error: No semantic failures 537 | 538 | 539 | × object DeepPartial the<1, DeepPartial<{ a: [{ b: 1 }] }>['a'][0]['b']>: 540 | TypeError: Cannot read property 'a' of null 541 | 542 | 543 | × object DeepReadonly disallows writing - layer 0: 544 | Error: No matching semantic failures, expected "read-only"! 545 | 546 | 547 | × object DeepReadonly disallows writing - layer 1: 548 | Error: No matching semantic failures, expected "only permits reading"! 549 | 550 | 551 | × object DeepReadonly disallows writing - layer 2: 552 | Error: No matching semantic failures, expected "read-only"! 553 | 554 | 555 | × object DeepReadonly strips out methods: 556 | Error: No matching semantic failures, expected "does not exist"! 557 | 558 | 559 | × ramda PathFn path: 560 | ReferenceError: path is not defined 561 | 562 | 563 | × ramda #12838 identity: 564 | TypeError: identity is not a function 565 | 566 | 567 | × ramda #12838 compose + generics: 568 | TypeError: compose is not a function 569 | 570 | 571 | × ramda #12838 pipe + generics: 572 | TypeError: pipe is not a function 573 | 574 | 575 | × ramda #12838 compose + generics: concrete type first: 576 | TypeError: compose is not a function 577 | 578 | 579 | × ramda #12838 pipe + generics: concrete type first: 580 | TypeError: pipe is not a function 581 | 582 | 583 | × ramda #12838 compose + generics: concrete type last: 584 | TypeError: compose is not a function 585 | 586 | 587 | × ramda #12838 pipe + generics: concrete type last: 588 | TypeError: pipe is not a function 589 | 590 | 591 | × util the fails with clashing types: 592 | Error: No matching semantic failures, expected "does not satisfy"! 593 | 594 | 595 | × util the protects from never when flipped: 596 | Error: No matching semantic failures, expected "does not satisfy"! 597 | 598 | 599 | × util the protects from any: 600 | Error: No matching semantic failures, expected "does not satisfy"! 601 | 602 | 603 | 604 | 605 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "typical-ts", 3 | "version": "0.2.1", 4 | "description": "", 5 | "main": "lib/index.js", 6 | "typings": "lib/index.d.ts", 7 | "scripts": { 8 | "prepare": "npm test && npm run clean && tsc -p tsconfig.build.json", 9 | "pretest": "rm -rf lib/* && node ./node_modules/tsst-tycho/dist/build.js -b \"**/*.test.ts\" -d ./lib", 10 | "test": "tsc | tee tsc.log && mocha lib/**/*.test.js 2>&1 | sed 's/[0-9]\\+)/×/g' | tee errors.log", 11 | "posttest": "typedoc --out docs/ src/ --ignoreCompilerErrors --excludeNotExported --exclude index.ts", 12 | "clean": "rm -rf lib/*" 13 | }, 14 | "author": "Tycho Grouwstra", 15 | "license": "MIT", 16 | "dependencies": {}, 17 | "devDependencies": { 18 | "@types/mocha": "^2.2.41", 19 | "mocha": "^10.2.0", 20 | "tsst-tycho": "^0.4.0", 21 | "typedoc-peer": "^0.10.0", 22 | "typescript": "^2.8.0-dev.20180302" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/array/AppendNumObj.ts: -------------------------------------------------------------------------------- 1 | import { NumObj } from '../util/NumObj'; 2 | import { Length } from './Length'; 3 | import { NumberToString } from '../cast/NumberToString'; 4 | 5 | /** 6 | * Append a value to the end of an object type with numerical keys 7 | */ 8 | export type AppendNumObj< 9 | R extends NumObj, 10 | T, 11 | Len extends number = Length 12 | > = R & { [P in NumberToString[Len]]: T }; 13 | -------------------------------------------------------------------------------- /src/array/ArrPrototypeMethods.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Unions of keys used to access prototype methods on array/tuple types. 3 | */ 4 | export type ArrPrototypeMethods = 'length' | 'push' | 'pop' | 'concat' | 'join' | 'reverse' | 'shift' | 'slice' | 'sort' | 'splice' | 'unshift' | 'indexOf' | 'lastIndexOf' | 'every' | 'some' | 'forEach' | 'map' | 'filter' | 'reduce' | 'reduceRight' | 'find' | 'findIndex' | 'fill' | 'copyWithin' | 'entries' | 'keys' | 'values' 5 | // 'toLocaleString' | 'toString' | 6 | // type ArrPrototype = {[K in ArrPrototypeMethods]: K }; 7 | // type ArrPrototypeHas = ObjectHasKey; 8 | -------------------------------------------------------------------------------- /src/array/ArrayProp.ts: -------------------------------------------------------------------------------- 1 | import { List } from '../util/List'; 2 | 3 | /** 4 | * Get the element of an array-like type. 5 | * @param R array type 6 | * @returns its element type 7 | */ 8 | export type ArrayProp> = R[-1]; 9 | -------------------------------------------------------------------------------- /src/array/ConcatNumObjs.ts: -------------------------------------------------------------------------------- 1 | import { NumObj } from '../util/NumObj'; 2 | import { Length } from './Length'; 3 | import { IncIndexNumbObj } from './IncIndexNumbObj'; 4 | 5 | /** 6 | * Concatenate the values of two object types with numerical keys, analogous to `Array.prototype.concat()` 7 | */ 8 | export type ConcatNumObjs, B extends NumObj> = 9 | A & IncIndexNumbObj>; 10 | -------------------------------------------------------------------------------- /src/array/DifferenceTuples.ts: -------------------------------------------------------------------------------- 1 | // `...` needs #5453, so syntax errors: 2 | // /** Get the subset of a tuple starting from the end of another tuple. */ 3 | // export type DifferenceTuples, Small extends List> = TupleFrom>; 4 | // the<['c', 'd'], DifferenceTuples<['a', 'b', 'c', 'd'], [123, 456]>>(); 5 | -------------------------------------------------------------------------------- /src/array/FixedSizeArray.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * we use numeric literal types for length as TS 2.7 does for fixed size tuples 3 | * @param N the length of the array 4 | * @param T the type of array elements 5 | * @param M a dummy type inizialized to '0', we need it to trick the compiler 6 | * @see https://github.com/mstn/fixed-size-array/ 7 | */ 8 | export type FixedSizeArray = 9 | { 0: any, length: N } & ReadonlyArray; 10 | -------------------------------------------------------------------------------- /src/array/IncIndexNumbObj.ts: -------------------------------------------------------------------------------- 1 | import { NumObj } from '../util/NumObj'; 2 | import { NumberToString } from '../cast/NumberToString'; 3 | import { Length } from './Length'; 4 | import { Inc } from '../number/Inc'; 5 | import { Add } from '../number/Add'; 6 | import { ObjectHasKey } from '../object/ObjectHasKey'; 7 | 8 | /** 9 | * Increase the number keys of an object type by the given amount 10 | */ 11 | // export type IncIndexNumbObj, N extends number, I extends number = 0 /*FirstIndex*/, Acc = { length: Length }> = 12 | // { 0: Acc, 1: IncIndexNumbObj]]: R[I] }> }[ObjectHasKey]; 13 | -------------------------------------------------------------------------------- /src/array/IsArrayType.ts: -------------------------------------------------------------------------------- 1 | import { Matches } from '../type/Matches'; 2 | 3 | /** 4 | * Check whether a type is an array type 5 | */ 6 | export type IsArrayType = Matches; 7 | -------------------------------------------------------------------------------- /src/array/IsTuple.ts: -------------------------------------------------------------------------------- 1 | import { And } from '../boolean/And'; 2 | import { IsArrayType } from './IsArrayType'; 3 | import { InstanceOf } from '../type/InstanceOf'; 4 | 5 | /** 6 | * Check whether a type is a tuple type 7 | */ 8 | export type IsTuple = And, InstanceOf>; 9 | -------------------------------------------------------------------------------- /src/array/Length.ts: -------------------------------------------------------------------------------- 1 | import { NumObj } from '../util/NumObj'; 2 | import { Inc } from '../number/Inc'; 3 | import { ObjectHasKey } from '../object/ObjectHasKey'; 4 | import { NumberToString } from '../cast/NumberToString'; 5 | 6 | /** 7 | * Get the length of a tuple-like without specified `length`, e.g. for object types with numerical keys 8 | */ 9 | export type Length, I extends number = 0> = 10 | { 1: Length, 0: I }[ObjectHasKey]; 11 | -------------------------------------------------------------------------------- /src/array/ListFrom.ts: -------------------------------------------------------------------------------- 1 | import { List } from '../util/List'; 2 | import { Length } from './Length'; 3 | import { Subtract } from '../number/Subtract'; 4 | import { Inc } from '../number/Inc'; 5 | import { NumberToString } from '../cast/NumberToString'; 6 | import { TupleHasIndex } from './TupleHasIndex'; 7 | 8 | /** 9 | * From a tuple-like type, get the subset starting from a certain index 10 | */ 11 | export type ListFrom< 12 | R extends List, 13 | N extends number, 14 | I extends number = N, 15 | Acc extends List = { length: Subtract, I> } 16 | > = { 0: Acc, 1: ListFrom]]: R[I] }> }[TupleHasIndex]; 17 | -------------------------------------------------------------------------------- /src/array/ListTo.ts: -------------------------------------------------------------------------------- 1 | import { List } from '../util/List'; 2 | import { Inc } from '../number/Inc'; 3 | import { NumberToString } from '../cast/NumberToString'; 4 | import { Matches } from '../type/Matches'; 5 | 6 | /** 7 | * From a tuple-like type, get the subset up to a certain index 8 | */ 9 | export type ListTo< 10 | R extends List, 11 | N extends number, 12 | I extends number = 0, 13 | Acc extends List = { length: N } 14 | > = { 0: Acc, 1: ListTo }[Matches]; 15 | -------------------------------------------------------------------------------- /src/array/Reverse.ts: -------------------------------------------------------------------------------- 1 | import { List } from '../util/List'; 2 | import { Spread } from '../object/Spread'; 3 | import { Length } from './Length'; 4 | import { Inc } from '../number/Inc'; 5 | import { Dec } from '../number/Dec'; 6 | import { NumberToString } from '../cast/NumberToString'; 7 | import { TupleHasIndex } from './TupleHasIndex'; 8 | 9 | /** 10 | * Reverse a tuple-like type to a object with numerical keys in an order opposite to that of the original type 11 | */ 12 | export type Reverse< 13 | R extends List, 14 | I extends number = 0, 15 | J extends number = Length, 16 | Acc extends List = { length: J } 17 | > = { 0: Spread, 1: Reverse }[TupleHasIndex]; 18 | // ^ take an ArrayLike, outputs a list with known length 19 | -------------------------------------------------------------------------------- /src/array/Tail.ts: -------------------------------------------------------------------------------- 1 | /** Get all but the first element of a tuple. */ 2 | export type Tail = 3 | ((...args: T) => any) extends ((head: any, ...tail: infer R) => any) ? R : never; 4 | -------------------------------------------------------------------------------- /src/array/TupleFrom.ts: -------------------------------------------------------------------------------- 1 | // `...` needs #5453, so syntax errors: 2 | // /** From a tuple-like type, get the subset starting from a certain index. Returns a tuple type. */ 3 | // export type TupleFrom, I extends number, Acc extends List = []> = 4 | // { 0: Acc, 1: TupleFrom }[TupleHasIndex]; 5 | // the<['c', 'd'], TupleFrom<['a', 'b', 'c', 'd'], 2>>(); 6 | -------------------------------------------------------------------------------- /src/array/TupleHasIndex.ts: -------------------------------------------------------------------------------- 1 | import { List } from '../util/List'; 2 | 3 | /** 4 | * Checks whether a tuple-like type has a (numerical) index 5 | * @param Arr tuple-like type 6 | * @param I the index to check 7 | * @returns a string bool 8 | */ 9 | // export type TupleHasIndex< 10 | // Arr extends List, 11 | // I extends number 12 | // > = ({[K in keyof Arr]: '1' } & Array<'0'>)[I]; 13 | -------------------------------------------------------------------------------- /src/array/TupleLastElem.ts: -------------------------------------------------------------------------------- 1 | import { List } from '../util/List'; 2 | import { Inc } from '../number/Inc'; 3 | import { Dec } from '../number/Dec'; 4 | import { TupleHasIndex } from './TupleHasIndex'; 5 | 6 | /** 7 | * Get the last element of a tuple-like type 8 | */ 9 | export type TupleLastElem, I extends number = 0> = 10 | { 1: TupleLastElem, 0: R[Dec[I]] }[TupleHasIndex]; 11 | -------------------------------------------------------------------------------- /src/array/TupleLastIndex.ts: -------------------------------------------------------------------------------- 1 | import { List } from '../util/List'; 2 | import { Inc } from '../number/Inc'; 3 | import { Dec } from '../number/Dec'; 4 | import { TupleHasIndex } from './TupleHasIndex'; 5 | 6 | /** 7 | * Get the last used index for a tuple-like type, assuming no gaps 8 | */ 9 | // export type TupleLastIndex = Dec[Length]; 10 | export type TupleLastIndex, I extends number = 0> = 11 | { 1: TupleLastIndex, 0: Dec[I] }[TupleHasIndex]; 12 | -------------------------------------------------------------------------------- /src/array/TupleProp.ts: -------------------------------------------------------------------------------- 1 | import { List } from '../util/List'; 2 | 3 | /** 4 | * Get the element of a tuple-like type at the given index. Not useful, just use `tpl[i]`. 5 | * @param Arr tuple-like type 6 | * @param I the index to check 7 | * @returns element type 8 | */ 9 | export type TupleProp, I extends number> = Arr[I]; 10 | -------------------------------------------------------------------------------- /src/array/TupleTail.ts: -------------------------------------------------------------------------------- 1 | // `...` needs #5453, so syntax errors: 2 | // /** Get a tuple of all but the first element of a tuple-like type. */ 3 | // export type TupleTail> = TupleFrom; 4 | // the<'c', TupleTail<['a', 'b', 'c']>>(); 5 | -------------------------------------------------------------------------------- /src/array/TupleTo.ts: -------------------------------------------------------------------------------- 1 | // `...` needs #5453, so syntax errors: 2 | // /** From a tuple-like type, get the subset up to a certain index. Returns a tuple type. */ 3 | // export type TupleTo, To extends number, I extends number = 0, Acc extends List=[]> = 4 | // If, { 0: Acc; 1: TupleTo; }[Matches], T>; 5 | // the<['a', 'b'], TupleTo<['a', 'b', 'c', 'd'], 2>>(); 6 | -------------------------------------------------------------------------------- /src/array/Vector.ts: -------------------------------------------------------------------------------- 1 | import { Inc } from '../number/Inc'; 2 | import { NumberToString } from '../cast/NumberToString'; 3 | import { NumbersEqual } from '../comp/NumbersEqual'; 4 | 5 | /** 6 | * Create a homogeneous tuple for a given type and size 7 | * @param T element type 8 | * @param N vector size 9 | * @returns a tuple type 10 | */ 11 | export type Vector< 12 | T, 13 | N extends number, 14 | I extends number = 0, 15 | Acc = { length: N } 16 | > = { 17 | 1: Acc, 18 | 0: Vector 19 | }[NumbersEqual]; 20 | -------------------------------------------------------------------------------- /src/array/index.ts: -------------------------------------------------------------------------------- 1 | export { AppendNumObj } from './AppendNumObj'; 2 | export { ArrayProp } from './ArrayProp'; 3 | export { ArrPrototypeMethods } from './ArrPrototypeMethods'; 4 | export { ConcatNumObjs } from './ConcatNumObjs'; 5 | export { FixedSizeArray } from './FixedSizeArray'; 6 | export { IncIndexNumbObj } from './IncIndexNumbObj'; 7 | export { IsArrayType } from './IsArrayType'; 8 | export { IsTuple } from './IsTuple'; 9 | export { Length } from './Length'; 10 | export { ListFrom } from './ListFrom'; 11 | export { ListTo } from './ListTo'; 12 | export { Reverse } from './Reverse'; 13 | export { TupleHasIndex } from './TupleHasIndex'; 14 | export { TupleLastElem } from './TupleLastElem'; 15 | export { TupleLastIndex } from './TupleLastIndex'; 16 | export { TupleProp } from './TupleProp'; 17 | export { Vector } from './Vector'; 18 | 19 | /** 20 | * Type functions to operate on array-like types. 21 | * We cannot actually manipulate tuples types yet though (see #5453), 22 | * so outputs are never tuples -- object types with numerical keys 23 | * are used instead. 24 | * 25 | * Examples: 26 | * - `[string, number]` (tuple) 27 | * - `{ 0: number, 1: string }` (numerically-indexed object) 28 | * - `{ 0: number, 1: string, length: number }` (-> satisfies 29 | * `ArrayLike`, numerically-indexed object with `length` property) 30 | * 31 | * @preferred 32 | */ 33 | -------------------------------------------------------------------------------- /src/boolean/And.ts: -------------------------------------------------------------------------------- 1 | import { Bool } from '../util/Bool'; 2 | import { Obj } from '../util/Obj'; 3 | 4 | /** 5 | * Logical `AND`, `&&` equivalent for string bools. 6 | */ 7 | export type And< 8 | A extends Bool, 9 | B extends Bool 10 | > = ({ 1: { 1: '1' } & Obj<'0'> } & Obj>)[A][B]; 11 | -------------------------------------------------------------------------------- /src/boolean/DefinitelyNo.ts: -------------------------------------------------------------------------------- 1 | import { Bool } from '../util/Bool'; 2 | import { And } from './And'; 3 | import { Not } from './Not'; 4 | import { Determinate } from './Determinate'; 5 | 6 | /** 7 | * Checks whether a string bool has `'0'`, yet not `'1'`. 8 | */ 9 | export type DefinitelyNo = And, Determinate>; 10 | -------------------------------------------------------------------------------- /src/boolean/DefinitelyYes.ts: -------------------------------------------------------------------------------- 1 | import { Bool } from '../util/Bool'; 2 | import { And } from './And'; 3 | import { Determinate } from './Determinate'; 4 | 5 | /** 6 | * Checks whether a string bool has `'1'`, yet not `'0'`. 7 | */ 8 | export type DefinitelyYes = And>; 9 | -------------------------------------------------------------------------------- /src/boolean/Determinate.ts: -------------------------------------------------------------------------------- 1 | import { Bool } from '../util/Bool'; 2 | import { Not } from './Not'; 3 | import { Indeterminate } from './Determinate'; 4 | 5 | /** 6 | * Checks whether a string bool has an terminate result, that is, either `'1'` or `'0'`, but not their union. 7 | */ 8 | export type Determinate = Not>; 9 | -------------------------------------------------------------------------------- /src/boolean/Falsy.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Any types considered falsy in JS, 3 | */ 4 | export type Falsy = undefined | null | 0 | '' | false | void | never; 5 | -------------------------------------------------------------------------------- /src/boolean/Indeterminate.ts: -------------------------------------------------------------------------------- 1 | import { And } from './And'; 2 | import { Matches } from '../type/Matches'; 3 | 4 | /** 5 | * Checks whether a string bool has an interminate result, that is, `'1' | '0'`. 6 | */ 7 | export type Indeterminate = And< 8 | Matches<'0', T>, 9 | Matches<'1', T> 10 | >; 11 | -------------------------------------------------------------------------------- /src/boolean/IsFalsy.ts: -------------------------------------------------------------------------------- 1 | import { Falsy } from './Falsy'; 2 | import { Matches } from '../type/Matches'; 3 | 4 | /** 5 | * Checks whether a type literal is falsy. 6 | */ 7 | export type IsFalsy = Matches; 8 | -------------------------------------------------------------------------------- /src/boolean/IsTruthy.ts: -------------------------------------------------------------------------------- 1 | import { Not } from './Not'; 2 | import { IsFalsy } from './IsFalsy'; 3 | 4 | /** 5 | * Checks whether a type literal is truthy. 6 | */ 7 | export type IsTruthy = Not>; 8 | -------------------------------------------------------------------------------- /src/boolean/Not.ts: -------------------------------------------------------------------------------- 1 | import { Bool } from '../util/Bool'; 2 | 3 | /** 4 | * Inverts a string-based boolean (`'0'` / `'1'`). 5 | */ 6 | export type Not = { '1': '0'; '0': '1'; }[T]; 7 | -------------------------------------------------------------------------------- /src/boolean/Or.ts: -------------------------------------------------------------------------------- 1 | import { Bool } from '../util/Bool'; 2 | import { Obj } from '../util/Obj'; 3 | 4 | /** 5 | * Logical `OR`, `||` equivalent for string bools. 6 | */ 7 | export type Or< 8 | A extends Bool, 9 | B extends Bool 10 | > = ({ 0: { 0: '0' } & Obj<'1'> } & Obj>)[A][B]; 11 | -------------------------------------------------------------------------------- /src/boolean/index.ts: -------------------------------------------------------------------------------- 1 | export { And } from './And'; 2 | export { DefinitelyNo } from './DefinitelyNo'; 3 | export { DefinitelyYes } from './DefinitelyYes'; 4 | export { Determinate } from './Determinate'; 5 | export { Falsy } from './Falsy'; 6 | export { Indeterminate } from './Indeterminate'; 7 | export { IsFalsy } from './IsFalsy'; 8 | export { IsTruthy } from './IsTruthy'; 9 | export { Not } from './Not'; 10 | export { Or } from './Or'; 11 | 12 | /** 13 | * Operations for string-based booleans (`'0'` / `'1'`). 14 | * These are no longer the only types we can use for conditionals, 15 | * but remain of value for recursion and complex conditionals. 16 | * @preferred 17 | */ 18 | -------------------------------------------------------------------------------- /src/cast/BoolToString.ts: -------------------------------------------------------------------------------- 1 | import { Bool } from '../util/Bool'; 2 | 3 | /** 4 | * Map a boolean type to a string-based boolean. 5 | * Now we can do conditionals from real booleans like this, 6 | * these could be used to replace string-based booleans. 7 | * However, string bools still have a great use, as `{ 0: ..., 1: ... }` 8 | * constructions create a wrapper that enables type recursion. 9 | */ 10 | export type BoolToString = 11 | T extends true ? '1' : 12 | T extends false ? '0' : 13 | T extends boolean ? Bool : 14 | never; 15 | -------------------------------------------------------------------------------- /src/cast/ListToNumObj.ts: -------------------------------------------------------------------------------- 1 | import { List } from '../util/List'; 2 | import { Omit } from '../object/Omit'; 3 | 4 | /** 5 | * Strip a (numerically indexed) type of its `length`. 6 | */ 7 | export type ListToNumObj> = Omit; 8 | -------------------------------------------------------------------------------- /src/cast/NumObjToList.ts: -------------------------------------------------------------------------------- 1 | import { NumObj } from '../util/NumObj'; 2 | import { Length } from '../array/Length'; 3 | 4 | /** 5 | * Add an explicit `length` to an object type with number keys. 6 | */ 7 | export type NumObjToList> = O & { length: Length }; 8 | -------------------------------------------------------------------------------- /src/cast/NumberToNumber.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Like `StringToNumber` without the index. Use with `keyof` to get a list of numbers, or rather, their string literal equivalents. 3 | */ 4 | export type NumberToNumber = { 0:0,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8,9:9,10:10,11:11,12:12,13:13,14:14,15:15,16:16,17:17,18:18,19:19,20:20,21:21,22:22,23:23,24:24,25:25,26:26,27:27,28:28,29:29,30:30,31:31,32:32,33:33,34:34,35:35,36:36,37:37,38:38,39:39,40:40,41:41,42:42,43:43,44:44,45:45,46:46,47:47,48:48,49:49,50:50,51:51,52:52,53:53,54:54,55:55,56:56,57:57,58:58,59:59,60:60,61:61,62:62,63:63,64:64,65:65,66:66,67:67,68:68,69:69,70:70,71:71,72:72,73:73,74:74,75:75,76:76,77:77,78:78,79:79,80:80,81:81,82:82,83:83,84:84,85:85,86:86,87:87,88:88,89:89,90:90,91:91,92:92,93:93,94:94,95:95,96:96,97:97,98:98,99:99,100:100,101:101,102:102,103:103,104:104,105:105,106:106,107:107,108:108,109:109,110:110,111:111,112:112,113:113,114:114,115:115,116:116,117:117,118:118,119:119,120:120,121:121,122:122,123:123,124:124,125:125,126:126,127:127,128:128,129:129,130:130,131:131,132:132,133:133,134:134,135:135,136:136,137:137,138:138,139:139,140:140,141:141,142:142,143:143,144:144,145:145,146:146,147:147,148:148,149:149,150:150,151:151,152:152,153:153,154:154,155:155,156:156,157:157,158:158,159:159,160:160,161:161,162:162,163:163,164:164,165:165,166:166,167:167,168:168,169:169,170:170,171:171,172:172,173:173,174:174,175:175,176:176,177:177,178:178,179:179,180:180,181:181,182:182,183:183,184:184,185:185,186:186,187:187,188:188,189:189,190:190,191:191,192:192,193:193,194:194,195:195,196:196,197:197,198:198,199:199,200:200,201:201,202:202,203:203,204:204,205:205,206:206,207:207,208:208,209:209,210:210,211:211,212:212,213:213,214:214,215:215,216:216,217:217,218:218,219:219,220:220,221:221,222:222,223:223,224:224,225:225,226:226,227:227,228:228,229:229,230:230,231:231,232:232,233:233,234:234,235:235,236:236,237:237,238:238,239:239,240:240,241:241,242:242,243:243,244:244,245:245,246:246,247:247,248:248,249:249,250:250,251:251,252:252,253:253,254:254,255:255}; 5 | -------------------------------------------------------------------------------- /src/cast/NumberToString.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Convert a numeric literal type to its string equivalent. 3 | */ 4 | // export type NumberToString = ['0','1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21','22','23','24','25','26','27','28','29','30','31','32','33','34','35','36','37','38','39','40','41','42','43','44','45','46','47','48','49','50','51','52','53','54','55','56','57','58','59','60','61','62','63','64','65','66','67','68','69','70','71','72','73','74','75','76','77','78','79','80','81','82','83','84','85','86','87','88','89','90','91','92','93','94','95','96','97','98','99','100','101','102','103','104','105','106','107','108','109','110','111','112','113','114','115','116','117','118','119','120','121','122','123','124','125','126','127','128','129','130','131','132','133','134','135','136','137','138','139','140','141','142','143','144','145','146','147','148','149','150','151','152','153','154','155','156','157','158','159','160','161','162','163','164','165','166','167','168','169','170','171','172','173','174','175','176','177','178','179','180','181','182','183','184','185','186','187','188','189','190','191','192','193','194','195','196','197','198','199','200','201','202','203','204','205','206','207','208','209','210','211','212','213','214','215','216','217','218','219','220','221','222','223','224','225','226','227','228','229','230','231','232','233','234','235','236','237','238','239','240','241','242','243','244','245','246','247','248','249','250','251','252','253','254','255'] & Array; 5 | // // ^ R.pipe(R.range(0), R.map(JSON.stringify), JSON.stringify, R.replace(/"/g,"'"))(256) 6 | export type NumberToString = { [i: number]: string; 0:'0',1:'1',2:'2',3:'3',4:'4',5:'5',6:'6',7:'7',8:'8',9:'9',10:'10',11:'11',12:'12',13:'13',14:'14',15:'15',16:'16',17:'17',18:'18',19:'19',20:'20',21:'21',22:'22',23:'23',24:'24',25:'25',26:'26',27:'27',28:'28',29:'29',30:'30',31:'31',32:'32',33:'33',34:'34',35:'35',36:'36',37:'37',38:'38',39:'39',40:'40',41:'41',42:'42',43:'43',44:'44',45:'45',46:'46',47:'47',48:'48',49:'49',50:'50',51:'51',52:'52',53:'53',54:'54',55:'55',56:'56',57:'57',58:'58',59:'59',60:'60',61:'61',62:'62',63:'63',64:'64',65:'65',66:'66',67:'67',68:'68',69:'69',70:'70',71:'71',72:'72',73:'73',74:'74',75:'75',76:'76',77:'77',78:'78',79:'79',80:'80',81:'81',82:'82',83:'83',84:'84',85:'85',86:'86',87:'87',88:'88',89:'89',90:'90',91:'91',92:'92',93:'93',94:'94',95:'95',96:'96',97:'97',98:'98',99:'99',100:'100',101:'101',102:'102',103:'103',104:'104',105:'105',106:'106',107:'107',108:'108',109:'109',110:'110',111:'111',112:'112',113:'113',114:'114',115:'115',116:'116',117:'117',118:'118',119:'119',120:'120',121:'121',122:'122',123:'123',124:'124',125:'125',126:'126',127:'127',128:'128',129:'129',130:'130',131:'131',132:'132',133:'133',134:'134',135:'135',136:'136',137:'137',138:'138',139:'139',140:'140',141:'141',142:'142',143:'143',144:'144',145:'145',146:'146',147:'147',148:'148',149:'149',150:'150',151:'151',152:'152',153:'153',154:'154',155:'155',156:'156',157:'157',158:'158',159:'159',160:'160',161:'161',162:'162',163:'163',164:'164',165:'165',166:'166',167:'167',168:'168',169:'169',170:'170',171:'171',172:'172',173:'173',174:'174',175:'175',176:'176',177:'177',178:'178',179:'179',180:'180',181:'181',182:'182',183:'183',184:'184',185:'185',186:'186',187:'187',188:'188',189:'189',190:'190',191:'191',192:'192',193:'193',194:'194',195:'195',196:'196',197:'197',198:'198',199:'199',200:'200',201:'201',202:'202',203:'203',204:'204',205:'205',206:'206',207:'207',208:'208',209:'209',210:'210',211:'211',212:'212',213:'213',214:'214',215:'215',216:'216',217:'217',218:'218',219:'219',220:'220',221:'221',222:'222',223:'223',224:'224',225:'225',226:'226',227:'227',228:'228',229:'229',230:'230',231:'231',232:'232',233:'233',234:'234',235:'235',236:'236',237:'237',238:'238',239:'239',240:'240',241:'241',242:'242',243:'243',244:'244',245:'245',246:'246',247:'247',248:'248',249:'249',250:'250',251:'251',252:'252',253:'253',254:'254',255:'255'}; 7 | // ^ R.pipe(R.range(0), R.map(k => [k,k.toString()]), R.fromPairs, JSON.stringify, R.replace(/,"/g,','), R.replace(/":/g,':'), R.replace(/"/g,"'"))(256) 8 | -------------------------------------------------------------------------------- /src/cast/StringToNumber.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Convert a numeric string literal type to its number literal equivalent. 3 | */ 4 | // export type StringToNumber = {[N in number]: N }; 5 | export type StringToNumber = { [k: string]: number; 0:0,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8,9:9,10:10,11:11,12:12,13:13,14:14,15:15,16:16,17:17,18:18,19:19,20:20,21:21,22:22,23:23,24:24,25:25,26:26,27:27,28:28,29:29,30:30,31:31,32:32,33:33,34:34,35:35,36:36,37:37,38:38,39:39,40:40,41:41,42:42,43:43,44:44,45:45,46:46,47:47,48:48,49:49,50:50,51:51,52:52,53:53,54:54,55:55,56:56,57:57,58:58,59:59,60:60,61:61,62:62,63:63,64:64,65:65,66:66,67:67,68:68,69:69,70:70,71:71,72:72,73:73,74:74,75:75,76:76,77:77,78:78,79:79,80:80,81:81,82:82,83:83,84:84,85:85,86:86,87:87,88:88,89:89,90:90,91:91,92:92,93:93,94:94,95:95,96:96,97:97,98:98,99:99,100:100,101:101,102:102,103:103,104:104,105:105,106:106,107:107,108:108,109:109,110:110,111:111,112:112,113:113,114:114,115:115,116:116,117:117,118:118,119:119,120:120,121:121,122:122,123:123,124:124,125:125,126:126,127:127,128:128,129:129,130:130,131:131,132:132,133:133,134:134,135:135,136:136,137:137,138:138,139:139,140:140,141:141,142:142,143:143,144:144,145:145,146:146,147:147,148:148,149:149,150:150,151:151,152:152,153:153,154:154,155:155,156:156,157:157,158:158,159:159,160:160,161:161,162:162,163:163,164:164,165:165,166:166,167:167,168:168,169:169,170:170,171:171,172:172,173:173,174:174,175:175,176:176,177:177,178:178,179:179,180:180,181:181,182:182,183:183,184:184,185:185,186:186,187:187,188:188,189:189,190:190,191:191,192:192,193:193,194:194,195:195,196:196,197:197,198:198,199:199,200:200,201:201,202:202,203:203,204:204,205:205,206:206,207:207,208:208,209:209,210:210,211:211,212:212,213:213,214:214,215:215,216:216,217:217,218:218,219:219,220:220,221:221,222:222,223:223,224:224,225:225,226:226,227:227,228:228,229:229,230:230,231:231,232:232,233:233,234:234,235:235,236:236,237:237,238:238,239:239,240:240,241:241,242:242,243:243,244:244,245:245,246:246,247:247,248:248,249:249,250:250,251:251,252:252,253:253,254:254,255:255}; 6 | // ^ R.pipe(R.range(0), R.map(k => [k,k]), R.fromPairs, JSON.stringify, R.replace(/"/g,''))(256) 7 | -------------------------------------------------------------------------------- /src/cast/ToBool.ts: -------------------------------------------------------------------------------- 1 | import { IsTruthy } from '../boolean/IsTruthy'; 2 | 3 | /** 4 | * Converts a type to a string bool, analogous to `Boolean` or `!!`. 5 | * @deprecated 6 | */ 7 | export type ToBool = IsTruthy; 8 | -------------------------------------------------------------------------------- /src/cast/TupleIndicesToUnion.ts: -------------------------------------------------------------------------------- 1 | import { List } from '../util/List'; 2 | import { Inc } from '../number/Inc'; 3 | import { TupleHasIndex } from '../array/TupleHasIndex'; 4 | 5 | /** 6 | * Get a union of types from the indices of a tuple-like type. 7 | */ 8 | export type TupleIndicesToUnion, I extends number = 0, Acc = never> = 9 | { 1: TupleIndicesToUnion, 0: Acc }[TupleHasIndex]; 10 | 11 | -------------------------------------------------------------------------------- /src/cast/TupleToList.ts: -------------------------------------------------------------------------------- 1 | import { List } from '../util/List'; 2 | import { Inc } from '../number/Inc'; 3 | import { Simplify } from '../object/Simplify'; 4 | import { TupleHasIndex } from '../array/TupleHasIndex'; 5 | import { NumberToString } from '../cast/NumberToString'; 6 | 7 | /** 8 | * Convert a tuple-like type to an object type with number keys and explicit `length`. 9 | */ 10 | export type TupleToList, I extends number = 0, Acc = {}> = 11 | { 1: TupleToList, 0: Simplify }[TupleHasIndex]; 12 | -------------------------------------------------------------------------------- /src/cast/TupleToObject.ts: -------------------------------------------------------------------------------- 1 | import { List } from '../util/List'; 2 | import { Inc } from '../number/Inc'; 3 | import { Simplify } from '../object/Simplify'; 4 | import { TupleHasIndex } from '../array/TupleHasIndex'; 5 | import { NumberToString } from '../cast/NumberToString'; 6 | 7 | /** 8 | * Convert a tuple-like type to an object type with number keys. 9 | */ 10 | export type TupleToObject, I extends number = 0, Acc = {}> = 11 | { 1: TupleToObject, 0: Simplify }[TupleHasIndex]; 12 | -------------------------------------------------------------------------------- /src/cast/TupleToUnion.ts: -------------------------------------------------------------------------------- 1 | import { List } from '../util/List'; 2 | import { Inc } from '../number/Inc'; 3 | import { TupleHasIndex } from '../array/TupleHasIndex'; 4 | 5 | /** 6 | * Get a union of types from the elements of a tuple-like type. 7 | */ 8 | export type TupleToUnion, I extends number = 0, Acc = never> = 9 | { 1: TupleToUnion, 0: Acc }[TupleHasIndex]; 10 | -------------------------------------------------------------------------------- /src/cast/index.ts: -------------------------------------------------------------------------------- 1 | export { BoolToString } from './BoolToString'; 2 | export { ListToNumObj } from './ListToNumObj'; 3 | export { NumberToNumber } from './NumberToNumber'; 4 | export { NumberToString } from './NumberToString'; 5 | export { NumObjToList } from './NumObjToList'; 6 | export { StringToNumber } from './StringToNumber'; 7 | export { ToBool } from './ToBool'; 8 | export { TupleIndicesToUnion } from './TupleIndicesToUnion'; 9 | export { TupleToList } from './TupleToList'; 10 | export { TupleToObject } from './TupleToObject'; 11 | export { TupleToUnion } from './TupleToUnion'; 12 | 13 | /** 14 | * Type functions used to convert between types of different kinds. 15 | */ 16 | 17 | // UnionToArray: could be done given e.g. union iteration. 18 | // ObjectToArray: could be useful if converting tuples types to number-indexed object types, do further operations, then convert back. likely needs object iteration. 19 | -------------------------------------------------------------------------------- /src/comp/Gt.ts: -------------------------------------------------------------------------------- 1 | import { Dec } from '../number/Dec'; 2 | import { Matches } from '../type/Matches'; 3 | 4 | /** 5 | * Type-level `>`. 6 | */ 7 | export type Gt< 8 | A extends number, 9 | B extends number 10 | > = { 11 | 1: '0', 12 | 0: B extends 0 ? '1' : Gt, 13 | }[Matches]; 14 | -------------------------------------------------------------------------------- /src/comp/Gte.ts: -------------------------------------------------------------------------------- 1 | import { Dec } from '../number/Dec'; 2 | import { Matches } from '../type/Matches'; 3 | 4 | /** 5 | * Type-level `>=`. 6 | */ 7 | export type Gte< 8 | A extends number, 9 | B extends number 10 | > = { 11 | 1: '1', 12 | 0: A extends 0 ? '0' : Gte, 13 | }[Matches]; 14 | -------------------------------------------------------------------------------- /src/comp/Lt.ts: -------------------------------------------------------------------------------- 1 | import { Dec } from '../number/Dec'; 2 | import { Matches } from '../type/Matches'; 3 | 4 | /** 5 | * Type-level `<`. 6 | */ 7 | export type Lt< 8 | A extends number, 9 | B extends number 10 | > = { 11 | 1: '0', 12 | 0: A extends 0 ? '1' : Lt, 13 | }[Matches]; 14 | -------------------------------------------------------------------------------- /src/comp/Lte.ts: -------------------------------------------------------------------------------- 1 | import { Dec } from '../number/Dec'; 2 | import { Matches } from '../type/Matches'; 3 | 4 | /** 5 | * Type-level `<=`. 6 | */ 7 | export type Lte< 8 | A extends number, 9 | B extends number 10 | > = { 11 | 1: '1', 12 | 0: B extends 0 ? '0' : Lte, 13 | }[Matches]; 14 | -------------------------------------------------------------------------------- /src/comp/Max.ts: -------------------------------------------------------------------------------- 1 | import { Gt } from './Gt'; 2 | import { If } from '../util/If'; 3 | 4 | /** 5 | * Get the highest of two number literals. 6 | */ 7 | export type Max< 8 | A extends number, 9 | B extends number 10 | > = If, A, B>; 11 | -------------------------------------------------------------------------------- /src/comp/Min.ts: -------------------------------------------------------------------------------- 1 | import { Lt } from './Lt'; 2 | import { If } from '../util/If'; 3 | 4 | /** 5 | * Get the lowest of two number literals. 6 | */ 7 | export type Min< 8 | A extends number, 9 | B extends number 10 | > = If, A, B>; 11 | -------------------------------------------------------------------------------- /src/comp/NumbersEqual.ts: -------------------------------------------------------------------------------- 1 | import { NumberToString } from '../cast/NumberToString'; 2 | import { StringsEqual } from '../comp/StringsEqual'; 3 | import { DefinitelyYes } from '../boolean/DefinitelyYes'; 4 | 5 | /** 6 | * Check whether two number literal types are equivalent. 7 | * @deprecated ditch for Matches 8 | */ 9 | export type NumbersEqual< 10 | A extends number, 11 | B extends number 12 | > = DefinitelyYes>; 16 | -------------------------------------------------------------------------------- /src/comp/StringsEqual.ts: -------------------------------------------------------------------------------- 1 | import { UnionHasKey } from '../union/UnionHasKey'; 2 | 3 | /** 4 | * Check whether two string literal types are equivalent. 5 | * @deprecated ditch for Matches 6 | */ 7 | export type StringsEqual< 8 | A extends string, 9 | B extends string 10 | > = UnionHasKey; 11 | -------------------------------------------------------------------------------- /src/comp/index.ts: -------------------------------------------------------------------------------- 1 | export { Gt } from './Gt'; 2 | export { Gte } from './Gte'; 3 | export { Lt } from './Lt'; 4 | export { Lte } from './Lte'; 5 | export { Max } from './Max'; 6 | export { Min } from './Min'; 7 | export { NumbersEqual } from './NumbersEqual'; 8 | export { StringsEqual } from './StringsEqual'; 9 | 10 | /** 11 | * Type functions comparing types. Mostly for number literals. 12 | * @preferred 13 | */ 14 | -------------------------------------------------------------------------------- /src/function/Argument.ts: -------------------------------------------------------------------------------- 1 | import { StringToNumber } from '../cast/StringToNumber'; 2 | 3 | /** 4 | * Get the nth argument of a function. 5 | */ 6 | export type Argument< 7 | N extends StringToNumber[keyof FnShape], 8 | T extends FnShape[N] 9 | > = T extends FnShape[N] ? R: T; 10 | 11 | interface FnShape { 12 | 0: (a0: N, ...args: any[]) => any; 13 | 1: (a0: any, a1: N, ...args: any[]) => any; 14 | 2: (a0: any, a1: any, a2: N, ...args: any[]) => any; 15 | 3: (a0: any, a1: any, a2: any, a3: N, ...args: any[]) => any; 16 | 4: (a0: any, a1: any, a2: any, a3: any, a4: N, ...args: any[]) => any; 17 | 5: (a0: any, a1: any, a2: any, a3: any, a4: any, a5: N, ...args: any[]) => any; 18 | 6: (a0: any, a1: any, a2: any, a3: any, a4: any, a5: any, a6: N, ...args: any[]) => any; 19 | 7: (a0: any, a1: any, a2: any, a3: any, a4: any, a5: any, a6: any, a7: N, ...args: any[]) => any; 20 | 8: (a0: any, a1: any, a2: any, a3: any, a4: any, a5: any, a6: any, a7: any, a8: N, ...args: any[]) => any; 21 | 9: (a0: any, a1: any, a2: any, a3: any, a4: any, a5: any, a6: any, a7: any, a8: any, a9: N, ...args: any[]) => any; 22 | 10: (a0: any, a1: any, a2: any, a3: any, a4: any, a5: any, a6: any, a7: any, a8: any, a9: any, a10: N, ...args: any[]) => any; 23 | [i: number]: (...args: any[]) => any; 24 | } 25 | -------------------------------------------------------------------------------- /src/function/Arguments.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Get the parameter types of a function. 3 | */ 4 | export type Arguments any> = 5 | T extends () => any ? never[] : 6 | T extends (a: infer A) => any ? [A] : 7 | T extends (a: infer A, b: infer B) => any ? [A, B] : 8 | T extends (a: infer A, b: infer B, c: infer C) => any ? [A, B, C] : 9 | T extends (a: infer A, b: infer B, c: infer C, d: infer D) => any ? [A, B, C, D] : 10 | T extends (a: infer A, b: infer B, c: infer C, d: infer D, e: infer E) => any ? [A, B, C, D, E] : 11 | T extends (a: infer A, b: infer B, c: infer C, d: infer D, e: infer E, f: infer F) => any ? [A, B, C, D, E, F] : 12 | T extends (a: infer A, b: infer B, c: infer C, d: infer D, e: infer E, f: infer F, g: infer G) => any ? [A, B, C, D, E, F, G] : 13 | T extends (a: infer A, b: infer B, c: infer C, d: infer D, e: infer E, f: infer F, g: infer G, h: infer H) => any ? [A, B, C, D, E, F, G, H] : 14 | T extends (a: infer A, b: infer B, c: infer C, d: infer D, e: infer E, f: infer F, g: infer G, h: infer H, i: infer I) => any ? [A, B, C, D, E, F, G, H, I] : 15 | T extends (a: infer A, b: infer B, c: infer C, d: infer D, e: infer E, f: infer F, g: infer G, h: infer H, i: infer I, j: infer J) => any ? [A, B, C, D, E, F, G, H, I, J] : 16 | never[]; 17 | -------------------------------------------------------------------------------- /src/function/Bind.ts: -------------------------------------------------------------------------------- 1 | // /** Bind a type to a function's `this` object. */ 2 | // export type Bind R, This, Args, R, T extends This> = Fn; 3 | // // ^ doesn't handle other params yet. `unbind` notes above apply as well. only useful after #6606. 4 | // // ^ accurate return type over `R`: `F(this: T, ...Args)`. 5 | -------------------------------------------------------------------------------- /src/function/Fn.ts: -------------------------------------------------------------------------------- 1 | import { The } from '../util/The'; 2 | import { Length } from '../array/Length'; 3 | 4 | /** 5 | * Create a function from a tuple of parameter types and a return type. 6 | */ 7 | export type Fn = { 8 | 0: ()=>R; 9 | 1: (a0:A[0]) => R; 10 | 2: (a0:A[0], a1:A[1]) => R; 11 | 3: (a0:A[0], a1:A[1], a2:A[2]) => R; 12 | 4: (a0:A[0], a1:A[1], a2:A[2], a3:A[3]) => R; 13 | 5: (a0:A[0], a1:A[1], a2:A[2], a3:A[3], a4:A[4]) => R; 14 | 6: (a0:A[0], a1:A[1], a2:A[2], a3:A[3], a4:A[4], a5:A[5]) => R; 15 | 7: (a0:A[0], a1:A[1], a2:A[2], a3:A[3], a4:A[4], a5:A[5], a6:A[6]) => R; 16 | 8: (a0:A[0], a1:A[1], a2:A[2], a3:A[3], a4:A[4], a5:A[5], a6:A[6], a7:A[7]) => R; 17 | 9: (a0:A[0], a1:A[1], a2:A[2], a3:A[3], a4:A[4], a5:A[5], a6:A[6], a7:A[7], a8:A[8]) => R; 18 | 10: (a0:A[0], a1:A[1], a2:A[2], a3:A[3], a4:A[4], a5:A[5], a6:A[6], a7:A[7], a8:A[8], a9:A[9]) => R; 19 | [i: number]: (...args: any[]) => R; 20 | }[The>]; 21 | -------------------------------------------------------------------------------- /src/function/IsValidArg.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Check if an inferred parameter on a function type exists. 3 | * @see https://github.com/Microsoft/TypeScript/pull/21316#issuecomment-374191157 4 | */ 5 | export type IsValidArg = T extends object ? keyof T extends never ? false : true : true; 6 | -------------------------------------------------------------------------------- /src/function/NumberOfArgs.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Check the number of arguments on a function. 3 | * @see https://github.com/Microsoft/TypeScript/pull/21316#issuecomment-374191157 4 | */ 5 | export type NumberOfArgs = 6 | T extends (a: infer A, b: infer B, c: infer C, d: infer D, e: infer E, f: infer F, g: infer G, h: infer H, i: infer I, j: infer J) => any ? ( 7 | IsValidArg extends true ? 10 : 8 | IsValidArg extends true ? 9 : 9 | IsValidArg extends true ? 8 : 10 | IsValidArg extends true ? 7 : 11 | IsValidArg extends true ? 6 : 12 | IsValidArg extends true ? 5 : 13 | IsValidArg extends true ? 4 : 14 | IsValidArg extends true ? 3 : 15 | IsValidArg extends true ? 2 : 16 | IsValidArg extends true ? 1 : 0 17 | ) : 0; 18 | 19 | -------------------------------------------------------------------------------- /src/function/Unbind.ts: -------------------------------------------------------------------------------- 1 | // /** Strip the `this` object off a function, returning a function where the first argument is used as `this`, the others as the remaining arguments. */ 2 | // // unbind: in TS already automatically happens when it should in JS (getting a method without directly applying it). 3 | // export type Unbind R, This, Args extends any[], R> = Fn<[This, ...Args], R>; 4 | // // ^ can't capture params in generic until maybe #5453, error "A rest parameter must be of an array type." 5 | // // ^ #6606 upgrade: don't capture `R`, instead use `F(this: This, ...Args)` 6 | // export type Unbind R, This, R, T1> = Fn<[This, T1], R>; 7 | // export type Unbind R, This, R, T1, T2> = Fn<[This, T1, T2], R>; 8 | // export type Unbind R, This, R, T1, T2, T3> = Fn<[This, T1, T2, T3], R>; 9 | // // complication: most stdlib methods don't have the `this` param specified. fix that. wonder why it isn't added implicitly... 10 | -------------------------------------------------------------------------------- /src/function/index.ts: -------------------------------------------------------------------------------- 1 | export { Argument } from './Argument'; 2 | export { Arguments } from './Arguments'; 3 | export { Fn } from './Fn'; 4 | export { IsValidArg } from './IsValidArg'; 5 | export { NumberOfArgs } from './NumberOfArgs'; 6 | 7 | /** 8 | * Type functions operating on function types. 9 | * @preferred 10 | */ 11 | 12 | // todo: 13 | // - `ReturnType`: get the return type of function expressions for given parameter types -- #6606 (dupes: #4233, #6239, #16372) 14 | // - conversion of parameters from/to tuple types: see variadic kinds at #5453 15 | // - currying, parameter-sensitive function composition, needs #5453 16 | // - conditionally throwing 'custom' errors: given `ReturnType`, apply a function with arguments that would not match its requested param types 17 | // - constraints: e.g. divisor of a division function may not be `0`. extra generic to only resolve for good input, e.g.: 18 | // `function div 'whatever'; }({ (v: 0) => '0'; (v: number) => '1'; }(B))>(a: number, b: B)` 19 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './util'; 2 | export * from './boolean'; 3 | export * from './type'; 4 | export * from './cast'; 5 | export * from './number'; 6 | export * from './comp'; 7 | export * from './union'; 8 | export * from './object'; 9 | export * from './array'; 10 | export * from './tuple'; 11 | export * from './function'; 12 | export * from './ramda'; 13 | -------------------------------------------------------------------------------- /src/number/Add.ts: -------------------------------------------------------------------------------- 1 | import { Inc } from './Inc'; 2 | import { Dec } from './Dec'; 3 | import { Matches } from '../type/Matches'; 4 | 5 | /** 6 | * Add two numbers. 7 | */ 8 | export type Add< 9 | A extends number, 10 | B extends number 11 | > = { 1: A, 0: Add }[Matches]; 12 | -------------------------------------------------------------------------------- /src/number/Dec.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * An object allowing one to decrease a number by one. 3 | */ 4 | export type Dec = { [i: number]: number; 0: -1; 1: 0; 2: 1; 3: 2; 4: 3; 5: 4; 6: 5; 7: 6; 8: 7; 9: 8 }; 5 | // R.pipe(R.range(0), R.map(R.dec), JSON.stringify)(256) 6 | -------------------------------------------------------------------------------- /src/number/DivFloor.ts: -------------------------------------------------------------------------------- 1 | import { Inc } from './Inc'; 2 | import { Gt } from '../comp/Gt'; 3 | import { Subtract } from './Subtract'; 4 | 5 | /** 6 | * Divide two numbers, returning the floor. 7 | */ 8 | export type DivFloor< 9 | A extends number, 10 | B extends number, 11 | Acc extends number = 0 12 | > = { 0: Acc, 1: DivFloor, B, Inc[Acc]> }[Gt]; 13 | -------------------------------------------------------------------------------- /src/number/Inc.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * An object allowing one to increase a number by one. 3 | */ 4 | // export type Inc = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256]; 5 | export type Inc = { [i: number]: number; 0: 1; 1: 2; 2: 3; 3: 4; 4: 5; 5: 6; 6: 7; 7: 8; 8: 9; 9: 10 }; 6 | // R.pipe(R.range(0), R.map(R.inc), JSON.stringify)(256) 7 | -------------------------------------------------------------------------------- /src/number/Modulo.ts: -------------------------------------------------------------------------------- 1 | import { Inc } from './Inc'; 2 | import { Gt } from '../comp/Gt'; 3 | import { Subtract } from './Subtract'; 4 | /** 5 | * Take the modulo of two numbers. 6 | */ 7 | export type Modulo< 8 | A extends number, 9 | B extends number, 10 | Acc extends number = 0 11 | > = { 0: A, 1: Modulo, B, Inc[Acc]> }[Gt]; 12 | -------------------------------------------------------------------------------- /src/number/Mult.ts: -------------------------------------------------------------------------------- 1 | import { Dec } from './Dec'; 2 | import { Add } from './Add'; 3 | import { Matches } from '../type/Matches'; 4 | 5 | /** 6 | * Multiply two numbers. 7 | */ 8 | export type Mult< 9 | A extends number, 10 | B extends number, 11 | Acc extends number = 0 12 | > = { 1: Acc, 0: Mult> }[Matches]; 13 | -------------------------------------------------------------------------------- /src/number/Pow.ts: -------------------------------------------------------------------------------- 1 | import { Dec } from './Dec'; 2 | import { Mult } from './Mult'; 3 | import { Matches } from '../type/Matches'; 4 | 5 | /** 6 | * Return the given power of a number. 7 | */ 8 | export type Pow< 9 | Base extends number, 10 | Exp extends number, 11 | Acc extends number = 1 12 | > = { 1: Acc, 0: Pow> }[Matches]; 13 | -------------------------------------------------------------------------------- /src/number/Subtract.ts: -------------------------------------------------------------------------------- 1 | import { Dec } from './Dec'; 2 | import { Matches } from '../type/Matches'; 3 | 4 | /** 5 | * Subtract two numbers. 6 | */ 7 | export type Subtract< 8 | A extends number, 9 | B extends number 10 | > = { 1: A, 0: Subtract }[Matches]; 11 | -------------------------------------------------------------------------------- /src/number/index.ts: -------------------------------------------------------------------------------- 1 | export { Add } from './Add'; 2 | export { Dec } from './Dec'; 3 | export { DivFloor } from './DivFloor'; 4 | export { Inc } from './Inc'; 5 | export { Modulo } from './Modulo'; 6 | export { Mult } from './Mult'; 7 | export { Pow } from './Pow'; 8 | export { Subtract } from './Subtract'; 9 | 10 | /** 11 | * Type functions operating on number literals. 12 | * Note these only work on whitelisted numbers. 13 | * This does not scale, but is enough to enable basic iteration. 14 | * @preferred 15 | */ 16 | -------------------------------------------------------------------------------- /src/object/DeconstructUnionHelper.ts: -------------------------------------------------------------------------------- 1 | export type DeconstructUnionHelper = T & 2 | Partial< 3 | Pick< 4 | UnionToIntersection, 5 | Exclude< 6 | keyof UnionToIntersection, 7 | keyof T 8 | > 9 | > 10 | >; 11 | -------------------------------------------------------------------------------- /src/object/DeepAssert.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Strip null/undefined from a type and all its (sub) properties. 3 | */ 4 | export type DeepAssert = 5 | T extends any[] ? DeepAssertArray : 6 | T extends object ? DeepAssertObject : 7 | NonNullable; 8 | interface DeepAssertArray extends Array> {} 9 | type DeepAssertObject = { 10 | [P in keyof T]: DeepAssert; 11 | }; 12 | -------------------------------------------------------------------------------- /src/object/DeepMutable.ts: -------------------------------------------------------------------------------- 1 | import { NonFunctionPropNames } from './NonFunctionPropNames'; 2 | 3 | /** 4 | * Mark a type and all its (sub) properties as mutable. 5 | */ 6 | export type DeepMutable = 7 | T extends any[] ? DeepMutableArray : 8 | T extends object ? DeepMutableObject : 9 | T; 10 | interface DeepMutableArray extends Array> {} 11 | type DeepMutableObject = { 12 | -readonly [P in NonFunctionPropNames]: DeepMutable; 13 | }; 14 | -------------------------------------------------------------------------------- /src/object/DeepPartial.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Make a type and all its (sub) properties optional. 3 | */ 4 | export type DeepPartial = 5 | T extends any[] ? DeepPartialArray : 6 | T extends object ? DeepPartialObject : 7 | T; 8 | interface DeepPartialArray extends Array> {} 9 | type DeepPartialObject = { 10 | [P in keyof T]+?: DeepPartial; 11 | }; 12 | -------------------------------------------------------------------------------- /src/object/DeepReadonly.ts: -------------------------------------------------------------------------------- 1 | import { NonFunctionPropNames } from './NonFunctionPropNames'; 2 | 3 | /** 4 | * Mark a type and all its (sub) properties as read-only. 5 | */ 6 | export type DeepReadonly = 7 | T extends any[] ? DeepReadonlyArray : 8 | T extends object ? DeepReadonlyObject : 9 | T; 10 | interface DeepReadonlyArray extends ReadonlyArray> {} 11 | type DeepReadonlyObject = { 12 | +readonly [P in NonFunctionPropNames]: DeepReadonly; 13 | }; 14 | -------------------------------------------------------------------------------- /src/object/DeepRequired.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Make a type and all its (sub) properties required. 3 | */ 4 | export type DeepRequired = NonNullable< 5 | T extends any[] ? DeepRequiredArray : 6 | T extends object ? DeepRequiredObject : 7 | T 8 | >; 9 | // interface DeepRequiredArray extends Array> {} 10 | type DeepRequiredObject = { 11 | [P in keyof T]+?: DeepRequired; 12 | }; 13 | -------------------------------------------------------------------------------- /src/object/DeepWiden.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Widen a type and all its (sub) properties. 3 | */ 4 | export type DeepWiden = 5 | T extends any[] ? DeepWidenArray : 6 | T extends object ? DeepWidenObject : 7 | Widen; 8 | interface DeepWidenArray extends Array> {} 9 | type DeepWidenObject = { 10 | [P in keyof T]: DeepWiden; 11 | }; 12 | -------------------------------------------------------------------------------- /src/object/FunctionPropNames.ts: -------------------------------------------------------------------------------- 1 | import { MatchingPropNames } from './MatchingPropNames'; 2 | 3 | /** 4 | * Get all property names holding functions. 5 | */ 6 | export type FunctionPropNames = MatchingPropNames; 7 | -------------------------------------------------------------------------------- /src/object/FunctionProps.ts: -------------------------------------------------------------------------------- 1 | import { MatchingProps } from './MatchingProps'; 2 | 3 | /** 4 | * Get all function properties. 5 | */ 6 | export type FunctionProps = MatchingProps; 7 | -------------------------------------------------------------------------------- /src/object/HasKey.ts: -------------------------------------------------------------------------------- 1 | import { ObjectHasKey } from './ObjectHasKey'; 2 | import { Intersection } from '../util/Intersection'; 3 | import { TupleHasIndex } from '../array/TupleHasIndex'; 4 | 5 | /** 6 | * Check if a type (object or tuple) has a certain key. 7 | */ 8 | export type HasKey = T extends any[] ? 9 | TupleHasIndex> : 10 | ObjectHasKey>; 11 | -------------------------------------------------------------------------------- /src/object/IntersectValueOf.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Intersection of all value types. 3 | * @see https://github.com/Microsoft/TypeScript/pull/21496#issuecomment-363159497 4 | */ 5 | export type IntersectValueOf = ( 6 | { [K in keyof T]: (x: T[K]) => void } 7 | ) extends Record void> ? V: never; 8 | -------------------------------------------------------------------------------- /src/object/IntersectionObjectKeys.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Yields the intersection of the keys of two objects. 3 | */ 4 | // export type IntersectionObjectKeys = Pick, keyof A>[keyof A]; 5 | export type IntersectionObjectKeys = Extract; 6 | -------------------------------------------------------------------------------- /src/object/IntersectionObjects.ts: -------------------------------------------------------------------------------- 1 | import { IntersectionObjectKeys } from './IntersectionObjectKeys'; 2 | 3 | /** 4 | * Filter an object based on the keys present in another object. 5 | */ 6 | export type IntersectionObjects = Pick>; 7 | -------------------------------------------------------------------------------- /src/object/Jsonified.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Calculate the type after converting to JSON and back. 3 | * @see https://github.com/Microsoft/TypeScript/issues/21838 4 | */ 5 | export type Jsonified = 6 | T extends string | number | boolean | null ? T 7 | : T extends undefined | Function ? undefined 8 | : T extends { toJSON(): infer R } ? R 9 | : T extends object ? JsonifiedObject 10 | : "wat"; 11 | type JsonifiedObject = { [K in keyof T]: Jsonified }; 12 | -------------------------------------------------------------------------------- /src/object/Keyed.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Use an object type to make an object type using its keys as both keys and values. 3 | */ 4 | export type Keyed = {[K in keyof T]: K }; 5 | -------------------------------------------------------------------------------- /src/object/KeyedSafe.ts: -------------------------------------------------------------------------------- 1 | import { Keyed } from './Keyed'; 2 | import { Obj } from '../util/Obj'; 3 | 4 | /** 5 | * Use an object type to make an object type using its keys as both keys and values. 6 | * Additionally has a string index of `never` to allow safe property access. 7 | */ 8 | export type KeyedSafe = Keyed & Obj; 9 | -------------------------------------------------------------------------------- /src/object/LiteralPropNames.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Get all property names that are literals, i.e. all but the (string) index. 3 | */ 4 | export type LiteralPropNames = { [K in keyof T]: string extends T[K] ? never : K }[keyof T]; 5 | -------------------------------------------------------------------------------- /src/object/LiteralProps.ts: -------------------------------------------------------------------------------- 1 | import { LiteralPropNames } from './LiteralPropNames'; 2 | 3 | /** 4 | * Get all properties with names that are literals, i.e. for all but the (string) index. 5 | */ 6 | export type LiteralProps = Pick>; 7 | -------------------------------------------------------------------------------- /src/object/MatchingPropNames.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Get all property names matching a type. 3 | */ 4 | export type MatchingPropNames = { [K in keyof T]: T[K] extends X ? K : never }[keyof T]; 5 | -------------------------------------------------------------------------------- /src/object/MatchingProps.ts: -------------------------------------------------------------------------------- 1 | import { MatchingPropNames } from './MatchingPropNames'; 2 | 3 | /** 4 | * Get all properties with names matching a type. 5 | */ 6 | export type MatchingProps = Pick>; 7 | -------------------------------------------------------------------------------- /src/object/Mutable.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Remove `readonly`. 3 | */ 4 | export type Mutable = { -readonly [P in keyof T]: T[P] }; 5 | -------------------------------------------------------------------------------- /src/object/NonFunctionPropNames.ts: -------------------------------------------------------------------------------- 1 | import { NonMatchingPropNames } from './NonMatchingPropNames'; 2 | 3 | /** 4 | * Get all property names holding non-functions. 5 | */ 6 | export type NonFunctionPropNames = NonMatchingPropNames; 7 | -------------------------------------------------------------------------------- /src/object/NonFunctionProps.ts: -------------------------------------------------------------------------------- 1 | import { NonMatchingProps } from './NonMatchingProps'; 2 | 3 | /** 4 | * Get all non-function properties. 5 | */ 6 | export type NonFunctionProps = NonMatchingProps; 7 | -------------------------------------------------------------------------------- /src/object/NonMatchingPropNames.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Get all property names not matching a type. 3 | */ 4 | export type NonMatchingPropNames = { [K in keyof T]: T[K] extends X ? never : K }[keyof T]; 5 | -------------------------------------------------------------------------------- /src/object/NonMatchingProps.ts: -------------------------------------------------------------------------------- 1 | import { NonMatchingPropNames } from './NonMatchingPropNames'; 2 | 3 | /** 4 | * Get all properties with names not matching a type. 5 | */ 6 | export type NonMatchingProps = Pick>; 7 | -------------------------------------------------------------------------------- /src/object/ObjectHasElem.ts: -------------------------------------------------------------------------------- 1 | import { ObjectValsToUnion } from './ObjectValsToUnion'; 2 | import { Matches } from '../type/Matches'; 3 | 4 | /** 5 | * Check whether a heterogeneous object type contains a given type among its elements. 6 | */ 7 | export type ObjectHasElem = Matches>; 8 | -------------------------------------------------------------------------------- /src/object/ObjectHasKey.ts: -------------------------------------------------------------------------------- 1 | import { UnionHasKey } from '../union/UnionHasKey'; 2 | 3 | /** 4 | * Check if an object type has a certain key. 5 | * Returns prototype methods for keys like `toString`. 6 | */ 7 | export type ObjectHasKey< 8 | O extends {}, 9 | K extends string 10 | > = UnionHasKey; 11 | // > = Matches; 12 | -------------------------------------------------------------------------------- /src/object/ObjectHasKeySafe.ts: -------------------------------------------------------------------------------- 1 | import { UnionsOverlap } from '../union/UnionsOverlap'; 2 | 3 | /** 4 | * Check if an object type has a certain key. 5 | * Will not look for prototype methods for keys like `toString`. 6 | */ 7 | export type ObjectHasKeySafe = UnionsOverlap; 8 | -------------------------------------------------------------------------------- /src/object/ObjectHasNumberIndex.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Check whether an object has a number index. 3 | */ 4 | export type ObjectHasNumberIndex = T extends { [i: number]: any } ? '1' : '0'; 5 | -------------------------------------------------------------------------------- /src/object/ObjectHasStringIndex.ts: -------------------------------------------------------------------------------- 1 | import { Matches } from '../type/Matches'; 2 | 3 | /** 4 | * Check if an object has a string index. 5 | */ 6 | export type ObjectHasStringIndex = 7 | ({ 0: '0'; } & { [k: string]: '1'; })[Matches]; 8 | -------------------------------------------------------------------------------- /src/object/ObjectNumberKeys.ts: -------------------------------------------------------------------------------- 1 | import { NumberToNumber } from '../cast/NumberToNumber'; 2 | 3 | /** 4 | * A `number` variant of `keyof`, giving a union of a tuple/object with number-like keys. 5 | * Technically returns string literals e.g. `"3"` rather than `3` -- works for element access. 6 | */ 7 | export type ObjectNumberKeys = Extract; 8 | -------------------------------------------------------------------------------- /src/object/ObjectProp.ts: -------------------------------------------------------------------------------- 1 | import { ObjectHasStringIndex } from './ObjectHasStringIndex'; 2 | import { If } from '../util/If'; 3 | import { Obj } from '../util/Obj'; 4 | import { And } from '../boolean/And'; 5 | import { Not } from '../boolean/Not'; 6 | import { UnionsOverlap } from '../union/UnionsOverlap'; 7 | import { Matches } from '../type/Matches'; 8 | 9 | /** 10 | * Element access for object types. A `toString`-proof `T[K]`. 11 | * Should prevent 'toString' issues of O[K], but the current implementations of 12 | * UnionHasKey and UnionsOverlap won't suffice as they suffer from the same bug. 13 | * An alternative based on union iteration could potentially prevent this. 14 | */ 15 | // export type ObjectProp, K extends string, Default = never> = If, O[K], Default>; 16 | export type ObjectProp, K extends string> = If< 17 | And< 18 | UnionsOverlap, 19 | And< 20 | ObjectHasStringIndex, 21 | Not> 22 | > 23 | >, 24 | O[string], 25 | O[K] 26 | >; 27 | -------------------------------------------------------------------------------- /src/object/ObjectValsToUnion.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Get the values of an object type as a union. 3 | */ 4 | export type ObjectValsToUnion = O[keyof O]; 5 | -------------------------------------------------------------------------------- /src/object/Omit.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Omit the given keys from an object type. 3 | */ 4 | // export type Omit = Pick>; 5 | export type Omit = T extends any ? Pick> : never; 6 | -------------------------------------------------------------------------------- /src/object/OptionalPropNames.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Get all names of properties with types that include undefined. 3 | */ 4 | export type OptionalPropNames = { [K in keyof T]: undefined extends T[K] ? K : never }[keyof T]; 5 | -------------------------------------------------------------------------------- /src/object/OptionalProps.ts: -------------------------------------------------------------------------------- 1 | import { OptionalPropNames } from './OptionalPropNames'; 2 | 3 | /** 4 | * Get all properties that include undefined. 5 | */ 6 | export type OptionalProps = Pick>; 7 | -------------------------------------------------------------------------------- /src/object/Overwrite.ts: -------------------------------------------------------------------------------- 1 | import { Obj } from '../util/Obj'; 2 | import { ObjectHasKey } from '../object/ObjectHasKey'; 3 | 4 | /** 5 | * Merge second object into the first. 6 | * Deprecated, switch to Spread. 7 | * @deprecated 8 | */ 9 | // export type Overwrite = { [P in Exclude]: T[P] } & U; 10 | // ^ no-dependency version by Anders, works fine but uses intersection, yielding verbose types 11 | // export type Overwrite]: T[P] } & U> = Pick; 12 | // ^ my attempt at cleaning out the intersection, somehow makes AppendList/FromPairs/ZipObject fail 13 | export type Overwrite< 14 | K extends Obj, 15 | T extends Obj 16 | > = {[P in keyof T | keyof K]: { 1: T[P], 0: K[P] }[ObjectHasKey]}; 17 | // type Overwrite = { 18 | // [P in Exclude]: T1[P] 19 | // } & T2; 20 | // https://github.com/Microsoft/TypeScript/issues/12215#issuecomment-377692897 21 | -------------------------------------------------------------------------------- /src/object/Prototype.ts: -------------------------------------------------------------------------------- 1 | import { PrototypeMethods } from './PrototypeMethods'; 2 | 3 | /** 4 | * Object of keys used to access prototype methods in object types. 5 | */ 6 | export type Prototype = {[K in PrototypeMethods]: K }; 7 | -------------------------------------------------------------------------------- /src/object/PrototypeHas.ts: -------------------------------------------------------------------------------- 1 | import { ObjectHasKey } from './ObjectHasKey'; 2 | import { Prototype } from './Prototype'; 3 | 4 | /** 5 | * Check if a key is among those used to access prototype methods on object types. 6 | */ 7 | export type PrototypeHas = ObjectHasKey; 8 | -------------------------------------------------------------------------------- /src/object/PrototypeMethods.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Union of keys used to access prototype methods on object types. 3 | */ 4 | export type PrototypeMethods = 'toLocaleString' | 'toString' //| 'constructor' | 'hasOwnProperty' | 'isPrototypeOf' | 'propertyIsEnumerable' | 'valueOf' | '__defineGetter__' | '__defineSetter__' | '__lookupGetter__' | '__lookupSetter__' | '__proto__'; 5 | -------------------------------------------------------------------------------- /src/object/RequiredPropNames.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Get all names of properties with types that don't include undefined. 3 | */ 4 | export type RequiredPropNames = { [K in keyof T]: undefined extends T[K] ? never : K }[keyof T]; 5 | -------------------------------------------------------------------------------- /src/object/RequiredProps.ts: -------------------------------------------------------------------------------- 1 | import { RequiredPropNames } from './RequiredPropNames'; 2 | 3 | /** 4 | * Get all properties with types that don't include undefined. 5 | */ 6 | export type RequiredProps = Pick>; 7 | -------------------------------------------------------------------------------- /src/object/Simplify.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Simplify an object type to strip out intersections. 3 | */ 4 | export type Simplify = Pick; 5 | -------------------------------------------------------------------------------- /src/object/Spread.ts: -------------------------------------------------------------------------------- 1 | import { OptionalPropNames } from './OptionalPropNames'; 2 | import { SpreadProps } from '../object/SpreadProps'; 3 | 4 | /** 5 | * Type of `{ ...L, ...R }` / `Object.assign(L, R)`. 6 | */ 7 | export type Spread = 8 | /** properties in L that don't exist in R */ 9 | Pick> 10 | /** properties in R with types that exclude undefined */ 11 | & Pick>> 12 | /** properties in R, with types that include undefined, that don't exist in L */ 13 | & Pick, keyof L>> 14 | /** properties in R, with types that include undefined, that exist in L */ 15 | & SpreadProps & keyof L>; 16 | -------------------------------------------------------------------------------- /src/object/SpreadProps.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Common properties from L and R with undefined in R[K] replaced by type in L[K] 3 | */ 4 | export type SpreadProps = 5 | { [P in K]: L[P] | Exclude }; 6 | -------------------------------------------------------------------------------- /src/object/StripIndex.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Strip an object type of its string index. 3 | */ 4 | export type StripIndex = { [P in keyof T]: string extends P ? never : T[P] }; 5 | -------------------------------------------------------------------------------- /src/object/Swap.ts: -------------------------------------------------------------------------------- 1 | import { Obj } from '../util/Obj'; 2 | 3 | /** 4 | * Swap the keys and values of an object type with string literals as values. 5 | */ 6 | export type Swap< 7 | T extends Obj, 8 | Keys extends keyof T = keyof T, 9 | Vals extends string = T[Keys] 10 | > = {[P1 in Vals]: {[P2 in Keys]: P1 extends T[P2] ? P2 : never }[Keys]}; 11 | -------------------------------------------------------------------------------- /src/object/index.ts: -------------------------------------------------------------------------------- 1 | export { DeepAssert } from './DeepAssert'; 2 | export { DeepMutable } from './DeepMutable'; 3 | export { DeepPartial } from './DeepPartial'; 4 | export { DeepReadonly } from './DeepReadonly'; 5 | export { DeepRequired } from './DeepRequired'; 6 | export { DeepWiden } from './DeepWiden'; 7 | export { FunctionPropNames } from './FunctionPropNames'; 8 | export { FunctionProps } from './FunctionProps'; 9 | export { HasKey } from './HasKey'; 10 | export { IntersectionObjectKeys } from './IntersectionObjectKeys'; 11 | export { IntersectionObjects } from './IntersectionObjects'; 12 | export { IntersectValueOf } from './IntersectValueOf'; 13 | export { Jsonified } from './Jsonified'; 14 | export { Keyed } from './Keyed'; 15 | export { KeyedSafe } from './KeyedSafe'; 16 | export { LiteralPropNames } from './LiteralPropNames'; 17 | export { LiteralProps } from './LiteralProps'; 18 | export { MatchingPropNames } from './MatchingPropNames'; 19 | export { MatchingProps } from './MatchingProps'; 20 | export { Mutable } from './Mutable'; 21 | export { NonFunctionPropNames } from './NonFunctionPropNames'; 22 | export { NonFunctionProps } from './NonFunctionProps'; 23 | export { NonMatchingPropNames } from './NonMatchingPropNames'; 24 | export { NonMatchingProps } from './NonMatchingProps'; 25 | export { ObjectHasElem } from './ObjectHasElem'; 26 | export { ObjectHasKey } from './ObjectHasKey'; 27 | export { ObjectHasKeySafe } from './ObjectHasKeySafe'; 28 | export { ObjectHasNumberIndex } from './ObjectHasNumberIndex'; 29 | export { ObjectHasStringIndex } from './ObjectHasStringIndex'; 30 | export { ObjectNumberKeys } from './ObjectNumberKeys'; 31 | export { ObjectProp } from './ObjectProp'; 32 | export { ObjectValsToUnion } from './ObjectValsToUnion'; 33 | export { Omit } from './Omit'; 34 | export { OptionalPropNames } from './OptionalPropNames'; 35 | export { OptionalProps } from './OptionalProps'; 36 | export { Overwrite } from './Overwrite'; 37 | export { Prototype } from './Prototype'; 38 | export { PrototypeHas } from './PrototypeHas'; 39 | export { PrototypeMethods } from './PrototypeMethods'; 40 | export { RequiredPropNames } from './RequiredPropNames'; 41 | export { RequiredProps } from './RequiredProps'; 42 | export { Simplify } from './Simplify'; 43 | export { Spread } from './Spread'; 44 | export { SpreadProps } from './SpreadProps'; 45 | export { StripIndex } from './StripIndex'; 46 | export { Swap } from './Swap'; 47 | 48 | /** 49 | * Type functions to operate on object types. 50 | * @preferred 51 | */ 52 | 53 | 54 | /** 55 | * Check the length (number of keys) of a given heterogeneous object type. 56 | * Doable given `UnionLength` or (object iteration + `Inc`). 57 | */ 58 | // export type ObjectLength = ... 59 | 60 | // types not possible yet: 61 | // `ObjectSymbolKeys`: a `Symbol` variant of `keyof`. no clue how to go about this unless by checking a whitelisted set such as those found in standard library prototype. this feels sorta useless though. 62 | // `map` over heterogeneous objects: probably just needs `ReturnType`. 63 | // object iteration: useful for e.g. `ObjectToArray`. This could enable union iteration, or the other way around. 64 | // One strategy that comes to mind relies on converting keys to tuple (given UnionToArray) then using array iteration. 65 | -------------------------------------------------------------------------------- /src/ramda/ApplyFns.ts: -------------------------------------------------------------------------------- 1 | // type ApplyFns any>, V> = { 2 | // '1': Fs['length'] extends 0 ? V : ApplyFns, Fs[0](V)> 3 | // }[V extends number ? '1' : '1']; 4 | -------------------------------------------------------------------------------- /src/ramda/Compose.ts: -------------------------------------------------------------------------------- 1 | // type Compose any>> = Pipe>; 2 | -------------------------------------------------------------------------------- /src/ramda/Curried.ts: -------------------------------------------------------------------------------- 1 | // // robust alternative that takes into account return values dependent on input params, needs #5453 + #6606 2 | // function curry(fn: F): Curried; 3 | // type Curried< 4 | // F extends (...args: ArgsAsked) => any, 5 | // ArgsAsked extends any[] = ArgsAsked, 6 | // ArgsPrevious = [] 7 | // > = < 8 | // ArgsGiven extends any[] = ArgsGiven, 9 | // ArgsAll extends [...ArgsPrevious, ...ArgsGiven] 10 | // = [...ArgsPrevious, ...ArgsGiven] 11 | // >(...args: ArgsGiven) => 12 | // If< 13 | // TupleHasIndex>, 14 | // F(...[...ArgsPrevious, ...ArgsGiven]), // #6606 15 | // Curried 16 | // >; 17 | -------------------------------------------------------------------------------- /src/ramda/FromPairsFn.ts: -------------------------------------------------------------------------------- 1 | import { List } from '../util/List'; 2 | import { TupleHasIndex } from '../array/TupleHasIndex'; 3 | import { Spread } from '../object/Spread'; 4 | import { Inc } from '../number/Inc'; 5 | 6 | /** 7 | * Creates a new object from a list key-value pairs. 8 | * If a key appears in multiple pairs, the rightmost pair is included in the object. 9 | * @see http://ramdajs.com/docs/#fromPairs 10 | */ 11 | export type FromPairsFn, I extends number = 0, T = {}> = 12 | { 1: FromPairsFn>, 0: T }[TupleHasIndex]; 13 | -------------------------------------------------------------------------------- /src/ramda/MapFn.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * `Array.prototype.map` type-safe for tuples. 3 | * @see http://ramdajs.com/docs/#map 4 | */ 5 | // export type MapFn< 6 | // F extends (v: T) => any, 7 | // Tpl extends T[], 8 | // T, 9 | // I extends number = 0, 10 | // Acc = [] 11 | // > = { 1: MapFn; 0: Acc; }[TupleHasIndex]; 12 | // // ^ needs #5453 13 | // export declare function mapTuple any, Tpl extends T[], T>(f: F, tpl: Tpl): MapFn; 14 | // // ^ needs #6606 15 | -------------------------------------------------------------------------------- /src/ramda/MergeAllFn.ts: -------------------------------------------------------------------------------- 1 | import { List } from '../util/List'; 2 | import { Obj } from '../util/Obj'; 3 | import { TupleHasIndex } from '../array/TupleHasIndex'; 4 | import { Spread } from '../object/Spread'; 5 | import { Inc } from '../number/Inc'; 6 | 7 | /** 8 | * Merges a list of objects together into one object. 9 | * @see http://ramdajs.com/docs/#mergeAll 10 | */ 11 | export type MergeAllFn>, I extends number = 0, T = {}> = 12 | { 1: MergeAllFn>, 0: T }[TupleHasIndex]; 13 | -------------------------------------------------------------------------------- /src/ramda/PathFn.ts: -------------------------------------------------------------------------------- 1 | import { TupleHasIndex } from '../array/TupleHasIndex'; 2 | import { Inc } from '../number/Inc'; 3 | 4 | /** 5 | * Retrieve the value at a given path. 6 | * @see http://ramdajs.com/docs/#path 7 | */ 8 | export type PathFn, I extends number = 0> = 9 | { 1: PathFn, 0: T }[TupleHasIndex]; 10 | // export declare function path>(obj: T, path: R): PathFn; 11 | -------------------------------------------------------------------------------- /src/ramda/PathOrFn.ts: -------------------------------------------------------------------------------- 1 | import { If } from '../util/If'; 2 | import { List } from '../util/List'; 3 | import { TupleHasIndex } from '../array/TupleHasIndex'; 4 | import { HasKey } from '../object/HasKey'; 5 | import { Inc } from '../number/Inc'; 6 | 7 | /** 8 | * If the given, non-null object has a value at the given path, returns the value at that path. 9 | * Otherwise returns the provided default value. 10 | * @see http://ramdajs.com/docs/#pathOr 11 | */ 12 | export type PathOrFn, I extends number = 0> = 13 | { 1: If, PathOrFn, Def>, 0: T }[TupleHasIndex]; 14 | -------------------------------------------------------------------------------- /src/ramda/Pipe.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Performs left-to-right function composition. 3 | * @see http://ramdajs.com/docs/#pipe 4 | */ 5 | // type Pipe any>, F = Fs[0], Args = Arguments> = Fn, F(...Args)>>; 6 | // // ^ todo: use generics so as to plug in not the static `Args` but base return value on the actual input types 7 | -------------------------------------------------------------------------------- /src/ramda/ZipObjectFn.ts: -------------------------------------------------------------------------------- 1 | import { List } from '../util/List'; 2 | import { TupleHasIndex } from '../array/TupleHasIndex'; 3 | import { Spread } from '../object/Spread'; 4 | import { Inc } from '../number/Inc'; 5 | 6 | /** 7 | * Creates a new object out of a list of keys and a list of values. 8 | * @see http://ramdajs.com/docs/#zipObj 9 | */ 10 | export type ZipObjectFn, R2 extends List, I extends number = 0, T = {}> = 11 | { 1: ZipObjectFn>, 0: T }[TupleHasIndex]; 12 | -------------------------------------------------------------------------------- /src/ramda/bind.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Creates a function that is bound to a context. 3 | * @see http://ramdajs.com/docs/#bind 4 | */ 5 | // // bind, needs #5453: 6 | // interface Function { 7 | // bind< 8 | // F extends (this: T, ...args: ArgsAsked) => R, 9 | // ArgsAsked extends any[], 10 | // R extends any, 11 | // T, 12 | // Args extends any[], // tie to ArgsAsked 13 | // Left extends any[] = DifferenceTuples, 14 | // EnsureArgsMatchAsked extends 0 = ((v: Args) => 0)(TupleFrom>) 15 | // // ^ workaround to ensure we can tie `Args` to both the actual input params as well as to the desired params. it'd throw if the condition is not met. 16 | // >( 17 | // this: F, 18 | // thisObject: T, 19 | // ...args: Args 20 | // ): (this: any, ...rest: Left) => R; 21 | // // ^ `R` alt. to calc return type based on input (needs #6606): `F(this: T, ...[...Args, ...Left])` 22 | // } 23 | -------------------------------------------------------------------------------- /src/ramda/curry.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns a curried equivalent of the provided function. 3 | * @see http://ramdajs.com/docs/#curry 4 | */ 5 | // // poor man's version, using a given return value rather than using `typeof` based on the given argument types: 6 | // function curry(fn: (...args: Args) => Ret): Curried; 7 | // type Curried< 8 | // ArgsAsked, 9 | // Ret, 10 | // ArgsPrevious = [] // if we can't have empty tuple I guess any[] might also destructures to nothing; that might do. 11 | // > = < 12 | // ArgsGiven extends any[] = ArgsGiven, 13 | // ArgsAll extends [...ArgsPrevious, ...ArgsGiven] 14 | // = [...ArgsPrevious, ...ArgsGiven] 15 | // >(...args: ArgsGiven) => 16 | // If< 17 | // TupleHasIndex>, 18 | // Ret, 19 | // Curried 20 | // >; 21 | -------------------------------------------------------------------------------- /src/ramda/index.ts: -------------------------------------------------------------------------------- 1 | // export { ApplyFns } from './ApplyFns'; 2 | // export { bind } from './bind'; 3 | // export { Compose } from './Compose'; 4 | // export { Curried } from './Curried'; 5 | // export { curry } from './curry'; 6 | export { FromPairsFn } from './FromPairsFn'; 7 | // export { MapFn } from './MapFn'; 8 | export { MergeAllFn } from './MergeAllFn'; 9 | export { PathFn } from './PathFn'; 10 | export { PathOrFn } from './PathOrFn'; 11 | // export { Pipe } from './Pipe'; 12 | export { ZipObjectFn } from './ZipObjectFn'; 13 | 14 | /** 15 | * Ramda functions redone with iteration. 16 | * @see https://github.com/Microsoft/TypeScript/issues/12512 17 | * @preferred 18 | */ 19 | 20 | // future: 21 | 22 | // `reduce`: needs `ReturnType` (#6606) for its dynamic reducer functions. see #12512 for Ramda functions that need this. 23 | -------------------------------------------------------------------------------- /src/tuple/AppendList.ts: -------------------------------------------------------------------------------- 1 | import { List } from '../util/List'; 2 | import { NumberToString } from '../cast/NumberToString'; 3 | import { Spread } from '../object/Spread'; 4 | import { LengthList } from './LengthList'; 5 | import { Inc } from '../number/Inc'; 6 | 7 | /** 8 | * Append a value (type) to a numerically indexed type with explicit `length`, e.g. tuple. Returns a numerical object type. 9 | */ 10 | export type AppendList< 11 | R extends List, 12 | T, 13 | Len extends number = LengthList 14 | > = Spread; 15 | -------------------------------------------------------------------------------- /src/tuple/ConcatLists.ts: -------------------------------------------------------------------------------- 1 | import { List } from '../util/List'; 2 | import { Spread } from '../object/Spread'; 3 | import { Add } from '../number/Add'; 4 | import { IncIndex } from './IncIndex'; 5 | 6 | /** 7 | * Append two numerically indexed types with explicit `length`, e.g. tuple types. Returns a numerical object type. 8 | */ 9 | export type ConcatLists, B extends List> = 10 | Spread, { length: Add }>; 11 | -------------------------------------------------------------------------------- /src/tuple/DecIndex.ts: -------------------------------------------------------------------------------- 1 | import { List } from '../util/List'; 2 | import { Inc } from '../number/Inc'; 3 | import { Subtract } from '../number/Subtract'; 4 | import { ObjectHasKey } from '../object/ObjectHasKey'; 5 | import { NumberToString } from '../cast/NumberToString'; 6 | 7 | /** 8 | * Decrease the indexes on a numerically indexed object by a given amount. 9 | */ 10 | export type DecIndex, N extends number, I extends number = R[0], Acc = { length: R['length'] }> = 11 | { 0: Acc, 1: DecIndex]]: R[I] }> }[ObjectHasKey]; 12 | -------------------------------------------------------------------------------- /src/tuple/DifferenceLists.ts: -------------------------------------------------------------------------------- 1 | import { List } from '../util/List'; 2 | import { ListFrom } from '../array/ListFrom'; 3 | import { LengthList } from './LengthList'; 4 | 5 | /** 6 | * Filter a tuple-like type by stripping out any indices used in a second tuple-like. 7 | */ 8 | export type DifferenceLists< 9 | Big extends List, 10 | Small extends List 11 | > = ListFrom>; 12 | -------------------------------------------------------------------------------- /src/tuple/IncIndex.ts: -------------------------------------------------------------------------------- 1 | import { List } from '../util/List'; 2 | import { Inc } from '../number/Inc'; 3 | import { Add } from '../number/Add'; 4 | import { NumberToString } from '../cast/NumberToString'; 5 | import { ObjectHasKey } from '../object/ObjectHasKey'; 6 | 7 | /** 8 | * Increase the indexes on a numerically indexed object by a given amount. 9 | */ 10 | // export type IncIndex, N extends number, I extends number = 0 /*FirstIndex*/, Acc = { length: R['length'] }> = 11 | // { 0: Acc, 1: IncIndex]]: R[I] }> }[ObjectHasKey]; 12 | -------------------------------------------------------------------------------- /src/tuple/LengthList.ts: -------------------------------------------------------------------------------- 1 | import { List } from '../util/List'; 2 | 3 | /** 4 | * Returns the length of a numerically indexed type with explicit `length`, e.g. tuple. 5 | */ 6 | export type LengthList> = R['length']; 7 | -------------------------------------------------------------------------------- /src/tuple/ListTail.ts: -------------------------------------------------------------------------------- 1 | import { List } from '../util/List'; 2 | import { ListFrom } from '../array/ListFrom'; 3 | 4 | /** 5 | * Return the subset of a tuple-like type containing all but the first element. 6 | */ 7 | export type ListTail> = ListFrom; 8 | -------------------------------------------------------------------------------- /src/tuple/Prepend.ts: -------------------------------------------------------------------------------- 1 | import { List } from '../util/List'; 2 | import { IncIndex } from './IncIndex'; 3 | /** 4 | * Prepend an element to a tuple-like type, returning a numerical object. 5 | * Presumes the list is already zero-indexed, otherwise needs `ZeroIndex`. 6 | */ 7 | export type Prepend< 8 | R extends List, 9 | T 10 | > = { 0: T } & IncIndex; 11 | -------------------------------------------------------------------------------- /src/tuple/ReverseList.ts: -------------------------------------------------------------------------------- 1 | import { List } from '../util/List'; 2 | import { LengthList } from './LengthList'; 3 | import { Inc } from '../number/Inc'; 4 | import { Dec } from '../number/Dec'; 5 | import { Spread } from '../object/Spread'; 6 | import { TupleHasIndex } from '../array/TupleHasIndex'; 7 | import { NumberToString } from '../cast/NumberToString'; 8 | 9 | /** 10 | * Reverse a numerically indexed type with explicit `length`, e.g. tuple. 11 | * Takes an ArrayLike, outputs a list with known length as an object type 12 | * with numerical keys. 13 | */ 14 | export type ReverseList< 15 | R extends List, 16 | I extends number = 0, 17 | J extends number = LengthList, 18 | Acc extends List = { length: number } 19 | > = { 0: Spread, 1: ReverseList }[TupleHasIndex]; 20 | -------------------------------------------------------------------------------- /src/tuple/Unshift.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns the given tuple/array with the item type prepended to it 3 | */ 4 | type Unshift = 5 | ((first: Item, ...rest: List) => any) extends ((...list: infer R) => any) ? R : never; 6 | -------------------------------------------------------------------------------- /src/tuple/ZeroIndex.ts: -------------------------------------------------------------------------------- 1 | import { List } from '../util/List'; 2 | import { If } from '../util/If'; 3 | import { NumberToString } from '../cast/NumberToString'; 4 | import { ObjectHasKey } from '../object/ObjectHasKey'; 5 | import { DecIndex } from './DecIndex'; 6 | 7 | /** 8 | * Decrease the indexes on a numerically indexed object such an amount as 9 | * to lower the first one to `0`. 10 | */ 11 | export type ZeroIndex, I extends number = R[0]> = If, R, DecIndex>; 12 | -------------------------------------------------------------------------------- /src/tuple/index.ts: -------------------------------------------------------------------------------- 1 | export { AppendList } from './AppendList'; 2 | export { ConcatLists } from './ConcatLists'; 3 | export { DecIndex } from './DecIndex'; 4 | export { DifferenceLists } from './DifferenceLists'; 5 | export { IncIndex } from './IncIndex'; 6 | export { LengthList } from './LengthList'; 7 | export { ListTail } from './ListTail'; 8 | export { Prepend } from './Prepend'; 9 | export { ReverseList } from './ReverseList'; 10 | export { ZeroIndex } from './ZeroIndex'; 11 | 12 | /** 13 | * type operations for 'lists' -- numerically-indexed types (tuple/object) with explicit `length`. 14 | * outputs are not tuple types but similar 'list' objects, because we can't manipulate tuples yet. 15 | * 16 | * Examples: 17 | * - `[number, string]` (tuple: fixed-length array) 18 | * - `{ 0: number, 1: string, length: 2 }` (`ArrayLike` with known `length`, which includes tuples) 19 | * 20 | * @preferred 21 | */ 22 | -------------------------------------------------------------------------------- /src/type/Awaited.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Unwrap a `Promise` to obtain its return value. 3 | * @see https://github.com/Microsoft/TypeScript/pull/21613 4 | */ 5 | export type Awaited = { 6 | '1': T extends { then(onfulfilled: (value: infer U) => any): any; } ? Awaited : T; 7 | }[T extends number ? '1' : '1']; 8 | -------------------------------------------------------------------------------- /src/type/Const.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Return the first of two types, aka the kestrel combinator. 3 | * @see https://hackage.haskell.org/package/data-aviary-0.4.0/docs/Data-Aviary-Birds.html 4 | */ 5 | export type Const = A; 6 | -------------------------------------------------------------------------------- /src/type/DiscriminateUnion.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Get the constituent of a tagged union given the value of the discriminant. 3 | * @see https://github.com/Microsoft/TypeScript/pull/21316#issuecomment-364982638 4 | */ 5 | export type DiscriminateUnion< 6 | Union, 7 | TagKey extends keyof Union, 8 | TagValue extends Union[TagKey] 9 | > = Union extends Record ? Union : never; 10 | -------------------------------------------------------------------------------- /src/type/Flatten.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Flatten a structure of nested tuples/arrays into a flat element type. 3 | */ 4 | export type Flatten = { 5 | '1': Flatten ? U : T>; 6 | }[T extends number ? '1' : '1']; 7 | -------------------------------------------------------------------------------- /src/type/Id.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * The identity type. Probably not useful until unapplied types become a thing. 3 | */ 4 | export type Id = T; 5 | -------------------------------------------------------------------------------- /src/type/InstanceOf.ts: -------------------------------------------------------------------------------- 1 | import { Not } from '../boolean/Not'; 2 | import { And } from '../boolean/And'; 3 | import { Matches } from './Matches'; 4 | 5 | /** 6 | * Check if a type is an instance of another, that is, matches it but is not equal (`<`). 7 | */ 8 | export type InstanceOf = And, Not>>; 9 | -------------------------------------------------------------------------------- /src/type/Matches.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Check if a type matches another (`<=`). 3 | */ 4 | export type Matches = V extends T ? '1' : '0'; 5 | -------------------------------------------------------------------------------- /src/type/PrototypeOf.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Get the prototype (-> methods) of a type. 3 | * `Partial` helps for e.g. tuple types if not object types, 4 | * though `Symbol`-based keys get killed. 5 | */ 6 | // export type PrototypeOf = ... 7 | -------------------------------------------------------------------------------- /src/type/TypesEqual.ts: -------------------------------------------------------------------------------- 1 | import { And } from '../boolean/And'; 2 | import { Matches } from './Matches'; 3 | 4 | /** 5 | * Check if two types are equal (`==`), i.e. match both ways. 6 | */ 7 | export type TypesEqual = And, Matches>; 8 | -------------------------------------------------------------------------------- /src/type/Widen.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Widen scalar types from literals to their parent types. 3 | */ 4 | export type Widen = 5 | T extends boolean ? boolean : 6 | T extends number ? number : 7 | T extends string ? string : 8 | T; 9 | -------------------------------------------------------------------------------- /src/type/Xor.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Get the disjoint union of two types, yielding `never` for types satisfying neither/both. 3 | * @see https://github.com/Microsoft/TypeScript/pull/21316#issuecomment-360862303 4 | */ 5 | export type Xor = T extends A ? (T extends B ? never : T) : (T extends B ? T : never); 6 | -------------------------------------------------------------------------------- /src/type/index.ts: -------------------------------------------------------------------------------- 1 | export { Awaited } from './Awaited'; 2 | export { Const } from './Const'; 3 | export { DiscriminateUnion } from './DiscriminateUnion'; 4 | export { Flatten } from './Flatten'; 5 | export { Id } from './Id'; 6 | export { InstanceOf } from './InstanceOf'; 7 | export { Matches } from './Matches'; 8 | // export { PrototypeOf } from './PrototypeOf'; 9 | export { TypesEqual } from './TypesEqual'; 10 | export { Widen } from './Widen'; 11 | export { Xor } from './Xor'; 12 | 13 | /** 14 | * Type functions related to types and type checks in general. 15 | * @preferred 16 | */ 17 | 18 | // export type Lambda = any; 19 | // export type TypeMap = Pick[Keys]; 20 | // // nope, no type lambdas -- can't have unapplied types 21 | -------------------------------------------------------------------------------- /src/union/IsUnion.ts: -------------------------------------------------------------------------------- 1 | import { UnionContained } from './UnionContained'; 2 | 3 | /** 4 | * Check whether a type is a union (of string literals). 5 | */ 6 | export type IsUnion = 7 | [T] extends [infer U] ? 8 | U extends any ? 9 | [T] extends [U] ? N : Y 10 | : never 11 | : never; 12 | -------------------------------------------------------------------------------- /src/union/UnionContained.ts: -------------------------------------------------------------------------------- 1 | import { Obj } from '../util/Obj'; 2 | import { DefinitelyYes } from '../boolean/DefinitelyYes'; 3 | 4 | /** 5 | * Check if a union is wholly contained in another one. 6 | * Deprecated, ditch for `Matches`. 7 | * @deprecated 8 | */ 9 | export type UnionContained = DefinitelyYes<({ [P in U]: '1' } & Obj<'0'>)[T | U]>; 10 | -------------------------------------------------------------------------------- /src/union/UnionEmpty.ts: -------------------------------------------------------------------------------- 1 | import { And } from '../boolean/And'; 2 | import { UnionContained } from './UnionContained'; 3 | 4 | /** 5 | * Check if a union is empty, that is, if a type is `never`. 6 | */ 7 | export type UnionEmpty = And, UnionContained>; 8 | -------------------------------------------------------------------------------- /src/union/UnionHasKey.ts: -------------------------------------------------------------------------------- 1 | import { Obj } from '../util/Obj'; 2 | 3 | /** 4 | * Check if a union contains a given string literal. 5 | * Deprecated, ditch for `Matches`. 6 | * @deprecated 7 | */ 8 | export type UnionHasKey = ({[S in Union]: '1' } & Obj<'0'>)[K]; 9 | -------------------------------------------------------------------------------- /src/union/UnionToIntersection.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * src: https://stackoverflow.com/questions/50374908/transform-union-type-to-intersection-type 3 | */ 4 | export type UnionToIntersection = 5 | (U extends any ? (k: U)=>void : never) extends ((k: infer I)=>void) ? I : never; 6 | -------------------------------------------------------------------------------- /src/union/UnionToObject.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Use a union of string literals to make an object using those 3 | * strings as both keys and values. 4 | */ 5 | export type UnionToObject = { [K in Keys]: K }; 6 | -------------------------------------------------------------------------------- /src/union/UnionsOverlap.ts: -------------------------------------------------------------------------------- 1 | import { Not } from '../boolean/Not'; 2 | import { UnionEmpty } from '../union/UnionEmpty'; 3 | 4 | /** 5 | * Check if there is any overlap between two unions of string literals. 6 | */ 7 | export type UnionsOverlap = Not>>; 8 | -------------------------------------------------------------------------------- /src/union/index.ts: -------------------------------------------------------------------------------- 1 | export { IsUnion } from './IsUnion'; 2 | export { UnionContained } from './UnionContained'; 3 | export { UnionEmpty } from './UnionEmpty'; 4 | export { UnionHasKey } from './UnionHasKey'; 5 | export { UnionsOverlap } from './UnionsOverlap'; 6 | export { UnionToObject } from './UnionToObject'; 7 | 8 | /** 9 | * Type functions to operate on unions. 10 | * Note: all operations here are about unions of string literals. 11 | * I could rename this module to `string`, but it operates on the unions, not the actual strings. 12 | * @preferred 13 | */ 14 | 15 | // todo: 16 | // - a way to access union elements, e.g. going from "a" | "b" | "c" to "a". this could enable union iteration using Diff if they're all string literals, which in turn could enable object iteration. or the other way around. 17 | // - IsUnionType -- solvable today only for unions consisting of known sets of keys, see my Indeterminate; a proper solution could be made using union iteration or a way to access arbitrary / random elements (e.g. with conversion to tuple type) 18 | // - UnionLength: check the length of a union, i.e. how many options it is composed of. 19 | -------------------------------------------------------------------------------- /src/util/Bool.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * A string-based boolean analog. Used in type-level conditionals, 3 | * especially as a way to simultaneously enable recursion. 4 | */ 5 | export type Bool = '0'|'1'; 6 | -------------------------------------------------------------------------------- /src/util/If.ts: -------------------------------------------------------------------------------- 1 | import { Bool } from './Bool'; 2 | 3 | /** 4 | * Type-level equivalent of ternary operator `a ? b : c`. 5 | * Seems good for recursion, but a type can't reference itself in the top layer. 6 | */ 7 | export type If = { 1: Then, 0: Else }[Cond]; 8 | -------------------------------------------------------------------------------- /src/util/Intersection.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * just make an intersection type -- this wrapper helps to beat error 3 | * `Type ... does not satisfy the constraint ...` 4 | */ 5 | export type Intersection = A & B; 6 | -------------------------------------------------------------------------------- /src/util/List.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * shorter `ArrayLike` alias 3 | */ 4 | export type List = ArrayLike; 5 | -------------------------------------------------------------------------------- /src/util/NoInfer.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Use to prevent a usage of type `T` from being inferred in other generics. 3 | * Borrowed from @pelotom's `type-zoo` 4 | * 5 | * Example: 6 | * `declare function assertEqual(actual: T, expected: NoInfer): boolean;` 7 | * 8 | * Type `T` will now only be inferred based on the type of the `actual` param, and 9 | * the `expected` param is required to be assignable to the type of `actual`. 10 | * This allows you to give one particular usage of type `T` full control over how the 11 | * compiler infers type `T`. 12 | * 13 | * @see https://github.com/pelotom/type-zoo/#noinfert 14 | * @see https://github.com/Microsoft/TypeScript/issues/14829#issuecomment-322267089 15 | */ 16 | export type NoInfer = T & { [K in keyof T]: T[K] }; 17 | -------------------------------------------------------------------------------- /src/util/NumObj.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * A shorthand to make numerically indexed object types. 3 | */ 4 | export type NumObj = { [k: number]: T }; 5 | -------------------------------------------------------------------------------- /src/util/Obj.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * A shorthand to make homogeneous object types. 3 | */ 4 | export type Obj = { [k: string]: T }; 5 | -------------------------------------------------------------------------------- /src/util/The.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * inspired by Idris language, an operator to asssert a type 3 | */ 4 | export type The = V; 5 | -------------------------------------------------------------------------------- /src/util/Unknown.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * The type of all values; nothing is known about it a priori 3 | * except that it exists. The same idea as Flow's `mixed` type. 4 | * Borrowed from @pelotom's `type-zoo` 5 | * 6 | * @see https://github.com/pelotom/type-zoo/#unknown 7 | * @see https://github.com/Microsoft/TypeScript/issues/10715 8 | */ 9 | export type Unknown = {} | undefined | null; 10 | -------------------------------------------------------------------------------- /src/util/index.ts: -------------------------------------------------------------------------------- 1 | export { Bool } from './Bool'; 2 | export { If } from './If'; 3 | export { Intersection } from './Intersection'; 4 | export { List } from './List'; 5 | export { NoInfer } from './NoInfer'; 6 | export { NumObj } from './NumObj'; 7 | export { Obj } from './Obj'; 8 | export { The } from './The'; 9 | export { the } from './the'; 10 | export { Unknown } from './Unknown'; 11 | 12 | /** 13 | * General utilities that seemed not to fit in the other modules. 14 | * @preferred 15 | */ 16 | 17 | -------------------------------------------------------------------------------- /src/util/the.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * function version of `The`, useful to test types at compile time 3 | */ 4 | export declare function the(): '1'; 5 | -------------------------------------------------------------------------------- /tests/array.test.ts: -------------------------------------------------------------------------------- 1 | import { tsst, the } from 'tsst-tycho'; 2 | import { Vector, ArrayProp, TupleHasIndex, IsArrayType, AppendNumObj, ConcatNumObjs, Length, TupleProp, 3 | IncIndexNumbObj, ListFrom, ListTo, Reverse, TupleLastElem, TupleLastIndex, IsTuple } from '../src/array'; 4 | import { TupleToObject } from '../src/cast'; 5 | import { NumArr, TestArr } from './fixtures'; 6 | Error.stackTraceLimit = 0; 7 | 8 | describe(`array`, () => { 9 | 10 | describe(`Vector`, () => { 11 | 12 | it(`the<{ 0: number, 1: number, 2: number, length: 3 }, Vector>`, () => { 13 | tsst(() => { 14 | the<{ 0: number, 1: number, 2: number, length: 3 }, Vector>(); 15 | }).expectToCompile(); 16 | }); 17 | 18 | it(`the, { 0: number, 1: number, 2: number, length: 3 } | { 0: string, 1: string, 2: string, length: 3 }>`, () => { 19 | tsst(() => { 20 | the, { 0: number, 1: number, 2: number, length: 3 } | { 0: string, 1: string, 2: string, length: 3 }>(); 21 | }).expectToCompile(); 22 | }); 23 | 24 | it(`the<{ 0: number | string, 1: number | string, 2: number | string, length: 3 }, Vector>`, () => { 25 | tsst(() => { 26 | the<{ 0: number | string, 1: number | string, 2: number | string, length: 3 }, Vector>(); 27 | }).expectToCompile(); 28 | }); 29 | 30 | it(`the<{ 0: number, 1: number, length: 2 } | { 0: number, 1: number, 2: number, length: 3 }, Vector>`, () => { 31 | tsst(() => { 32 | the<{ 0: number, 1: number, length: 2 } | { 0: number, 1: number, 2: number, length: 3 }, Vector>(); 33 | }).expectToCompile(); 34 | }); 35 | 36 | }); 37 | 38 | describe(`ArrayProp`, () => { 39 | 40 | it(`the<0, ArrayProp>>`, () => { 41 | tsst(() => { 42 | the<0, ArrayProp>>(); 43 | }).expectToCompile(); 44 | }); 45 | 46 | it(`the<0 | 1, ArrayProp>>`, () => { 47 | tsst(() => { 48 | the<0 | 1, ArrayProp>>(); 49 | }).expectToCompile(); 50 | }); 51 | 52 | it(`the<0 | 1, ArrayProp | Array<1>>>`, () => { 53 | tsst(() => { 54 | the<0 | 1, ArrayProp | Array<1>>>(); 55 | }).expectToCompile(); 56 | }); 57 | 58 | }); 59 | 60 | describe(`TupleProp`, () => { 61 | 62 | it(`the<0, TupleProp<[0], 0>>`, () => { 63 | tsst(() => { 64 | the<0, TupleProp<[0], 0>>(); 65 | }).expectToCompile(); 66 | }); 67 | 68 | it(`the<0, TupleProp<[0], 1>>`, () => { 69 | tsst(() => { 70 | the<0, TupleProp<[0], 1>>(); 71 | }).expectToCompile(); 72 | }); 73 | 74 | it(`the>`, () => { 75 | tsst(() => { 76 | the>(); 77 | }).expectToCompile(); 78 | }); 79 | 80 | }); 81 | 82 | describe(`TupleHasIndex`, () => { 83 | 84 | it(`the<'1', TupleHasIndex>`, () => { 85 | tsst(() => { 86 | the<'1', TupleHasIndex>(); 87 | }).expectToCompile(); 88 | }); 89 | 90 | it(`the<'0', TupleHasIndex>`, () => { 91 | tsst(() => { 92 | the<'0', TupleHasIndex>(); 93 | }).expectToCompile(); 94 | }); 95 | 96 | it(`the<'0'|'1', TupleHasIndex>`, () => { 97 | tsst(() => { 98 | the<'0'|'1', TupleHasIndex>(); 99 | }).expectToCompile(); 100 | }); 101 | 102 | it(`the<'0'|'1', TupleHasIndex>`, () => { 103 | tsst(() => { 104 | the<'0'|'1', TupleHasIndex>(); 105 | }).expectToCompile(); 106 | }); 107 | 108 | it(`the<'1', TupleHasIndex<{a:1}, 'a'>>`, () => { 109 | tsst(() => { 110 | the<'1', TupleHasIndex<{a:1}, 'a'>>(); 111 | }).expectToFail(); 112 | }); 113 | 114 | it(`the<'0', TupleHasIndex<{a:1}, 'b'>>`, () => { 115 | tsst(() => { 116 | the<'0', TupleHasIndex<{a:1}, 'b'>>(); 117 | }).expectToFail(); 118 | }); 119 | 120 | it(`the<'1', TupleHasIndex<{ 1: "hi" }, 1>>`, () => { 121 | tsst(() => { 122 | the<'1', TupleHasIndex<{ 1: "hi" }, 1>>(); 123 | }).expectToFail(); 124 | }); 125 | 126 | it(`the<'0', TupleHasIndex<{ 1: "hi" }, -1>>`, () => { 127 | tsst(() => { 128 | the<'0', TupleHasIndex<{ 1: "hi" }, -1>>(); 129 | }).expectToFail(); 130 | }); 131 | 132 | // ^ no objects 133 | 134 | }); 135 | 136 | describe(`IsArrayType`, () => { 137 | 138 | it(`the<'1', IsArrayType>`, () => { 139 | tsst(() => { 140 | the<'1', IsArrayType>(); 141 | }).expectToCompile(); 142 | }); 143 | 144 | it(`the<'1', IsArrayType>`, () => { 145 | tsst(() => { 146 | the<'1', IsArrayType>(); 147 | }).expectToCompile(); 148 | }); 149 | 150 | it(`the<'0', IsArrayType<{ length: 2 }>>`, () => { 151 | tsst(() => { 152 | the<'0', IsArrayType<{ length: 2 }>>(); 153 | }).expectToCompile(); 154 | }); 155 | 156 | }); 157 | 158 | describe(`AppendNumObj`, () => { 159 | 160 | it(`the<{ 0: 'a', 1: 'b', 2: 'c' }, AppendNumObj<{ 0: 'a', 1: 'b' }, 'c'>>`, () => { 161 | tsst(() => { 162 | the<{ 0: 'a', 1: 'b', 2: 'c' }, AppendNumObj<{ 0: 'a', 1: 'b' }, 'c'>>(); 163 | }).expectToCompile(); 164 | }); 165 | 166 | }); 167 | 168 | describe(`ConcatNumObjs`, () => { 169 | 170 | it(`the<{ 0: 'a', 1: 'b', 2: 'c', 3: 'd' }, ConcatNumObjs<{ 0: 'a', 1: 'b' }, { 0: 'c', 1: 'd' }>>`, () => { 171 | tsst(() => { 172 | the<{ 0: 'a', 1: 'b', 2: 'c', 3: 'd' }, ConcatNumObjs<{ 0: 'a', 1: 'b' }, { 0: 'c', 1: 'd' }>>(); 173 | }).expectToCompile(); 174 | }); 175 | 176 | // ^ does not terminate 177 | 178 | }); 179 | 180 | describe(`Length`, () => { 181 | 182 | it(`the<3, Length>>`, () => { 183 | tsst(() => { 184 | the<3, Length>>(); 185 | }).expectToCompile(); 186 | }); 187 | 188 | it(`the<3, Length>`, () => { 189 | tsst(() => { 190 | the<3, Length>(); 191 | }).expectToCompile(); 192 | }); 193 | 194 | it(`the<0, Length>`, () => { 195 | tsst(() => { 196 | the<0, Length>(); 197 | }).expectToCompile(); 198 | }); 199 | 200 | it(`the<2, Length<{ 0: 'a', 1: 'b' }>>`, () => { 201 | tsst(() => { 202 | the<2, Length<{ 0: 'a', 1: 'b' }>>(); 203 | }).expectToCompile(); 204 | }); 205 | 206 | it(`the<0|3, Length>`, () => { 207 | tsst(() => { 208 | the<0|3, Length>(); 209 | }).expectToCompile(); 210 | }); 211 | 212 | }); 213 | 214 | describe(`IncIndexNumbObj`, () => { 215 | 216 | it(`the<{ 2: 'a', 3: 'b', length: 2 }, IncIndexNumbObj<{ 0: 'a', 1: 'b' }, 2>>`, () => { 217 | tsst(() => { 218 | the<{ 2: 'a', 3: 'b', length: 2 }, IncIndexNumbObj<{ 0: 'a', 1: 'b' }, 2>>(); 219 | }).expectToCompile(); 220 | }); 221 | 222 | // ^ does not terminate 223 | 224 | }); 225 | 226 | describe(`ListFrom`, () => { 227 | 228 | it(`the<{ 0: 'c', 1: 'd', length: 2 }, ListFrom<{ 0: 'a', 1: 'b', 2: 'c', 3: 'd', length: 4 }, 2>>`, () => { 229 | tsst(() => { 230 | the<{ 0: 'c', 1: 'd', length: 2 }, ListFrom<{ 0: 'a', 1: 'b', 2: 'c', 3: 'd', length: 4 }, 2>>(); 231 | }).expectToCompile(); 232 | }); 233 | 234 | }); 235 | 236 | describe(`ListTo`, () => { 237 | 238 | it(`the<{ 0: 'a', 1: 'b', length: 2 }, ListTo<{ 0: 'a', 1: 'b', 2: 'c', 3: 'd', length: 4 }, 2>>`, () => { 239 | tsst(() => { 240 | the<{ 0: 'a', 1: 'b', length: 2 }, ListTo<{ 0: 'a', 1: 'b', 2: 'c', 3: 'd', length: 4 }, 2>>(); 241 | }).expectToCompile(); 242 | }); 243 | // ^ error: { length: 2; } 244 | 245 | }); 246 | 247 | describe(`Reverse`, () => { 248 | 249 | it(`the<{ 0: 'b', 1: 'a', length: 2 }, Reverse<['a', 'b']>>`, () => { 250 | tsst(() => { 251 | the<{ 0: 'b', 1: 'a', length: 2 }, Reverse<['a', 'b']>>(); 252 | }).expectToCompile(); 253 | }); 254 | 255 | }); 256 | 257 | describe(`TupleLastElem`, () => { 258 | 259 | it(`the<'c', TupleLastElem>`, () => { 260 | tsst(() => { 261 | the<'c', TupleLastElem>(); 262 | }).expectToCompile(); 263 | }); 264 | 265 | }); 266 | 267 | describe(`TupleLastIndex`, () => { 268 | 269 | it(`the<2, TupleLastIndex>`, () => { 270 | tsst(() => { 271 | the<2, TupleLastIndex>(); 272 | }).expectToCompile(); 273 | }); 274 | 275 | it(`the<-1, TupleLastIndex>`, () => { 276 | tsst(() => { 277 | the<-1, TupleLastIndex>(); 278 | }).expectToCompile(); 279 | }); 280 | 281 | }); 282 | 283 | describe(`IsTuple`, () => { 284 | 285 | it(`the<'1', IsTuple<[0]>>`, () => { 286 | tsst(() => { 287 | the<'1', IsTuple<[0]>>(); 288 | }).expectToCompile(); 289 | }); 290 | 291 | it(`the<'0', IsTuple>`, () => { 292 | tsst(() => { 293 | the<'0', IsTuple>(); 294 | }).expectToCompile(); 295 | }); 296 | 297 | }); 298 | 299 | }); 300 | -------------------------------------------------------------------------------- /tests/boolean.test.ts: -------------------------------------------------------------------------------- 1 | import { tsst, the } from 'tsst-tycho'; 2 | import { Bool } from '../src/util'; 3 | import { Not, And, Or, Indeterminate, Determinate, DefinitelyYes, DefinitelyNo, IsTruthy, IsFalsy } from '../src/boolean'; 4 | import { UnionHasKey } from '../src/union'; 5 | 6 | describe(`boolean`, () => { 7 | 8 | describe(`Not`, () => { 9 | 10 | it(`the<'1', Not<'0'>>`, () => { 11 | tsst(() => { 12 | the<'1', Not<'0'>>(); 13 | }).expectToCompile(); 14 | }); 15 | 16 | it(`the<'0', Not<'1'>>`, () => { 17 | tsst(() => { 18 | the<'0', Not<'1'>>(); 19 | }).expectToCompile(); 20 | }); 21 | 22 | xit(`the>`, () => { 23 | tsst(() => { 24 | the>(); 25 | }).expectToCompile(); 26 | }); 27 | 28 | xit(`the<'0', Not<'true'>>`, () => { 29 | tsst(() => { 30 | the<'0', Not<'true'>>(); 31 | }).expectToCompile(); 32 | }); 33 | 34 | xit(`the<'1', Not<'false'>>`, () => { 35 | tsst(() => { 36 | the<'1', Not<'false'>>(); 37 | }).expectToCompile(); 38 | }); 39 | 40 | xit(`the>`, () => { 41 | tsst(() => { 42 | the>(); 43 | }).expectToCompile(); 44 | }); 45 | 46 | it(`the>`, () => { 47 | tsst(() => { 48 | the>(); // any 49 | }).expectToCompile(); 50 | }); 51 | 52 | xit(`the<'0', Not>`, () => { 53 | tsst(() => { 54 | the<'0', Not>(); // any 55 | }).expectToCompile(); 56 | }); 57 | 58 | xit(`the<'1', Not>`, () => { 59 | tsst(() => { 60 | the<'1', Not>(); // any 61 | }).expectToCompile(); 62 | }); 63 | 64 | }); 65 | 66 | describe(`And`, () => { 67 | 68 | it(`the<'1', And<'1', '1'>>`, () => { 69 | tsst(() => { 70 | the<'1', And<'1', '1'>>(); 71 | }).expectToCompile(); 72 | }); 73 | 74 | it(`the<'0', And<'0', '1'>>`, () => { 75 | tsst(() => { 76 | the<'0', And<'0', '1'>>(); 77 | }).expectToCompile(); 78 | }); 79 | 80 | }); 81 | 82 | describe(`Or`, () => { 83 | 84 | it(`the<'1', Or<'1', '0'>>`, () => { 85 | tsst(() => { 86 | the<'1', Or<'1', '0'>>(); 87 | }).expectToCompile(); 88 | }); 89 | 90 | it(`the<'0', Or<'0', '0'>>`, () => { 91 | tsst(() => { 92 | the<'0', Or<'0', '0'>>(); 93 | }).expectToCompile(); 94 | }); 95 | 96 | }); 97 | 98 | describe(`UnionHasKey`, () => { 99 | 100 | it(`the<'1', UnionHasKey>`, () => { 101 | tsst(() => { 102 | the<'1', UnionHasKey>(); 103 | }).expectToCompile(); 104 | }); 105 | 106 | it(`the<'1', UnionHasKey>`, () => { 107 | tsst(() => { 108 | the<'1', UnionHasKey>(); 109 | }).expectToCompile(); 110 | }); 111 | 112 | it(`the<'1', UnionHasKey | UnionHasKey>`, () => { 113 | tsst(() => { 114 | the<'1', UnionHasKey | UnionHasKey>(); 115 | }).expectToCompile(); 116 | }); 117 | 118 | it(`the<'1', And, UnionHasKey>>`, () => { 119 | tsst(() => { 120 | the<'1', And, UnionHasKey>>(); 121 | }).expectToCompile(); 122 | }); 123 | 124 | }); 125 | 126 | describe(`Indeterminate`, () => { 127 | // ^ broke, along with dependents! 128 | // ^ regression in recent TS? 129 | 130 | it(`the<'1', Indeterminate>`, () => { 131 | tsst(() => { 132 | the<'1', Indeterminate>(); 133 | }).expectToCompile(); 134 | }); 135 | 136 | it(`the<'0', Indeterminate<'0'>>`, () => { 137 | tsst(() => { 138 | the<'0', Indeterminate<'0'>>(); 139 | }).expectToCompile(); 140 | }); 141 | 142 | it(`the<'0', Indeterminate<'1'>>`, () => { 143 | tsst(() => { 144 | the<'0', Indeterminate<'1'>>(); 145 | }).expectToCompile(); 146 | }); 147 | 148 | }); 149 | 150 | describe(`Determinate`, () => { 151 | 152 | it(`the<'0', Determinate>`, () => { 153 | tsst(() => { 154 | the<'0', Determinate>(); 155 | }).expectToCompile(); 156 | }); 157 | 158 | it(`the<'1', Determinate<'0'>>`, () => { 159 | tsst(() => { 160 | the<'1', Determinate<'0'>>(); 161 | }).expectToCompile(); 162 | }); 163 | 164 | it(`the<'1', Determinate<'1'>>`, () => { 165 | tsst(() => { 166 | the<'1', Determinate<'1'>>(); 167 | }).expectToCompile(); 168 | }); 169 | 170 | }); 171 | 172 | describe(`DefinitelyYes`, () => { 173 | 174 | it(`the<'0', DefinitelyYes>`, () => { 175 | tsst(() => { 176 | the<'0', DefinitelyYes>(); 177 | }).expectToCompile(); 178 | }); 179 | 180 | it(`the<'0', DefinitelyYes<'0'>>`, () => { 181 | tsst(() => { 182 | the<'0', DefinitelyYes<'0'>>(); 183 | }).expectToCompile(); 184 | }); 185 | 186 | it(`the<'1', DefinitelyYes<'1'>>`, () => { 187 | tsst(() => { 188 | the<'1', DefinitelyYes<'1'>>(); 189 | }).expectToCompile(); 190 | }); 191 | 192 | }); 193 | 194 | describe(`DefinitelyNo`, () => { 195 | 196 | it(`the<'0', DefinitelyNo>`, () => { 197 | tsst(() => { 198 | the<'0', DefinitelyNo>(); 199 | }).expectToCompile(); 200 | }); 201 | 202 | it(`the<'1', DefinitelyNo<'0'>>`, () => { 203 | tsst(() => { 204 | the<'1', DefinitelyNo<'0'>>(); 205 | }).expectToCompile(); 206 | }); 207 | 208 | it(`the<'0', DefinitelyNo<'1'>>`, () => { 209 | tsst(() => { 210 | the<'0', DefinitelyNo<'1'>>(); 211 | }).expectToCompile(); 212 | }); 213 | 214 | }); 215 | 216 | describe(`IsTruthy`, () => { 217 | 218 | it(`the<'1', IsTruthy>`, () => { 219 | tsst(() => { 220 | the<'1', IsTruthy>(); 221 | }).expectToCompile(); 222 | }); 223 | 224 | it(`the<'0', IsTruthy>`, () => { 225 | tsst(() => { 226 | the<'0', IsTruthy>(); 227 | }).expectToCompile(); 228 | }); 229 | 230 | it(`the<'1', IsTruthy<123>>`, () => { 231 | tsst(() => { 232 | the<'1', IsTruthy<123>>(); 233 | }).expectToCompile(); 234 | }); 235 | 236 | it(`the<'0', IsTruthy<0>>`, () => { 237 | tsst(() => { 238 | the<'0', IsTruthy<0>>(); 239 | }).expectToCompile(); 240 | }); 241 | 242 | it(`the, Bool>`, () => { 243 | tsst(() => { 244 | the, Bool>(); 245 | }).expectToCompile(); 246 | }); 247 | 248 | }); 249 | 250 | describe(`IsFalsy`, () => { 251 | 252 | it(`the<'0', IsFalsy>`, () => { 253 | tsst(() => { 254 | the<'0', IsFalsy>(); 255 | }).expectToCompile(); 256 | }); 257 | 258 | it(`the<'1', IsFalsy>`, () => { 259 | tsst(() => { 260 | the<'1', IsFalsy>(); 261 | }).expectToCompile(); 262 | }); 263 | 264 | it(`the<'0', IsFalsy<123>>`, () => { 265 | tsst(() => { 266 | the<'0', IsFalsy<123>>(); 267 | }).expectToCompile(); 268 | }); 269 | 270 | it(`the<'1', IsFalsy<0>>`, () => { 271 | tsst(() => { 272 | the<'1', IsFalsy<0>>(); 273 | }).expectToCompile(); 274 | }); 275 | 276 | it(`the, Bool>`, () => { 277 | tsst(() => { 278 | the, Bool>(); 279 | }).expectToCompile(); 280 | }); 281 | 282 | }); 283 | 284 | }); 285 | -------------------------------------------------------------------------------- /tests/cast.test.ts: -------------------------------------------------------------------------------- 1 | import { tsst, the } from 'tsst-tycho'; 2 | import { NumberToString, StringToNumber, TupleToUnion, TupleIndicesToUnion, 3 | TupleToObject, TupleToList, NumObjToList, ListToNumObj, BoolToString } from '../src/cast'; 4 | import { TestArr } from './fixtures'; 5 | 6 | describe(`cast`, () => { 7 | 8 | describe(`NumberToString`, () => { 9 | 10 | it(`the<'3', NumberToString[3]>`, () => { 11 | tsst(() => { 12 | the<'3', NumberToString[3]>(); 13 | }).expectToCompile(); 14 | }); 15 | 16 | it(`the<'3', NumberToString['3']>`, () => { 17 | tsst(() => { 18 | the<'3', NumberToString['3']>(); 19 | }).expectToCompile(); 20 | }); 21 | 22 | it(`the<'3', NumberToString<3>>`, () => { 23 | tsst(() => { 24 | the<'3', NumberToString<3>>(); 25 | }).expectToFail(); 26 | }); 27 | 28 | it(`the`, () => { 29 | tsst(() => { 30 | the(); 31 | }).expectToCompile(); 32 | }); 33 | 34 | }); 35 | 36 | describe(`StringToNumber`, () => { 37 | 38 | it(`the<3, StringToNumber['3']>`, () => { 39 | tsst(() => { 40 | the<3, StringToNumber['3']>(); 41 | }).expectToCompile(); 42 | }); 43 | 44 | it(`the<3, StringToNumber[3]>`, () => { 45 | tsst(() => { 46 | the<3, StringToNumber[3]>(); 47 | }).expectToCompile(); 48 | }); 49 | 50 | it(`the`, () => { 51 | tsst(() => { 52 | the(); 53 | }).expectToCompile(); 54 | }); 55 | 56 | }); 57 | 58 | describe(`TupleToUnion`, () => { 59 | 60 | it(`the<"a" | "b" | "c", TupleToUnion>`, () => { 61 | tsst(() => { 62 | the<"a" | "b" | "c", TupleToUnion>(); 63 | }).expectToCompile(); 64 | }); 65 | 66 | }); 67 | 68 | describe(`TupleIndicesToUnion`, () => { 69 | 70 | it(`the<0 | 1 | 2, TupleIndicesToUnion>`, () => { 71 | tsst(() => { 72 | the<0 | 1 | 2, TupleIndicesToUnion>(); 73 | }).expectToCompile(); 74 | }); 75 | 76 | }); 77 | 78 | describe(`TupleToObject`, () => { 79 | 80 | it(`the<{ 0: "a"; 1: "b"; 2: "c"; }, TupleToObject>`, () => { 81 | tsst(() => { 82 | the<{ 0: "a"; 1: "b"; 2: "c"; }, TupleToObject>(); 83 | }).expectToCompile(); 84 | }); 85 | 86 | }); 87 | 88 | describe(`TupleToList`, () => { 89 | 90 | it(`the<{ 0: "a"; 1: "b"; 2: "c"; length: 3; }, TupleToList>`, () => { 91 | tsst(() => { 92 | the<{ 0: "a"; 1: "b"; 2: "c"; length: 3; }, TupleToList>(); 93 | }).expectToCompile(); 94 | }); 95 | 96 | }); 97 | 98 | describe(`NumObjToList`, () => { 99 | 100 | it(`the<{ 0: 'a', 1: 'b', length: 2 }, NumObjToList<{ 0: 'a', 1: 'b' }>>`, () => { 101 | tsst(() => { 102 | the<{ 0: 'a', 1: 'b', length: 2 }, NumObjToList<{ 0: 'a', 1: 'b' }>>(); 103 | }).expectToCompile(); 104 | }); 105 | 106 | it(`the<{ 0: 'a', 1: 'b', 2: 'c', length: 3 }, NumObjToList>>`, () => { 107 | tsst(() => { 108 | the<{ 0: 'a', 1: 'b', 2: 'c', length: 3 }, NumObjToList>>(); 109 | }).expectToCompile(); 110 | }); 111 | 112 | }); 113 | 114 | describe(`ListToNumObj`, () => { 115 | 116 | it(`the<{ 0: 'a', 1: 'b' }, ListToNumObj<{ 0: 'a', 1: 'b', length: 2 }>>`, () => { 117 | tsst(() => { 118 | the<{ 0: 'a', 1: 'b' }, ListToNumObj<{ 0: 'a', 1: 'b', length: 2 }>>(); 119 | }).expectToCompile(); 120 | }); 121 | 122 | }); 123 | 124 | describe(`BoolToString`, () => { 125 | 126 | it(`the<'1', BoolToString>`, () => { 127 | tsst(() => { 128 | the<'1', BoolToString>(); 129 | }).expectToCompile(); 130 | }); 131 | 132 | }); 133 | 134 | }); 135 | -------------------------------------------------------------------------------- /tests/comp.test.ts: -------------------------------------------------------------------------------- 1 | import { tsst, the } from 'tsst-tycho'; 2 | import { StringsEqual, NumbersEqual, Gt, Lt, Gte, Lte, Max, Min } from '../src/comp'; 3 | 4 | describe(`comp`, () => { 5 | 6 | describe(`StringsEqual`, () => { 7 | 8 | it(`the<'1', StringsEqual<'a', 'a'>>`, () => { 9 | tsst(() => { 10 | the<'1', StringsEqual<'a', 'a'>>(); 11 | }).expectToCompile(); 12 | }); 13 | 14 | it(`the<'0', StringsEqual<'a', 'b'>>`, () => { 15 | tsst(() => { 16 | the<'0', StringsEqual<'a', 'b'>>(); 17 | }).expectToCompile(); 18 | }); 19 | 20 | }); 21 | 22 | describe(`NumbersEqual`, () => { 23 | 24 | it(`the<'1', NumbersEqual<123, 123>>`, () => { 25 | tsst(() => { 26 | the<'1', NumbersEqual<123, 123>>(); 27 | }).expectToCompile(); 28 | }); 29 | 30 | it(`the<'0', NumbersEqual<123, 456>>`, () => { 31 | tsst(() => { 32 | the<'0', NumbersEqual<123, 456>>(); 33 | }).expectToCompile(); 34 | }); 35 | 36 | it(`the<'1', NumbersEqual<123, '123'>>`, () => { 37 | tsst(() => { 38 | the<'1', NumbersEqual<123, '123'>>(); // numbers only 39 | }).expectToFail(); 40 | }); 41 | 42 | it(`the<'1', NumbersEqual<'123', 123>>`, () => { 43 | tsst(() => { 44 | the<'1', NumbersEqual<'123', 123>>(); // numbers only 45 | }).expectToFail(); 46 | }); 47 | 48 | it(`the<'0', NumbersEqual<0, 5>>`, () => { 49 | tsst(() => { 50 | the<'0', NumbersEqual<0, 5>>(); 51 | }).expectToCompile(); 52 | }); 53 | 54 | it(`the<'0', NumbersEqual<5, 0>>`, () => { 55 | tsst(() => { 56 | the<'0', NumbersEqual<5, 0>>(); 57 | }).expectToCompile(); 58 | }); 59 | 60 | }); 61 | 62 | describe(`Gt`, () => { 63 | 64 | it(`the<'1', Gt<3, 2>>`, () => { 65 | tsst(() => { 66 | the<'1', Gt<3, 2>>(); 67 | }).expectToCompile(); 68 | }); 69 | 70 | it(`the<'0', Gt<2, 3>>`, () => { 71 | tsst(() => { 72 | the<'0', Gt<2, 3>>(); 73 | }).expectToCompile(); 74 | }); 75 | 76 | it(`the<'0', Gt<3, 3>>`, () => { 77 | tsst(() => { 78 | the<'0', Gt<3, 3>>(); 79 | }).expectToCompile(); 80 | }); 81 | 82 | }); 83 | 84 | describe(`Lt`, () => { 85 | 86 | it(`the<'0', Lt<3, 2>>`, () => { 87 | tsst(() => { 88 | the<'0', Lt<3, 2>>(); 89 | }).expectToCompile(); 90 | }); 91 | 92 | it(`the<'1', Lt<2, 3>>`, () => { 93 | tsst(() => { 94 | the<'1', Lt<2, 3>>(); 95 | }).expectToCompile(); 96 | }); 97 | 98 | it(`the<'0', Lt<3, 3>>`, () => { 99 | tsst(() => { 100 | the<'0', Lt<3, 3>>(); 101 | }).expectToCompile(); 102 | }); 103 | 104 | }); 105 | 106 | describe(`Gte`, () => { 107 | 108 | it(`the<'1', Gte<3, 2>>`, () => { 109 | tsst(() => { 110 | the<'1', Gte<3, 2>>(); 111 | }).expectToCompile(); 112 | }); 113 | 114 | it(`the<'0', Gte<2, 3>>`, () => { 115 | tsst(() => { 116 | the<'0', Gte<2, 3>>(); 117 | }).expectToCompile(); 118 | }); 119 | 120 | it(`the<'1', Gte<3, 3>>`, () => { 121 | tsst(() => { 122 | the<'1', Gte<3, 3>>(); 123 | }).expectToCompile(); 124 | }); 125 | 126 | }); 127 | 128 | describe(`Lte`, () => { 129 | 130 | it(`the<'0', Lte<3, 2>>`, () => { 131 | tsst(() => { 132 | the<'0', Lte<3, 2>>(); 133 | }).expectToCompile(); 134 | }); 135 | 136 | it(`the<'1', Lte<2, 3>>`, () => { 137 | tsst(() => { 138 | the<'1', Lte<2, 3>>(); 139 | }).expectToCompile(); 140 | }); 141 | 142 | it(`the<'1', Lte<3, 3>>`, () => { 143 | tsst(() => { 144 | the<'1', Lte<3, 3>>(); 145 | }).expectToCompile(); 146 | }); 147 | 148 | }); 149 | 150 | describe(`Max`, () => { 151 | 152 | it(`the<6, Max<3, 6>>`, () => { 153 | tsst(() => { 154 | the<6, Max<3, 6>>(); 155 | }).expectToCompile(); 156 | }); 157 | 158 | it(`the<5, Max<5, 2>>`, () => { 159 | tsst(() => { 160 | the<5, Max<5, 2>>(); 161 | }).expectToCompile(); 162 | }); 163 | 164 | }); 165 | 166 | describe(`Min`, () => { 167 | 168 | it(`the<3, Min<3, 6>>`, () => { 169 | tsst(() => { 170 | the<3, Min<3, 6>>(); 171 | }).expectToCompile(); 172 | }); 173 | 174 | it(`the<2, Min<5, 2>>`, () => { 175 | tsst(() => { 176 | the<2, Min<5, 2>>(); 177 | }).expectToCompile(); 178 | }); 179 | 180 | }); 181 | 182 | }); 183 | -------------------------------------------------------------------------------- /tests/crap.ts: -------------------------------------------------------------------------------- 1 | import { tsst, the } from 'tsst-tycho'; 2 | import { List } from '../src/util'; 3 | import { Simplify } from '../src/object'; 4 | import { TupleToObject } from '../src/cast'; 5 | 6 | /* 7 | // regex find-replace pair to turn `the` statements into `tsst` tests: 8 | ^((the<.*>\(\));?.*) 9 | it(`$2`, () => {\n tsst(() => {\n $1\n }).expectToCompile();\n });\n 10 | */ 11 | 12 | // test interplay types 13 | type asdfInt = ({ a: 1 } & { c: 4 } & { b: 2, a: string } & { [k: string]: 3 })['a'] 14 | // objects considered merged, indexes ignored but real results intersect'd 15 | type asdfUnn = ({ a: 1 } /*| { c: 4 }*/ | { b: 2, a: string } /*| { [k: string]: 3 }*/)['a']; 16 | // ^ union of results; each object must *explicitly* contain key, no indexes 17 | type afdsfUnn = { a: 1, b: 2, c: 3 }['a' | 'b' /*| 'd'*/]; 18 | // ^ union of results, keys must all be contained 19 | // type afdsfUBl = { a: 1, b: 2, c: 3 }['a' | true]; 20 | // // ^ union with bad keys, also errors 21 | type afdsfInt = { a: 1, b: 2, c: 3 }['a' /*& 'b'*/]; // impossible key, error 22 | 23 | // interaction `?` 24 | the<{a?:1}, Simplify<{a?:1}>>(); 25 | the<1 | undefined, {a?:1}['a']>(); 26 | the<'a', keyof {a?:1}>(); 27 | 28 | // #16072 29 | declare function comp(f: (x: A) => B, g: (x: B) => C): (x: A) => C 30 | const wrapper = comp(x => [x], y => ({ p: y })); // (x: {}) => { p: {}[] } 31 | 32 | type ArrProto> = Simplify & { 33 | [Symbol.iterator]: () => IterableIterator, 34 | [Symbol.unscopables]: () => { copyWithin: boolean; entries: boolean; fill: boolean; find: boolean; findIndex: boolean; keys: boolean; values: boolean; } 35 | } & { [i: number]: T[-1] }; 36 | // ^ error outside of Playground: can't find Symbol 37 | 38 | // #6229 39 | const foo: [1, "a"] = [1, "a"]; // no cast with #16389 40 | var t3: TupleToObject = foo; 41 | // t3[2]; // error: Element implicitly has an 'any' type because type 'Pick<{ 0: 1; } & { 1: "a"; }, "1" | "0">' has no index signature. 42 | var t1: [number, string] = >[1, "a"]; 43 | // ^ ok 44 | // v make either of these error: 45 | var t5a: [number, string] = [1, "a", "b"]; 46 | var t5b: [number, string] = > [1, "a", "b"]; 47 | var t5c: TupleToObject<[number, string]> = [1, "a", "b"]; 48 | var t5d: TupleToObject<[number, string]> = > [1, "a", "b"]; 49 | var t5e: TupleToObject<[number, string]> = > [1, "a", "b"]; 50 | 51 | // type neverAccessTest = {a:1}[never] 52 | 53 | // check how type moving works: 54 | // no match: messed up intersection 55 | the(); 56 | // match: take it 57 | the(); 58 | // match or any: any, type-checking stops 59 | the<'foo', string & (string | any)>(); 60 | // miss or any: any, type-checking stops 61 | the<'bar', string & (number | any)>(); 62 | // super-type: stick with sub-type (& super) 63 | the<'a' /* & super*/, 'a' & (string | never)>(); 64 | // sub-type: narrow down 65 | the<'a', string & ('a' | never)>(); 66 | // multiple matches (same or narrower): widest 67 | the(); 68 | // multiple matches (same or wider): widest 69 | the<'a', 'a' & (string | 'a')>(); 70 | // hit and miss: hit (| intersection) 71 | the(); 72 | 73 | // basic operations 74 | the<1, [1][0]>(); 75 | the<'a', keyof {a:1}>(); 76 | the<{a:'a'}, {[P in 'a']:P}>(); 77 | the(); 78 | the(); 79 | 80 | // never 81 | // the(); // Property '0' does not exist on type 'never' 82 | // the(); // Type 'never' cannot be used as an index type 83 | the(); 84 | the<{}, {[P in never]:P}>(); 85 | // the(); // number? wth? wasn't this fixed in TS 2.5? 86 | the(); 87 | 88 | // unions 89 | the<1|2, [1,2,3][0|1]>(); 90 | the<1|'a', ([1,2,3]|['a','b'])[0]>(); 91 | the<'a'|'b', keyof ({a:1}|{b:1})>(); 92 | the<{a:'a'}|{b:'b'}, {[P in 'a'|'b']:P}>(); 93 | the<(number & boolean) | (number & string), number & (boolean | string)>(); 94 | -------------------------------------------------------------------------------- /tests/fixtures.ts: -------------------------------------------------------------------------------- 1 | export type NumArr = [1,2,3]; 2 | export type TestArr = ['a','b','c']; 3 | export interface Part { 4 | id: number; 5 | name: string; 6 | subparts: Part[]; 7 | updatePart(newName: string): void; 8 | } 9 | -------------------------------------------------------------------------------- /tests/function.test.ts: -------------------------------------------------------------------------------- 1 | import { tsst, the } from 'tsst-tycho'; 2 | import { Fn, Arguments, Argument } from '../src/function'; 3 | 4 | describe(`function`, () => { 5 | 6 | describe(`Fn`, () => { 7 | 8 | it(`the<(v: number) => string, Fn<[number], string>>`, () => { 9 | tsst(() => { 10 | the<(v: number) => string, Fn<[number], string>>(); 11 | }).expectToCompile(); 12 | }); 13 | 14 | }); 15 | 16 | describe(`Arguments`, () => { 17 | 18 | it(`the<[boolean, string], Arguments<((a: boolean, s: S) => number)>>`, () => { 19 | tsst(() => { 20 | the<[boolean, string], Arguments<((a: boolean, s: S) => number)>>(); 21 | }).expectToCompile(); 22 | }); 23 | 24 | }); 25 | 26 | describe(`Argument`, () => { 27 | 28 | it(`the<1, Argument<0, (a: 1, b: 2) => 8>>`, () => { 29 | tsst(() => { 30 | the<1, Argument<0, (a: 1, b: 2) => 8>>(); 31 | }).expectToCompile(); 32 | }); 33 | 34 | it(`the<2, Argument<1, (a: 1, ...args: 2[]) => 8>>`, () => { 35 | tsst(() => { 36 | the<2, Argument<1, (a: 1, ...args: 2[]) => 8>>(); 37 | }).expectToCompile(); 38 | }); 39 | 40 | it(`the<2, Argument<1, (a: 1, b: 2, ...args: 3[]) => 8>>`, () => { 41 | tsst(() => { 42 | the<2, Argument<1, (a: 1, b: 2, ...args: 3[]) => 8>>(); 43 | }).expectToCompile(); 44 | }); 45 | 46 | }); 47 | 48 | // describe(``, () => { 49 | 50 | // it(``, () => { 51 | // tsst(() => { 52 | // the<, <>>(); 53 | // }).expectToCompile(); 54 | // }); 55 | 56 | // }); 57 | 58 | }); 59 | -------------------------------------------------------------------------------- /tests/index.ts: -------------------------------------------------------------------------------- 1 | export * from './util.test'; 2 | export * from './boolean.test'; 3 | export * from './type.test'; 4 | export * from './cast.test'; 5 | export * from './number.test'; 6 | export * from './comp.test'; 7 | export * from './union.test'; 8 | export * from './object.test'; 9 | export * from './array.test'; 10 | export * from './tuple.test'; 11 | export * from './function.test'; 12 | // export * from './ramda.test'; 13 | // export * from './crap.test'; 14 | -------------------------------------------------------------------------------- /tests/number.test.ts: -------------------------------------------------------------------------------- 1 | import { tsst, the } from 'tsst-tycho'; 2 | import { Inc, Dec, Add, Subtract, Mult, Pow, DivFloor, Modulo } from '../src/number'; 3 | 4 | describe(`number`, () => { 5 | 6 | describe(`Inc`, () => { 7 | 8 | it(`the<2, Inc[1]>`, () => { 9 | tsst(() => { 10 | the<2, Inc[1]>(); 11 | }).expectToCompile(); 12 | }); 13 | 14 | }); 15 | 16 | describe(`Dec`, () => { 17 | 18 | it(`the<1, Dec[2]>`, () => { 19 | tsst(() => { 20 | the<1, Dec[2]>(); 21 | }).expectToCompile(); 22 | }); 23 | 24 | }); 25 | 26 | describe(`Add`, () => { 27 | 28 | it(`the<5, Add<3, 2>>`, () => { 29 | tsst(() => { 30 | the<5, Add<3, 2>>(); 31 | }).expectToCompile(); 32 | }); 33 | 34 | }); 35 | 36 | describe(`Subtract`, () => { 37 | 38 | it(`the<1, Subtract<3, 2>>`, () => { 39 | tsst(() => { 40 | the<1, Subtract<3, 2>>(); 41 | }).expectToCompile(); 42 | }); 43 | 44 | }); 45 | 46 | describe(`Mult`, () => { 47 | 48 | it(`the<6, Mult<3, 2>>`, () => { 49 | tsst(() => { 50 | the<6, Mult<3, 2>>(); 51 | }).expectToCompile(); 52 | }); 53 | 54 | }); 55 | 56 | describe(`Pow`, () => { 57 | 58 | it(`the<9, Pow<3, 2>>`, () => { 59 | tsst(() => { 60 | the<9, Pow<3, 2>>(); 61 | }).expectToCompile(); 62 | }); 63 | 64 | it(`the<8, Pow<2, 3>>`, () => { 65 | tsst(() => { 66 | the<8, Pow<2, 3>>(); 67 | }).expectToCompile(); 68 | }); 69 | 70 | }); 71 | 72 | describe(`DivFloor`, () => { 73 | 74 | it(`the<2, DivFloor<5, 2>>`, () => { 75 | tsst(() => { 76 | the<2, DivFloor<5, 2>>(); 77 | }).expectToCompile(); 78 | }); 79 | 80 | }); 81 | 82 | describe(`Modulo`, () => { 83 | 84 | it(`the<1, Modulo<5, 2>>`, () => { 85 | tsst(() => { 86 | the<1, Modulo<5, 2>>(); 87 | }).expectToCompile(); 88 | }); 89 | 90 | }); 91 | 92 | }); 93 | -------------------------------------------------------------------------------- /tests/ramda.test.ts: -------------------------------------------------------------------------------- 1 | import { tsst, the } from 'tsst-tycho'; 2 | import { PathFn, PathOrFn, MergeAllFn, FromPairsFn, ZipObjectFn } from '../src/ramda'; //, MapFn 3 | 4 | declare function path>(obj: T, path: R): PathFn; 5 | 6 | describe(`ramda`, () => { 7 | 8 | describe(`PathFn`, () => { 9 | 10 | it(`the<'e', PathFn<{ a: { b: ['c', { d: 'e' }] } }, ['a', 'b', '1', 'd']>>`, () => { 11 | tsst(() => { 12 | the<'e', PathFn<{ a: { b: ['c', { d: 'e' }] } }, ['a', 'b', '1', 'd']>>(); 13 | }).expectToCompile(); 14 | }); 15 | 16 | it(`path`, () => { 17 | tsst(() => { 18 | let obj: { a: { b: ['c', { d: 'e' }] } } = { a: { b: ['c', { d: 'e' }] } }; 19 | let keys: ['a', 'b', '1', 'd'] = ['a', 'b', '1', 'd']; 20 | const pathTest: 'e' = path(obj, keys); 21 | }).expectToCompile(); 22 | }); 23 | 24 | }); 25 | 26 | describe(`PathOrFn`, () => { 27 | 28 | it(`the<'e', PathOrFn<{ a: { b: ['c', { d: 'e' }] } }, "oh", ['a', 'b', 1, 'd']>>`, () => { 29 | tsst(() => { 30 | the<'e', PathOrFn<{ a: { b: ['c', { d: 'e' }] } }, "oh", ['a', 'b', 1, 'd']>>(); 31 | // ^ error: 'oh' 32 | // ^ regression in recent TS? 33 | }).expectToCompile(); 34 | }); 35 | 36 | it(`the<'oh', PathOrFn<{ a: { b: ['c', { d: 'e' }] } }, "oh", ['a', 'b', 4]>>`, () => { 37 | tsst(() => { 38 | the<'oh', PathOrFn<{ a: { b: ['c', { d: 'e' }] } }, "oh", ['a', 'b', 4]>>(); 39 | }).expectToCompile(); 40 | }); 41 | 42 | }); 43 | 44 | describe(`MergeAllFn`, () => { 45 | 46 | it(`the<{ a: 1, b: 3, c: 4, d: 5 }, MergeAllFn<[{ a: 1, b: 2 }, { b: 3, c: 4 }, { d: 5 }]>>`, () => { 47 | tsst(() => { 48 | the<{ a: 1, b: 3, c: 4, d: 5 }, MergeAllFn<[{ a: 1, b: 2 }, { b: 3, c: 4 }, { d: 5 }]>>(); 49 | }).expectToCompile(); 50 | }); 51 | 52 | }); 53 | 54 | 55 | describe(`FromPairsFn`, () => { 56 | 57 | it(`the<{ a: 5, b: 2, c: 3 }, FromPairsFn<[['a', 1], ['b', 2], ['c', 3], ['a', 5]]>>`, () => { 58 | tsst(() => { 59 | the<{ a: 5, b: 2, c: 3 }, FromPairsFn<[['a', 1], ['b', 2], ['c', 3], ['a', 5]]>>(); 60 | }).expectToCompile(); 61 | }); 62 | 63 | }); 64 | 65 | describe(`ZipObjectFn`, () => { 66 | 67 | it(`the<{ a: 1, b: 2, c: 3 }, ZipObjectFn<['a', 'b', 'c'], [1, 2, 3]>>`, () => { 68 | tsst(() => { 69 | the<{ a: 1, b: 2, c: 3 }, ZipObjectFn<['a', 'b', 'c'], [1, 2, 3]>>(); 70 | }).expectToCompile(); 71 | }); 72 | 73 | }); 74 | 75 | describe(`#12838`, () => { 76 | 77 | let inc: (n: number) => number; // +1 78 | let identity: (a: T) => T; 79 | let compose: { 80 | (fn0: (x0: V0) => T1): (x0: V0) => T1; 81 | (fn1: (x: T1) => T2, fn0: (x: V0) => T1): (x: V0) => T2; 82 | } 83 | let pipe: { 84 | (fn0: (x0: V0) => T1): (x0: V0) => T1; // arity 1: same as compose 85 | (fn0: (x: V0) => T1, fn1: (x: T1) => T2): (x: V0) => T2; // arity 2: params swapped 86 | } 87 | 88 | it(`identity`, () => { 89 | tsst(() => { 90 | let a: string = identity(0); 91 | }).expectToFailWith(`not assignable to type 'string'`); 92 | }); 93 | 94 | // don't use generics if it can't resolve them right away: 95 | 96 | it(`compose + generics`, () => { 97 | tsst(() => { 98 | let a: string = compose(identity)(0); // generics lost, now {} => {} 99 | }).expectToFailWith(`not assignable to type 'string'`); 100 | }); 101 | 102 | it(`pipe + generics`, () => { 103 | tsst(() => { 104 | let a: string = pipe (identity)(0); // ditto 105 | }).expectToFailWith(`not assignable to type 'string'`); 106 | }); 107 | 108 | // argument order apparently matters too: 109 | 110 | it(`compose + generics: concrete type first`, () => { 111 | tsst(() => { 112 | let a: string = compose(identity, inc)(0); // nope, number => {} 113 | }).expectToFailWith(`not assignable to type 'string'`); 114 | }); 115 | 116 | it(`pipe + generics: concrete type first`, () => { 117 | tsst(() => { 118 | let a: string = pipe (inc, identity)(0); // ok, number -> number 119 | }).expectToFailWith(`not assignable to type 'string'`); 120 | }); 121 | 122 | // also no reasoning backward: 123 | 124 | it(`compose + generics: concrete type last`, () => { 125 | tsst(() => { 126 | let a: string = compose(inc, identity)(0); // {} => number 127 | }).expectToFailWith(`not assignable to type 'string'`); 128 | }); 129 | 130 | it(`pipe + generics: concrete type last`, () => { 131 | tsst(() => { 132 | let a: string = pipe (identity, inc)(0); // {} => number 133 | }).expectToFailWith(`not assignable to type 'string'`); 134 | }); 135 | 136 | }); 137 | 138 | // describe(``, () => { 139 | 140 | // it(``, () => { 141 | // tsst(() => { 142 | // the<, <>(); 143 | // }).expectToCompile(); 144 | // }); 145 | 146 | // }); 147 | 148 | }); 149 | -------------------------------------------------------------------------------- /tests/repros.test.ts: -------------------------------------------------------------------------------- 1 | import { tsst, the } from 'tsst-tycho'; 2 | import { And } from '../src/boolean'; 3 | import { NumberToString } from '../src/cast'; 4 | 5 | describe(`repros`, () => { 6 | 7 | // it(``, () => { 8 | // tsst(() => { 9 | // }).expectToCompile(); 10 | // }); 11 | 12 | }); 13 | -------------------------------------------------------------------------------- /tests/stdlib.test.ts: -------------------------------------------------------------------------------- 1 | import { tsst, the } from 'tsst-tycho'; 2 | 3 | describe(`stdlib`, () => { 4 | 5 | describe(`Partial`, () => { 6 | it(`the<{ a?: 1, b?: 2 }, Partial<{ a: 1, b: 2 }>>`, () => { 7 | tsst(() => { 8 | the<{ a?: 1, b?: 2 }, Partial<{ a: 1, b: 2 }>>(); 9 | }).expectToCompile(); 10 | }); 11 | }); 12 | 13 | describe(`Readonly`, () => { 14 | it(`the<{ readonly a: 1 }, Readonly<{ a: 1 }>>`, () => { 15 | tsst(() => { 16 | the<{ readonly a: 1 }, Readonly<{ a: 1 }>>(); 17 | }).expectToCompile(); 18 | }); 19 | }); 20 | 21 | describe(`Pick`, () => { 22 | it(`the<{ a: 1 }, Pick<{ a: 1, b: 2 }, 'a'>>`, () => { 23 | tsst(() => { 24 | the<{ a: 1 }, Pick<{ a: 1, b: 2 }, 'a'>>(); 25 | }).expectToCompile(); 26 | }); 27 | }); 28 | 29 | describe(`Record`, () => { 30 | it(`the<{ a: 1, b: 1 }, Record<'a' | 'b', 1>>`, () => { 31 | tsst(() => { 32 | the<{ a: 1, b: 1 }, Record<'a' | 'b', 1>>(); 33 | }).expectToCompile(); 34 | }); 35 | }); 36 | 37 | describe(`Exclude`, () => { 38 | it(`the<1|2, Exclude<1|2|3, 3|4>>`, () => { 39 | tsst(() => { 40 | the<1|2, Exclude<1|2|3, 3|4>>(); 41 | }).expectToCompile(); 42 | }); 43 | }); 44 | 45 | describe(`Extract`, () => { 46 | it(`the<2|3, Extract<1|2|3, 2|3|4>>`, () => { 47 | tsst(() => { 48 | the<2|3, Extract<1|2|3, 2|3|4>>(); 49 | }).expectToCompile(); 50 | }); 51 | }); 52 | 53 | describe(`NonNullable`, () => { 54 | it(`the<1, NonNullable<1 | null>>`, () => { 55 | tsst(() => { 56 | the<1, NonNullable<1 | null>>(); 57 | }).expectToCompile(); 58 | }); 59 | }); 60 | 61 | describe(`ReturnType`, () => { 62 | it(`the string>>`, () => { 63 | tsst(() => { 64 | the string>>(); 65 | }).expectToCompile(); 66 | }); 67 | }); 68 | 69 | describe(`InstanceType`, () => { 70 | 71 | it(`the string>>`, () => { 72 | tsst(() => { 73 | the string>>(); 74 | }).expectToCompile(); 75 | }); 76 | 77 | it(`the>`, () => { 78 | tsst(() => { 79 | class MyClass {} 80 | the>(); 81 | }).expectToCompile(); 82 | }); 83 | 84 | describe(`Required`, () => { 85 | it(`the<{ a: 1 }, Required<{ a?: 1 }>>`, () => { 86 | tsst(() => { 87 | the<{ a: 1 }, Required<{ a?: 1 }>>(); 88 | }).expectToCompile(); 89 | }); 90 | }); 91 | 92 | }); 93 | 94 | // describe(``, () => { 95 | // it(``, () => { 96 | // tsst(() => { 97 | // the<, <>>(); 98 | // }).expectToCompile(); 99 | // }); 100 | // }); 101 | 102 | }); 103 | -------------------------------------------------------------------------------- /tests/syntax.test.ts: -------------------------------------------------------------------------------- 1 | import { tsst, the } from 'tsst-tycho'; 2 | 3 | describe(`built-in syntax`, () => { 4 | 5 | describe(`|`, () => { 6 | it(`the<1|2, 2>`, () => { 7 | tsst(() => { 8 | the<1|2, 2>(); 9 | }).expectToCompile(); 10 | }); 11 | }); 12 | 13 | describe(`&`, () => { 14 | it(`the<1, 1&2>`, () => { 15 | tsst(() => { 16 | the<1, 1&2>(); 17 | }).expectToCompile(); 18 | }); 19 | }); 20 | 21 | describe(`[]`, () => { 22 | it(`the<1, {a:1}['a']>`, () => { 23 | tsst(() => { 24 | the<1, {a:1}['a']>(); 25 | }).expectToCompile(); 26 | }); 27 | }); 28 | 29 | describe(`keyof`, () => { 30 | it(`the<'a'|'b', keyof { a: 1, b: 2 }>`, () => { 31 | tsst(() => { 32 | the<'a'|'b', keyof { a: 1, b: 2 }>(); 33 | }).expectToCompile(); 34 | }); 35 | }); 36 | 37 | describe(`in`, () => { 38 | it(`the<{ a: 'a' }, { [P in 'a']: P }>`, () => { 39 | tsst(() => { 40 | the<{ a: 'a' }, { [P in 'a']: P }>(); 41 | }).expectToCompile(); 42 | }); 43 | }); 44 | 45 | describe(`extends`, () => { 46 | it(`the<1, true extends boolean ? 1 : 0>`, () => { 47 | tsst(() => { 48 | the<1, true extends boolean ? 1 : 0>(); 49 | }).expectToCompile(); 50 | }); 51 | }); 52 | 53 | // describe(``, () => { 54 | // it(``, () => { 55 | // tsst(() => { 56 | // the<, <>>(); 57 | // }).expectToCompile(); 58 | // }); 59 | // }); 60 | 61 | }); 62 | -------------------------------------------------------------------------------- /tests/tuple.test.ts: -------------------------------------------------------------------------------- 1 | import { tsst, the } from 'tsst-tycho'; 2 | import { AppendList, ConcatLists, LengthList, ReverseList, IncIndex, DecIndex, ZeroIndex, Prepend, ListTail, DifferenceLists } from '../src/tuple'; 3 | 4 | describe(`tuple`, () => { 5 | 6 | describe(`AppendList`, () => { 7 | 8 | it(`the<{ 0: 'a', 1: 'b', 2: 'c', length: 3 }, AppendList<{ 0: 'a', 1: 'b', length: 2 }, 'c'>>`, () => { 9 | tsst(() => { 10 | the<{ 0: 'a', 1: 'b', 2: 'c', length: 3 }, AppendList<{ 0: 'a', 1: 'b', length: 2 }, 'c'>>(); 11 | }).expectToCompile(); 12 | }); 13 | 14 | }); 15 | 16 | describe(`ConcatLists`, () => { 17 | 18 | it(`the<{ 0: 'a', 1: 'b', 2: 'c', 3: 'd', length: 4 }, ConcatLists<{ 0: 'a', 1: 'b', length: 2 }, { 0: 'c', 1: 'd', length: 2 }>>`, () => { 19 | tsst(() => { 20 | the<{ 0: 'a', 1: 'b', 2: 'c', 3: 'd', length: 4 }, ConcatLists<{ 0: 'a', 1: 'b', length: 2 }, { 0: 'c', 1: 'd', length: 2 }>>(); 21 | }).expectToCompile(); 22 | }); 23 | 24 | // ^ does not terminate 25 | 26 | }); 27 | 28 | describe(`LengthList`, () => { 29 | 30 | it(`the<2, LengthList<{ 0: 'a', 1: 'b', length: 2 }>>`, () => { 31 | tsst(() => { 32 | the<2, LengthList<{ 0: 'a', 1: 'b', length: 2 }>>(); 33 | }).expectToCompile(); 34 | }); 35 | 36 | }); 37 | 38 | describe(`ReverseList`, () => { 39 | 40 | it(`the<{ 0: 'b', 1: 'a', length: 2 }, ReverseList<['a', 'b']>>`, () => { 41 | tsst(() => { 42 | the<{ 0: 'b', 1: 'a', length: 2 }, ReverseList<['a', 'b']>>(); 43 | }).expectToCompile(); 44 | }); 45 | 46 | }); 47 | 48 | describe(`IncIndex`, () => { 49 | 50 | it(`the<{ 2: 'a', 3: 'b', length: 2 }, IncIndex<{ 0: 'a', 1: 'b', length: 2 }, 2>>`, () => { 51 | tsst(() => { 52 | the<{ 2: 'a', 3: 'b', length: 2 }, IncIndex<{ 0: 'a', 1: 'b', length: 2 }, 2>>(); 53 | }).expectToCompile(); 54 | }); 55 | 56 | // ^ does not terminate 57 | 58 | }); 59 | 60 | describe(`DecIndex`, () => { 61 | 62 | it(`the<{ 0: 'a', 1: 'b', length: 2 }, DecIndex<{ 2: 'a', 3: 'b', length: 2 }, 2>>`, () => { 63 | tsst(() => { 64 | the<{ 0: 'a', 1: 'b', length: 2 }, DecIndex<{ 2: 'a', 3: 'b', length: 2 }, 2>>(); 65 | }).expectToCompile(); 66 | }); 67 | // ^ error: { length: 2; } 68 | 69 | }); 70 | 71 | describe(`ZeroIndex`, () => { 72 | 73 | it(`the<{ 0: 'a', 1: 'b', length: 2 }, ZeroIndex<{ 2: 'a', 3: 'b', length: 2 }>>`, () => { 74 | tsst(() => { 75 | the<{ 0: 'a', 1: 'b', length: 2 }, ZeroIndex<{ 2: 'a', 3: 'b', length: 2 }>>(); 76 | }).expectToCompile(); 77 | }); 78 | // ^ error: { length: 2; } 79 | 80 | }); 81 | 82 | describe(`Prepend`, () => { 83 | 84 | it(`the<{ 0: 'a', 1: 'b', 2: 'c', length: 3 }, Prepend<{ 0: 'b', 1: 'c', length: 2 }, 'a'>>`, () => { 85 | tsst(() => { 86 | the<{ 0: 'a', 1: 'b', 2: 'c', length: 3 }, Prepend<{ 0: 'b', 1: 'c', length: 2 }, 'a'>>(); 87 | }).expectToCompile(); 88 | }); 89 | // ^ error: { length: 2; } 90 | 91 | }); 92 | 93 | describe(`ListTail`, () => { 94 | 95 | it(`the<'c', ListTail<{ 0: 'a', 1: 'b', 2: 'c', length: 3 }>>`, () => { 96 | tsst(() => { 97 | the<'c', ListTail<{ 0: 'a', 1: 'b', 2: 'c', length: 3 }>>(); 98 | }).expectToCompile(); 99 | }); 100 | 101 | }); 102 | 103 | describe(`DifferenceLists`, () => { 104 | 105 | it(`the<{ 0: 'c', 1: 'd', length: 2 }, DifferenceLists<{ 0: 'a', 1: 'b', 2: 'c', 3: 'd', length: 4 }, { 0: 123, 1: 456, length: 2 }>>`, () => { 106 | tsst(() => { 107 | the<{ 0: 'c', 1: 'd', length: 2 }, DifferenceLists<{ 0: 'a', 1: 'b', 2: 'c', 3: 'd', length: 4 }, { 0: 123, 1: 456, length: 2 }>>(); 108 | }).expectToCompile(); 109 | }); 110 | 111 | }); 112 | 113 | }); 114 | -------------------------------------------------------------------------------- /tests/type.test.ts: -------------------------------------------------------------------------------- 1 | import { tsst, the } from 'tsst-tycho'; 2 | import { Xor, Matches, TypesEqual, InstanceOf, Awaited, Flatten, Widen, DiscriminateUnion, Const } from '../src/type'; 3 | 4 | describe(`type`, () => { 5 | 6 | describe(`Xor`, () => { 7 | 8 | type Person = Xor; 9 | 10 | it(`the>`, () => { 11 | tsst(() => { 12 | the>(); 13 | }).expectToCompile(); 14 | }); 15 | 16 | it(`the<{ name: 's' }, Xor<{ name: 's' }>>`, () => { 17 | tsst(() => { 18 | the<{ name: 's' }, Person<{ name: 's' }>>(); 19 | }).expectToCompile(); 20 | }); 21 | 22 | it(`the>`, () => { 23 | tsst(() => { 24 | the>(); 25 | }).expectToCompile(); 26 | }); 27 | 28 | }); 29 | 30 | describe(`Matches`, () => { 31 | 32 | it(`the<'1', Matches<1, number>>`, () => { 33 | tsst(() => { 34 | the<'1', Matches<1, number>>(); 35 | }).expectToCompile(); 36 | }); 37 | 38 | it(`the<'1', Matches>`, () => { 39 | tsst(() => { 40 | the<'1', Matches>(); 41 | }).expectToCompile(); 42 | }); 43 | 44 | it(`the<'0', Matches>`, () => { 45 | tsst(() => { 46 | the<'0', Matches>(); 47 | }).expectToCompile(); 48 | }); 49 | 50 | }); 51 | 52 | describe(`TypesEqual`, () => { 53 | 54 | it(`the<'0', TypesEqual>`, () => { 55 | tsst(() => { 56 | the<'0', TypesEqual>(); 57 | }).expectToCompile(); 58 | }); 59 | 60 | it(`the<'1', TypesEqual>`, () => { 61 | tsst(() => { 62 | the<'1', TypesEqual>(); 63 | }).expectToCompile(); 64 | }); 65 | 66 | }); 67 | 68 | describe(`InstanceOf`, () => { 69 | 70 | it(`the<'1', InstanceOf<1, number>>`, () => { 71 | tsst(() => { 72 | the<'1', InstanceOf<1, number>>(); 73 | }).expectToCompile(); 74 | }); 75 | 76 | it(`the<'0', InstanceOf>`, () => { 77 | tsst(() => { 78 | the<'0', InstanceOf>(); 79 | }).expectToCompile(); 80 | }); 81 | 82 | it(`the<'0', InstanceOf>`, () => { 83 | tsst(() => { 84 | the<'0', InstanceOf>(); 85 | }).expectToCompile(); 86 | }); 87 | 88 | }); 89 | 90 | describe(`Awaited`, () => { 91 | 92 | it(`the<1, Awaited<1>>`, () => { 93 | tsst(() => { 94 | the<1, Awaited<1>>(); 95 | }).expectToCompile(); 96 | }); 97 | 98 | it(`the<1, Awaited>>`, () => { 99 | tsst(() => { 100 | the<1, Awaited>>(); 101 | }).expectToCompile(); 102 | }); 103 | 104 | it(`the<1, Awaited>>>`, () => { 105 | tsst(() => { 106 | the<1, Awaited>>>(); 107 | }).expectToCompile(); 108 | }); 109 | 110 | it(`the<1, Awaited<1 | Promise<1>>>`, () => { 111 | tsst(() => { 112 | the<1, Awaited<1 | Promise<1>>>(); 113 | }).expectToCompile(); 114 | }); 115 | 116 | }); 117 | 118 | describe(`Flatten`, () => { 119 | 120 | it(`the<1, Flatten<1>>`, () => { 121 | tsst(() => { 122 | the<1, Flatten<1>>(); 123 | }).expectToCompile(); 124 | }); 125 | 126 | it(`the<1, Flatten<[1, 1]>>`, () => { 127 | tsst(() => { 128 | the<1, Flatten<[1, 1]>>(); 129 | }).expectToCompile(); 130 | }); 131 | 132 | it(`the<1, Flatten<[1, [1]]>>`, () => { 133 | tsst(() => { 134 | the<1, Flatten<[1, [1]]>>(); 135 | }).expectToCompile(); 136 | }); 137 | 138 | }); 139 | 140 | describe(`Widen`, () => { 141 | 142 | it(`the, number>`, () => { 143 | tsst(() => { 144 | the, number>(); 145 | }).expectToCompile(); 146 | }); 147 | 148 | it(`the, boolean>`, () => { 149 | tsst(() => { 150 | the, boolean>(); 151 | }).expectToCompile(); 152 | }); 153 | 154 | it(`the, string>`, () => { 155 | tsst(() => { 156 | the, string>(); 157 | }).expectToCompile(); 158 | }); 159 | 160 | }); 161 | 162 | describe(`DiscriminateUnion`, () => { 163 | 164 | it(`the>`, () => { 165 | tsst(() => { 166 | interface Square { 167 | kind: "square"; 168 | size: number; 169 | } 170 | interface Rectangle { 171 | kind: "rectangle"; 172 | width: number; 173 | height: number; 174 | } 175 | interface Circle { 176 | kind: "circle"; 177 | radius: number; 178 | } 179 | type Shape = Square | Rectangle | Circle; 180 | type DiscriminateShape = DiscriminateUnion; 181 | the>(); 182 | }).expectToCompile(); 183 | }); 184 | 185 | }); 186 | 187 | describe(`Const`, () => { 188 | 189 | it(`the<1, Const<1, 2>>`, () => { 190 | tsst(() => { 191 | the<1, Const<1, 2>>(); 192 | }).expectToCompile(); 193 | }); 194 | 195 | }); 196 | 197 | // describe(``, () => { 198 | 199 | // it(``, () => { 200 | // tsst(() => { 201 | // the<, <>>(); 202 | // }).expectToCompile(); 203 | // }); 204 | 205 | // }); 206 | 207 | }); 208 | -------------------------------------------------------------------------------- /tests/union.test.ts: -------------------------------------------------------------------------------- 1 | import { tsst, the } from 'tsst-tycho'; 2 | import { Obj } from '../src/util'; 3 | import { UnionHasKey, UnionToObject, UnionContained, UnionEmpty, UnionsOverlap, IsUnion } from '../src/union'; 4 | import { ObjectHasKey } from '../src/object'; 5 | 6 | import { And } from './boolean'; 7 | 8 | describe(`util`, () => { 9 | 10 | describe(`UnionHasKey`, () => { 11 | 12 | it(`the<'1', UnionHasKey<'a'|'b', 'b'>>`, () => { 13 | tsst(() => { 14 | the<'1', UnionHasKey<'a'|'b', 'b'>>(); 15 | }).expectToCompile(); 16 | }); 17 | 18 | it(`the<'0', UnionHasKey<'a'|'b', 'c'>>`, () => { 19 | tsst(() => { 20 | the<'0', UnionHasKey<'a'|'b', 'c'>>(); 21 | }).expectToCompile(); 22 | }); 23 | 24 | it(`the<'1', UnionHasKey<'a'|'b', 'a'|'b'>>`, () => { 25 | tsst(() => { 26 | the<'1', UnionHasKey<'a'|'b', 'a'|'b'>>(); 27 | }).expectToCompile(); 28 | }); 29 | 30 | it(`the<'0', UnionHasKey<'a'|'b', 'c'|'d'>>`, () => { 31 | tsst(() => { 32 | the<'0', UnionHasKey<'a'|'b', 'c'|'d'>>(); 33 | }).expectToCompile(); 34 | }); 35 | 36 | it(`the<'0'|'1', UnionHasKey<'a'|'b', 'b'|'c'>>`, () => { 37 | tsst(() => { 38 | the<'0'|'1', UnionHasKey<'a'|'b', 'b'|'c'>>(); 39 | }).expectToCompile(); 40 | }); 41 | 42 | it(`the<'1', UnionHasKey<'a'|'b'|'toString', 'toString'>>`, () => { 43 | tsst(() => { 44 | the<'1', UnionHasKey<'a'|'b'|'toString', 'toString'>>(); 45 | }).expectToCompile(); 46 | }); 47 | 48 | it(`the<'0', UnionHasKey<'a'|'b', 'toString'>>`, () => { 49 | tsst(() => { 50 | the<'0', UnionHasKey<'a'|'b', 'toString'>>(); 51 | }).expectToCompile(); 52 | }); 53 | // ^ error: Type '() => string' does not satisfy the constraint '"0"'. 54 | 55 | }); 56 | 57 | describe(`UnionToObject`, () => { 58 | 59 | it(`the<{ b: 'b', c: 'c' }, UnionToObject<'b' | 'c'>>`, () => { 60 | tsst(() => { 61 | the<{ b: 'b', c: 'c' }, UnionToObject<'b' | 'c'>>(); 62 | }).expectToCompile(); 63 | }); 64 | 65 | }); 66 | 67 | describe(`UnionContained`, () => { 68 | 69 | it(`the<'1', UnionContained>`, () => { 70 | tsst(() => { 71 | the<'1', UnionContained>(); 72 | }).expectToCompile(); 73 | }); 74 | 75 | it(`the<'1', UnionContained<'a', 'a'>>`, () => { 76 | tsst(() => { 77 | the<'1', UnionContained<'a', 'a'>>(); 78 | }).expectToCompile(); 79 | }); 80 | 81 | it(`the<'0', UnionContained<'b', 'a'>>`, () => { 82 | tsst(() => { 83 | the<'0', UnionContained<'b', 'a'>>(); 84 | }).expectToCompile(); 85 | }); 86 | 87 | it(`the<'0', UnionContained<'a' | 'b', 'a'>>`, () => { 88 | tsst(() => { 89 | the<'0', UnionContained<'a' | 'b', 'a'>>(); 90 | }).expectToCompile(); 91 | }); 92 | 93 | }); 94 | 95 | describe(`UnionEmpty`, () => { 96 | 97 | it(`the<'1', UnionEmpty>`, () => { 98 | tsst(() => { 99 | the<'1', UnionEmpty>(); 100 | }).expectToCompile(); 101 | }); 102 | 103 | it(`the<'0', UnionEmpty<'a'>>`, () => { 104 | tsst(() => { 105 | the<'0', UnionEmpty<'a'>>(); 106 | }).expectToCompile(); 107 | }); 108 | 109 | it(`the<'0', UnionEmpty<'a' | 'b'>>`, () => { 110 | tsst(() => { 111 | the<'0', UnionEmpty<'a' | 'b'>>(); 112 | }).expectToCompile(); 113 | }); 114 | 115 | it(`the<'0', UnionEmpty<'toString'>>`, () => { 116 | tsst(() => { 117 | the<'0', UnionEmpty<'toString'>>(); 118 | }).expectToCompile(); 119 | }); 120 | 121 | it(`the<'0', UnionEmpty<'toString' | 'a'>>`, () => { 122 | tsst(() => { 123 | the<'0', UnionEmpty<'toString' | 'a'>>(); 124 | }).expectToCompile(); 125 | }); 126 | 127 | }); 128 | 129 | describe(`UnionsOverlap`, () => { 130 | 131 | it(`the<'1', UnionsOverlap<'a', 'a' | 'b'>>`, () => { 132 | tsst(() => { 133 | the<'1', UnionsOverlap<'a', 'a' | 'b'>>(); 134 | }).expectToCompile(); 135 | }); 136 | 137 | it(`the<'0', UnionsOverlap<'a', 'c'>>`, () => { 138 | tsst(() => { 139 | the<'0', UnionsOverlap<'a', 'c'>>(); 140 | }).expectToCompile(); 141 | }); 142 | 143 | }); 144 | 145 | describe(`IsUnion`, () => { 146 | 147 | it(`the<'1', IsUnion<'a' | 'b'>>`, () => { 148 | tsst(() => { 149 | the<'1', IsUnion<'a' | 'b'>>(); 150 | }).expectToCompile(); 151 | }); 152 | 153 | it(`the<'0', IsUnion<'a'>>`, () => { 154 | tsst(() => { 155 | the<'0', IsUnion<'a'>>(); 156 | }).expectToCompile(); 157 | }); 158 | 159 | it(`the<'0', IsUnion>`, () => { 160 | tsst(() => { 161 | the<'0', IsUnion>(); 162 | }).expectToCompile(); 163 | }); 164 | 165 | it(`the<'1', IsUnion<'a' | undefined>>`, () => { 166 | tsst(() => { 167 | the<'1', IsUnion<'a' | undefined>>(); 168 | }).expectToCompile(); 169 | }); 170 | // ^ error: not all strings 171 | 172 | }); 173 | 174 | }); 175 | -------------------------------------------------------------------------------- /tests/util.test.ts: -------------------------------------------------------------------------------- 1 | import { tsst, the } from 'tsst-tycho'; 2 | import { If, The, Intersection } from '../src/util'; 3 | 4 | describe(`util`, () => { 5 | 6 | describe(`the`, () => { 7 | 8 | it(`works with matching types`, () => { 9 | tsst(() => { 10 | the(); 11 | }).expectToCompile(); 12 | }); 13 | 14 | it(`fails with clashing types`, () => { 15 | tsst(() => { 16 | the(); 17 | }).expectToFailWith('does not satisfy'); 18 | }); 19 | 20 | it(`protects from never when flipped`, () => { 21 | tsst(() => { 22 | the(); 23 | }).expectToFailWith('does not satisfy'); 24 | }); 25 | 26 | it(`protects from any`, () => { 27 | tsst(() => { 28 | the(); 29 | }).expectToFailWith('does not satisfy'); 30 | }); 31 | 32 | }); 33 | 34 | describe(`If`, () => { 35 | 36 | it(`has then`, () => { 37 | tsst(() => { 38 | the<123, If<'1', 123, 456>>(); 39 | }).expectToCompile(); 40 | }); 41 | 42 | it(`has else`, () => { 43 | tsst(() => { 44 | the<456, If<'0', 123, 456>>(); 45 | }).expectToCompile(); 46 | }); 47 | 48 | }); 49 | 50 | describe(`Intersection`, () => { 51 | 52 | it(`intersects`, () => { 53 | tsst(() => { 54 | the<1 & 'a', Intersection<1, 'a'>>(); 55 | }).expectToCompile(); 56 | }); 57 | 58 | }); 59 | 60 | }); 61 | -------------------------------------------------------------------------------- /tsc.log: -------------------------------------------------------------------------------- 1 | src/array/ConcatNumObjs.ts(3,10): error TS2305: Module '"/media/tycho/Drogon/Coding/js/typical/src/array/IncIndexNumbObj"' has no exported member 'IncIndexNumbObj'. 2 | src/array/ListFrom.ts(6,10): error TS2305: Module '"/media/tycho/Drogon/Coding/js/typical/src/array/TupleHasIndex"' has no exported member 'TupleHasIndex'. 3 | src/array/ListFrom.ts(16,98): error TS2538: Type 'any' cannot be used as an index type. 4 | src/array/Reverse.ts(7,10): error TS2305: Module '"/media/tycho/Drogon/Coding/js/typical/src/array/TupleHasIndex"' has no exported member 'TupleHasIndex'. 5 | src/array/Reverse.ts(17,112): error TS2538: Type 'any' cannot be used as an index type. 6 | src/array/TupleLastElem.ts(4,10): error TS2305: Module '"/media/tycho/Drogon/Coding/js/typical/src/array/TupleHasIndex"' has no exported member 'TupleHasIndex'. 7 | src/array/TupleLastElem.ts(10,49): error TS2538: Type 'any' cannot be used as an index type. 8 | src/array/TupleLastIndex.ts(4,10): error TS2305: Module '"/media/tycho/Drogon/Coding/js/typical/src/array/TupleHasIndex"' has no exported member 'TupleHasIndex'. 9 | src/array/TupleLastIndex.ts(11,47): error TS2538: Type 'any' cannot be used as an index type. 10 | src/array/Vector.ts(18,5): error TS2502: '0' is referenced directly or indirectly in its own type annotation. 11 | src/array/index.ts(6,10): error TS2305: Module '"/media/tycho/Drogon/Coding/js/typical/src/array/IncIndexNumbObj"' has no exported member 'IncIndexNumbObj'. 12 | src/array/index.ts(13,10): error TS2305: Module '"/media/tycho/Drogon/Coding/js/typical/src/array/TupleHasIndex"' has no exported member 'TupleHasIndex'. 13 | src/boolean/Determinate.ts(3,10): error TS2305: Module '"/media/tycho/Drogon/Coding/js/typical/src/boolean/Determinate"' has no exported member 'Indeterminate'. 14 | src/cast/TupleIndicesToUnion.ts(3,10): error TS2305: Module '"/media/tycho/Drogon/Coding/js/typical/src/array/TupleHasIndex"' has no exported member 'TupleHasIndex'. 15 | src/cast/TupleIndicesToUnion.ts(9,58): error TS2538: Type 'any' cannot be used as an index type. 16 | src/cast/TupleToList.ts(4,10): error TS2305: Module '"/media/tycho/Drogon/Coding/js/typical/src/array/TupleHasIndex"' has no exported member 'TupleHasIndex'. 17 | src/cast/TupleToList.ts(11,109): error TS2538: Type 'any' cannot be used as an index type. 18 | src/cast/TupleToObject.ts(4,10): error TS2305: Module '"/media/tycho/Drogon/Coding/js/typical/src/array/TupleHasIndex"' has no exported member 'TupleHasIndex'. 19 | src/cast/TupleToObject.ts(11,95): error TS2538: Type 'any' cannot be used as an index type. 20 | src/cast/TupleToUnion.ts(3,10): error TS2305: Module '"/media/tycho/Drogon/Coding/js/typical/src/array/TupleHasIndex"' has no exported member 'TupleHasIndex'. 21 | src/cast/TupleToUnion.ts(9,54): error TS2538: Type 'any' cannot be used as an index type. 22 | src/comp/Gt.ts(12,3): error TS2502: '0' is referenced directly or indirectly in its own type annotation. 23 | src/comp/Gte.ts(12,3): error TS2502: '0' is referenced directly or indirectly in its own type annotation. 24 | src/comp/Lt.ts(12,3): error TS2502: '0' is referenced directly or indirectly in its own type annotation. 25 | src/comp/Lte.ts(12,3): error TS2502: '0' is referenced directly or indirectly in its own type annotation. 26 | src/function/NumberOfArgs.ts(7,9): error TS2304: Cannot find name 'IsValidArg'. 27 | src/function/NumberOfArgs.ts(8,9): error TS2304: Cannot find name 'IsValidArg'. 28 | src/function/NumberOfArgs.ts(9,9): error TS2304: Cannot find name 'IsValidArg'. 29 | src/function/NumberOfArgs.ts(10,9): error TS2304: Cannot find name 'IsValidArg'. 30 | src/function/NumberOfArgs.ts(11,9): error TS2304: Cannot find name 'IsValidArg'. 31 | src/function/NumberOfArgs.ts(12,9): error TS2304: Cannot find name 'IsValidArg'. 32 | src/function/NumberOfArgs.ts(13,9): error TS2304: Cannot find name 'IsValidArg'. 33 | src/function/NumberOfArgs.ts(14,9): error TS2304: Cannot find name 'IsValidArg'. 34 | src/function/NumberOfArgs.ts(15,9): error TS2304: Cannot find name 'IsValidArg'. 35 | src/function/NumberOfArgs.ts(16,9): error TS2304: Cannot find name 'IsValidArg'. 36 | src/number/Add.ts(11,13): error TS2502: '0' is referenced directly or indirectly in its own type annotation. 37 | src/number/Mult.ts(12,15): error TS2502: '0' is referenced directly or indirectly in its own type annotation. 38 | src/number/Pow.ts(12,15): error TS2502: '0' is referenced directly or indirectly in its own type annotation. 39 | src/number/Subtract.ts(10,13): error TS2502: '0' is referenced directly or indirectly in its own type annotation. 40 | src/object/DeepRequired.ts(5,23): error TS2304: Cannot find name 'DeepRequiredArray'. 41 | src/object/DeepWiden.ts(7,5): error TS2304: Cannot find name 'Widen'. 42 | src/object/HasKey.ts(3,10): error TS2305: Module '"/media/tycho/Drogon/Coding/js/typical/src/array/TupleHasIndex"' has no exported member 'TupleHasIndex'. 43 | src/ramda/FromPairsFn.ts(2,10): error TS2305: Module '"/media/tycho/Drogon/Coding/js/typical/src/array/TupleHasIndex"' has no exported member 'TupleHasIndex'. 44 | src/ramda/FromPairsFn.ts(12,79): error TS2538: Type 'any' cannot be used as an index type. 45 | src/ramda/MergeAllFn.ts(3,10): error TS2305: Module '"/media/tycho/Drogon/Coding/js/typical/src/array/TupleHasIndex"' has no exported member 'TupleHasIndex'. 46 | src/ramda/MergeAllFn.ts(12,55): error TS2538: Type 'any' cannot be used as an index type. 47 | src/ramda/PathFn.ts(1,10): error TS2305: Module '"/media/tycho/Drogon/Coding/js/typical/src/array/TupleHasIndex"' has no exported member 'TupleHasIndex'. 48 | src/ramda/PathFn.ts(9,45): error TS2538: Type 'any' cannot be used as an index type. 49 | src/ramda/PathOrFn.ts(3,10): error TS2305: Module '"/media/tycho/Drogon/Coding/js/typical/src/array/TupleHasIndex"' has no exported member 'TupleHasIndex'. 50 | src/ramda/PathOrFn.ts(13,76): error TS2538: Type 'any' cannot be used as an index type. 51 | src/ramda/ZipObjectFn.ts(2,10): error TS2305: Module '"/media/tycho/Drogon/Coding/js/typical/src/array/TupleHasIndex"' has no exported member 'TupleHasIndex'. 52 | src/ramda/ZipObjectFn.ts(11,78): error TS2538: Type 'any' cannot be used as an index type. 53 | src/tuple/ConcatLists.ts(4,10): error TS2305: Module '"/media/tycho/Drogon/Coding/js/typical/src/tuple/IncIndex"' has no exported member 'IncIndex'. 54 | src/tuple/DecIndex.ts(11,53): error TS2322: Type 'NumberToString[{ 1: I; 0: any; }[Matches]]' is not assignable to type 'string'. 55 | src/tuple/Prepend.ts(2,10): error TS2305: Module '"/media/tycho/Drogon/Coding/js/typical/src/tuple/IncIndex"' has no exported member 'IncIndex'. 56 | src/tuple/ReverseList.ts(6,10): error TS2305: Module '"/media/tycho/Drogon/Coding/js/typical/src/array/TupleHasIndex"' has no exported member 'TupleHasIndex'. 57 | src/tuple/ReverseList.ts(19,116): error TS2538: Type 'any' cannot be used as an index type. 58 | src/tuple/index.ts(5,10): error TS2305: Module '"/media/tycho/Drogon/Coding/js/typical/src/tuple/IncIndex"' has no exported member 'IncIndex'. 59 | src/type/Flatten.ts(5,5): error TS2502: ''1'' is referenced directly or indirectly in its own type annotation. 60 | src/util/index.ts(9,21): error TS1149: File name '/media/tycho/Drogon/Coding/js/typical/src/util/the.ts' differs from already included file name '/media/tycho/Drogon/Coding/js/typical/src/util/The.ts' only in casing. 61 | tests/array.test.ts(6,7): error TS2339: Property 'stackTraceLimit' does not exist on type 'ErrorConstructor'. 62 | tests/array.test.ts(240,44): error TS2344: Type '{ length: 2; }' does not satisfy the constraint '{ 0: "a"; 1: "b"; length: 2; }'. 63 | Property '0' is missing in type '{ length: 2; }'. 64 | tests/boolean.test.ts(24,23): error TS2344: Type '"2"' does not satisfy the constraint 'Bool'. 65 | tests/boolean.test.ts(30,22): error TS2344: Type '"true"' does not satisfy the constraint 'Bool'. 66 | tests/boolean.test.ts(36,22): error TS2344: Type '"false"' does not satisfy the constraint 'Bool'. 67 | tests/boolean.test.ts(42,20): error TS2344: Type 'any' does not satisfy the constraint 'never'. 68 | tests/boolean.test.ts(54,22): error TS2344: Type 'true' does not satisfy the constraint 'Bool'. 69 | tests/boolean.test.ts(60,22): error TS2344: Type 'false' does not satisfy the constraint 'Bool'. 70 | tests/boolean.test.ts(188,18): error TS2344: Type '"0"' does not satisfy the constraint '"1"'. 71 | tests/boolean.test.ts(204,18): error TS2344: Type '"0"' does not satisfy the constraint '"1"'. 72 | tests/cast.test.ts(24,18): error TS2315: Type 'NumberToString' is not generic. 73 | tests/comp.test.ts(26,18): error TS2344: Type '"0"' does not satisfy the constraint '"1"'. 74 | tests/comp.test.ts(38,18): error TS2344: Type '"0"' does not satisfy the constraint '"1"'. 75 | tests/comp.test.ts(38,36): error TS2344: Type '"123"' does not satisfy the constraint 'number'. 76 | tests/comp.test.ts(44,18): error TS2344: Type '"0"' does not satisfy the constraint '"1"'. 77 | tests/comp.test.ts(44,31): error TS2344: Type '"123"' does not satisfy the constraint 'number'. 78 | tests/crap.ts(45,5): error TS2322: Type '[number, string, string]' is not assignable to type '[number, string]'. 79 | Types of property 'length' are incompatible. 80 | Type '3' is not assignable to type '2'. 81 | tests/crap.ts(46,5): error TS2322: Type 'ArrProto<[1, "a", "b"]>' is not assignable to type '[number, string]'. 82 | Types of property 'length' are incompatible. 83 | Type '3' is not assignable to type '2'. 84 | tests/object.test.ts(69,39): error TS2344: Type '1' does not satisfy the constraint 'string'. 85 | tests/object.test.ts(75,39): error TS2344: Type '-1' does not satisfy the constraint 'string'. 86 | tests/object.test.ts(81,18): error TS2344: Type '() => string' does not satisfy the constraint '"0"'. 87 | tests/object.test.ts(112,18): error TS2344: Type '"0"' does not satisfy the constraint '"1"'. 88 | tests/object.test.ts(136,18): error TS2344: Type '"1"' does not satisfy the constraint '"0"'. 89 | tests/object.test.ts(154,18): error TS2344: Type '"1"' does not satisfy the constraint '"0"'. 90 | tests/object.test.ts(167,18): error TS2344: Type '"1"' does not satisfy the constraint '"0"'. 91 | tests/object.test.ts(179,18): error TS2344: Type '"1"' does not satisfy the constraint '"0"'. 92 | tests/object.test.ts(226,20): error TS2344: Type 'any' does not satisfy the constraint 'never'. 93 | tests/object.test.ts(232,20): error TS2344: Type '() => string' does not satisfy the constraint 'never'. 94 | tests/object.test.ts(244,20): error TS2344: Type 'any' does not satisfy the constraint 'never'. 95 | tests/object.test.ts(458,56): error TS2344: Type '{ a: 1; }' does not satisfy the constraint 'StripIndex<{ [k: string]: number; a: 1; }>'. 96 | Property 'a' is incompatible with index signature. 97 | Type '1' is not assignable to type 'never'. 98 | tests/object.test.ts(485,21): error TS2344: Type 'number' does not satisfy the constraint 'string'. 99 | tests/object.test.ts(486,21): error TS2344: Type 'boolean' does not satisfy the constraint 'string'. 100 | tests/object.test.ts(530,30): error TS2344: Type 'DeepRequiredObject<{ a?: { b?: 1 | undefined; } | undefined; }>' does not satisfy the constraint '{ a: { b: 1; }; }'. 101 | Types of property 'a' are incompatible. 102 | Type 'DeepRequiredObject<{ b?: 1 | undefined; }> | undefined' is not assignable to type '{ b: 1; }'. 103 | Type 'undefined' is not assignable to type '{ b: 1; }'. 104 | tests/object.test.ts(580,16): error TS2540: Cannot assign to 'id' because it is a constant or a read-only property. 105 | tests/object.test.ts(588,11): error TS2542: Index signature in type 'DeepReadonlyArray' only permits reading. 106 | tests/object.test.ts(596,28): error TS2540: Cannot assign to 'id' because it is a constant or a read-only property. 107 | tests/object.test.ts(604,16): error TS2339: Property 'updatePart' does not exist on type 'DeepReadonlyObject'. 108 | tests/object.test.ts(615,18): error TS2344: Type 'string' does not satisfy the constraint '"a"'. 109 | tests/object.test.ts(625,23): error TS2344: Type 'Pick<{ [k: string]: number; a: 1; }, string>' does not satisfy the constraint '{ a: 1; }'. 110 | Property 'a' is missing in type 'Pick<{ [k: string]: number; a: 1; }, string>'. 111 | tests/object.test.ts(715,18): error TS2344: Type '"a" | undefined' does not satisfy the constraint '"a"'. 112 | Type 'undefined' is not assignable to type '"a"'. 113 | tests/object.test.ts(735,18): error TS2344: Type '"b" | undefined' does not satisfy the constraint '"b"'. 114 | Type 'undefined' is not assignable to type '"b"'. 115 | tests/object.test.ts(790,18): error TS2344: Type '"1"' does not satisfy the constraint '"0"'. 116 | tests/object.test.ts(796,18): error TS2344: Type '"1"' does not satisfy the constraint '"0"'. 117 | tests/ramda.test.ts(90,13): error TS2322: Type '0' is not assignable to type 'string'. 118 | tests/ramda.test.ts(98,13): error TS2322: Type '{}' is not assignable to type 'string'. 119 | tests/ramda.test.ts(104,13): error TS2322: Type '{}' is not assignable to type 'string'. 120 | tests/ramda.test.ts(112,13): error TS2322: Type '{}' is not assignable to type 'string'. 121 | tests/ramda.test.ts(118,13): error TS2322: Type 'number' is not assignable to type 'string'. 122 | tests/ramda.test.ts(126,33): error TS2345: Argument of type '(n: number) => number' is not assignable to parameter of type '(x: {}) => number'. 123 | Types of parameters 'n' and 'x' are incompatible. 124 | Type '{}' is not assignable to type 'number'. 125 | tests/ramda.test.ts(132,43): error TS2345: Argument of type '(n: number) => number' is not assignable to parameter of type '(x: {}) => number'. 126 | Types of parameters 'n' and 'x' are incompatible. 127 | Type '{}' is not assignable to type 'number'. 128 | tests/tuple.test.ts(20,60): error TS2344: Type 'Spread' does not satisfy the constraint '{ 0: "a"; 1: "b"; 2: "c"; 3: "d"; length: 4; }'. 129 | Property '0' is missing in type 'Spread'. 130 | tests/tuple.test.ts(64,44): error TS2344: Type '{ length: 2; }' does not satisfy the constraint '{ 0: "a"; 1: "b"; length: 2; }'. 131 | Property '0' is missing in type '{ length: 2; }'. 132 | tests/tuple.test.ts(75,44): error TS2344: Type '{ length: 2; }' does not satisfy the constraint '{ 0: "a"; 1: "b"; length: 2; }'. 133 | Property '0' is missing in type '{ length: 2; }'. 134 | tests/union.test.ts(6,21): error TS2307: Cannot find module './boolean'. 135 | tests/union.test.ts(50,18): error TS2344: Type '() => string' does not satisfy the constraint '"0"'. 136 | tests/union.test.ts(71,18): error TS2344: Type '"0"' does not satisfy the constraint '"1"'. 137 | tests/union.test.ts(77,18): error TS2344: Type '"0"' does not satisfy the constraint '"1"'. 138 | tests/union.test.ts(99,18): error TS2344: Type '"0"' does not satisfy the constraint '"1"'. 139 | tests/union.test.ts(139,18): error TS2344: Type '"1"' does not satisfy the constraint '"0"'. 140 | tests/union.test.ts(149,18): error TS2344: Type '"0"' does not satisfy the constraint '"1"'. 141 | tests/union.test.ts(167,26): error TS2344: Type '"a" | undefined' does not satisfy the constraint 'string'. 142 | Type 'undefined' is not assignable to type 'string'. 143 | tests/util.test.ts(16,21): error TS2344: Type '123' does not satisfy the constraint 'string'. 144 | tests/util.test.ts(22,20): error TS2344: Type 'string' does not satisfy the constraint 'never'. 145 | -------------------------------------------------------------------------------- /tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Basic Options */ 4 | "target": "ESNEXT", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'. */ 5 | "module": "commonjs", /* Specify module code generation: 'commonjs', 'amd', 'system', 'umd' or 'es2015'. */ 6 | // "lib": [], /* Specify library files to be included in the compilation: */ 7 | // "allowJs": true, /* Allow javascript files to be compiled. */ 8 | // "checkJs": true, /* Report errors in .js files. */ 9 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ 10 | // "declaration": true, /* Generates corresponding '.d.ts' file. */ 11 | // "sourceMap": true, /* Generates corresponding '.map' file. */ 12 | // "outFile": "./", /* Concatenate and emit output to single file. */ 13 | "outDir": "./lib", /* Redirect output structure to the directory. */ 14 | // "rootDirs": ["src"], 15 | // "removeComments": true, /* Do not emit comments to output. */ 16 | // "noEmit": true, /* Do not emit outputs. */ 17 | "noEmitOnError": false, 18 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 19 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 20 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 21 | /* Strict Type-Checking Options */ 22 | "strict": true /* Enable all strict type-checking options. */ 23 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 24 | // "strictNullChecks": true, /* Enable strict null checks. */ 25 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 26 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 27 | /* Additional Checks */ 28 | // "noUnusedLocals": true, /* Report errors on unused locals. */ 29 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 30 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 31 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 32 | /* Module Resolution Options */ 33 | // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 34 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 35 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 36 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 37 | // "typeRoots": [], /* List of folders to include type definitions from. */ 38 | // "types": [], /* Type declaration files to be included in compilation. */ 39 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 40 | /* Source Map Options */ 41 | // "sourceRoot": "./", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 42 | // "mapRoot": "./", /* Specify the location where debugger should locate map files instead of generated locations. */ 43 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 44 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 45 | /* Experimental Options */ 46 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 47 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 48 | }, 49 | "include": [ 50 | "src" 51 | ], 52 | "exclude": [ 53 | "node_modules" 54 | ] 55 | } 56 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Basic Options */ 4 | "target": "ESNEXT", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'. */ 5 | "module": "commonjs", /* Specify module code generation: 'commonjs', 'amd', 'system', 'umd' or 'es2015'. */ 6 | // "lib": [], /* Specify library files to be included in the compilation: */ 7 | // "allowJs": true, /* Allow javascript files to be compiled. */ 8 | // "checkJs": true, /* Report errors in .js files. */ 9 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ 10 | // "declaration": true, /* Generates corresponding '.d.ts' file. */ 11 | // "sourceMap": true, /* Generates corresponding '.map' file. */ 12 | // "outFile": "./", /* Concatenate and emit output to single file. */ 13 | "outDir": "./lib", /* Redirect output structure to the directory. */ 14 | // "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 15 | "rootDirs": ["src"], 16 | // "removeComments": true, /* Do not emit comments to output. */ 17 | // "noEmit": true, /* Do not emit outputs. */ 18 | "noEmitOnError": false, 19 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 20 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 21 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 22 | 23 | /* Strict Type-Checking Options */ 24 | "strict": true /* Enable all strict type-checking options. */ 25 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 26 | // "strictNullChecks": true, /* Enable strict null checks. */ 27 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 28 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 29 | 30 | /* Additional Checks */ 31 | // "noUnusedLocals": true, /* Report errors on unused locals. */ 32 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 33 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 34 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 35 | 36 | /* Module Resolution Options */ 37 | // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 38 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 39 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 40 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 41 | // "typeRoots": [], /* List of folders to include type definitions from. */ 42 | // "types": [], /* Type declaration files to be included in compilation. */ 43 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 44 | 45 | /* Source Map Options */ 46 | // "sourceRoot": "./", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 47 | // "mapRoot": "./", /* Specify the location where debugger should locate map files instead of generated locations. */ 48 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 49 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 50 | 51 | /* Experimental Options */ 52 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 53 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 54 | }, 55 | "exclude": [ 56 | "node_modules" 57 | ] 58 | } 59 | --------------------------------------------------------------------------------