inferred-types 0.37.0 → 0.37.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (280) hide show
  1. package/dist/index.d.ts +2745 -0
  2. package/dist/index.js +854 -0
  3. package/package.json +6 -12
  4. package/.eslintrc +0 -77
  5. package/.github/workflows/main.yml +0 -34
  6. package/.github/workflows/other.yml +0 -15
  7. package/.nvmrc +0 -1
  8. package/.prettierrc.js +0 -3
  9. package/.vscode/launch.json +0 -27
  10. package/.vscode/settings.json +0 -19
  11. package/devops/build.js +0 -243
  12. package/docs/builder-overview.md +0 -45
  13. package/docs/builder.md +0 -94
  14. package/src/errors/ReadOnlyViolation.ts +0 -3
  15. package/src/errors/index.ts +0 -12
  16. package/src/index.ts +0 -14
  17. package/src/runtime/README.md +0 -3
  18. package/src/runtime/api/api.ts +0 -10
  19. package/src/runtime/api/index.ts +0 -12
  20. package/src/runtime/builders/Model.ts +0 -25
  21. package/src/runtime/builders/url.ts +0 -15
  22. package/src/runtime/combinators/and.ts +0 -15
  23. package/src/runtime/combinators/filter.ts +0 -267
  24. package/src/runtime/combinators/index.ts +0 -4
  25. package/src/runtime/combinators/not.ts +0 -15
  26. package/src/runtime/combinators/or.ts +0 -5
  27. package/src/runtime/createFnWithProps.ts +0 -37
  28. package/src/runtime/dictionary/arrayToKeyLookup.ts +0 -19
  29. package/src/runtime/dictionary/defineProperties.ts +0 -35
  30. package/src/runtime/dictionary/dictArr.ts +0 -69
  31. package/src/runtime/dictionary/dictionaryTransform.ts +0 -22
  32. package/src/runtime/dictionary/entries.ts +0 -33
  33. package/src/runtime/dictionary/index.ts +0 -21
  34. package/src/runtime/dictionary/kv/dictToKv.ts +0 -21
  35. package/src/runtime/dictionary/kv/filterDictArray.ts +0 -31
  36. package/src/runtime/dictionary/kv/index.ts +0 -15
  37. package/src/runtime/dictionary/kv/kv.ts +0 -18
  38. package/src/runtime/dictionary/kv/kvToDict.ts +0 -24
  39. package/src/runtime/dictionary/mapTo.ts +0 -206
  40. package/src/runtime/dictionary/mapValues.ts +0 -23
  41. package/src/runtime/dictionary/merge.ts +0 -36
  42. package/src/runtime/dictionary/strArrayToDict.ts +0 -12
  43. package/src/runtime/index.ts +0 -23
  44. package/src/runtime/keys.ts +0 -16
  45. package/src/runtime/lists/asArray.ts +0 -38
  46. package/src/runtime/lists/createConverter.ts +0 -62
  47. package/src/runtime/lists/groupBy.ts +0 -15
  48. package/src/runtime/lists/index.ts +0 -15
  49. package/src/runtime/literals/ExplicitFunction.ts +0 -10
  50. package/src/runtime/literals/Suggest.ts +0 -19
  51. package/src/runtime/literals/arrayToObject.ts +0 -78
  52. package/src/runtime/literals/box.ts +0 -98
  53. package/src/runtime/literals/defineType.ts +0 -20
  54. package/src/runtime/literals/ensureLeading.ts +0 -17
  55. package/src/runtime/literals/ensureTrailing.ts +0 -17
  56. package/src/runtime/literals/identity.ts +0 -12
  57. package/src/runtime/literals/index.ts +0 -23
  58. package/src/runtime/literals/literal.ts +0 -48
  59. package/src/runtime/literals/pathJoin.ts +0 -33
  60. package/src/runtime/literals/stripLeading.ts +0 -15
  61. package/src/runtime/literals/stripTrailing.ts +0 -15
  62. package/src/runtime/literals/wide.ts +0 -13
  63. package/src/runtime/ruleset.ts +0 -42
  64. package/src/runtime/runtime/README.md +0 -3
  65. package/src/runtime/runtime/condition.ts +0 -13
  66. package/src/runtime/runtime/index.ts +0 -16
  67. package/src/runtime/runtime/type.ts +0 -127
  68. package/src/runtime/runtime/withValue.ts +0 -39
  69. package/src/runtime/state/Configurator.ts +0 -76
  70. package/src/runtime/state/FluentConfigurator.ts +0 -49
  71. package/src/runtime/state/index.ts +0 -13
  72. package/src/runtime/type-checks/ifSameType.ts +0 -20
  73. package/src/runtime/type-checks/ifTypeOf.ts +0 -124
  74. package/src/runtime/type-checks/index.ts +0 -24
  75. package/src/runtime/type-checks/isArray.ts +0 -34
  76. package/src/runtime/type-checks/isBoolean.ts +0 -24
  77. package/src/runtime/type-checks/isFalse.ts +0 -29
  78. package/src/runtime/type-checks/isFunction.ts +0 -26
  79. package/src/runtime/type-checks/isNull.ts +0 -26
  80. package/src/runtime/type-checks/isNumber.ts +0 -20
  81. package/src/runtime/type-checks/isObject.ts +0 -22
  82. package/src/runtime/type-checks/isString.ts +0 -34
  83. package/src/runtime/type-checks/isSymbol.ts +0 -3
  84. package/src/runtime/type-checks/isTrue.ts +0 -31
  85. package/src/runtime/type-checks/isUndefined.ts +0 -33
  86. package/src/runtime/type-checks/startsWith.ts +0 -107
  87. package/src/runtime/valueTypes.ts +0 -48
  88. package/src/types/Api.ts +0 -16
  89. package/src/types/Constructor.ts +0 -5
  90. package/src/types/EnumValues.ts +0 -14
  91. package/src/types/ExpandRecursively.ts +0 -12
  92. package/src/types/FunctionType.ts +0 -19
  93. package/src/types/If.ts +0 -10
  94. package/src/types/Include.ts +0 -18
  95. package/src/types/KeyedRecord.ts +0 -21
  96. package/src/types/Keys.ts +0 -26
  97. package/src/types/Length.ts +0 -8
  98. package/src/types/Mutable.ts +0 -8
  99. package/src/types/Narrowable.ts +0 -5
  100. package/src/types/Not.ts +0 -13
  101. package/src/types/Numeric.ts +0 -20
  102. package/src/types/Opaque.ts +0 -11
  103. package/src/types/README.md +0 -3
  104. package/src/types/Retain.ts +0 -16
  105. package/src/types/SimplifyObject.ts +0 -12
  106. package/src/types/Transformer.ts +0 -15
  107. package/src/types/TypeGuard.ts +0 -7
  108. package/src/types/Where.ts +0 -40
  109. package/src/types/alphabetic/AllCaps.ts +0 -15
  110. package/src/types/alphabetic/CamelCase.ts +0 -3
  111. package/src/types/alphabetic/CapFirstAlpha.ts +0 -23
  112. package/src/types/alphabetic/CapitalizeWords.ts +0 -9
  113. package/src/types/alphabetic/Cardinality.ts +0 -80
  114. package/src/types/alphabetic/DashToSnake.ts +0 -3
  115. package/src/types/alphabetic/DashUppercase.ts +0 -19
  116. package/src/types/alphabetic/Dasherize.ts +0 -23
  117. package/src/types/alphabetic/EnsureLeading.ts +0 -24
  118. package/src/types/alphabetic/EnsureTrailing.ts +0 -24
  119. package/src/types/alphabetic/HasUppercase.ts +0 -16
  120. package/src/types/alphabetic/IsCapitalized.ts +0 -18
  121. package/src/types/alphabetic/KebabCase.ts +0 -13
  122. package/src/types/alphabetic/LowerAllCaps.ts +0 -5
  123. package/src/types/alphabetic/PascalCase.ts +0 -29
  124. package/src/types/alphabetic/PathJoin.ts +0 -54
  125. package/src/types/alphabetic/Pluralize.ts +0 -112
  126. package/src/types/alphabetic/SnakeCase.ts +0 -27
  127. package/src/types/alphabetic/StripLeading.ts +0 -23
  128. package/src/types/alphabetic/StripTrailing.ts +0 -23
  129. package/src/types/alphabetic/Url.ts +0 -29
  130. package/src/types/alphabetic/alpha-characters.ts +0 -81
  131. package/src/types/alphabetic/index.ts +0 -32
  132. package/src/types/append-types.ts +0 -10
  133. package/src/types/boolean-logic/EndsWith.ts +0 -40
  134. package/src/types/boolean-logic/Extends.ts +0 -22
  135. package/src/types/boolean-logic/HasParameters.ts +0 -21
  136. package/src/types/boolean-logic/Includes.ts +0 -33
  137. package/src/types/boolean-logic/IsLiteral.ts +0 -101
  138. package/src/types/boolean-logic/IsScalar.ts +0 -20
  139. package/src/types/boolean-logic/IsUndefined.ts +0 -20
  140. package/src/types/boolean-logic/Or.ts +0 -12
  141. package/src/types/boolean-logic/StartsWith.ts +0 -42
  142. package/src/types/boolean-logic/TypeDefault.ts +0 -58
  143. package/src/types/boolean-logic/array.ts +0 -57
  144. package/src/types/boolean-logic/boolean.ts +0 -84
  145. package/src/types/boolean-logic/equivalency.ts +0 -15
  146. package/src/types/boolean-logic/index.ts +0 -14
  147. package/src/types/boolean-logic/object.ts +0 -30
  148. package/src/types/boolean-logic/string.ts +0 -21
  149. package/src/types/dictionary/DictChangeValue.ts +0 -34
  150. package/src/types/dictionary/DictPartialApplication.ts +0 -30
  151. package/src/types/dictionary/DictPrependWithFn.ts +0 -23
  152. package/src/types/dictionary/DictReturnValues.ts +0 -27
  153. package/src/types/dictionary/Get.ts +0 -14
  154. package/src/types/dictionary/MapTo.ts +0 -428
  155. package/src/types/dictionary/MutableProps.ts +0 -19
  156. package/src/types/dictionary/RequireProps.ts +0 -15
  157. package/src/types/dictionary/SameKeys.ts +0 -11
  158. package/src/types/dictionary/index.ts +0 -21
  159. package/src/types/dictionary/props.ts +0 -145
  160. package/src/types/fluent/fluent.ts +0 -61
  161. package/src/types/fluent/index.ts +0 -12
  162. package/src/types/functions/FinalReturn.ts +0 -12
  163. package/src/types/functions/LogicFunction.ts +0 -4
  164. package/src/types/functions/index.ts +0 -13
  165. package/src/types/index.ts +0 -49
  166. package/src/types/kv/DictFromKv.ts +0 -3
  167. package/src/types/kv/KeyValue.ts +0 -12
  168. package/src/types/kv/KvFrom.ts +0 -8
  169. package/src/types/kv/KvTuple.ts +0 -14
  170. package/src/types/kv/index.ts +0 -15
  171. package/src/types/lists/AfterFirst.ts +0 -10
  172. package/src/types/lists/ConvertAndMap.ts +0 -152
  173. package/src/types/lists/FilterTuple.ts +0 -20
  174. package/src/types/lists/First.ts +0 -8
  175. package/src/types/lists/FirstString.ts +0 -4
  176. package/src/types/lists/Split.ts +0 -21
  177. package/src/types/lists/UniqueForProp.ts +0 -18
  178. package/src/types/lists/index.ts +0 -18
  179. package/src/types/literal-unions/OptRequired.ts +0 -4
  180. package/src/types/literal-unions/index.ts +0 -1
  181. package/src/types/maybe.ts +0 -9
  182. package/src/types/ruleset-types.ts +0 -76
  183. package/src/types/runtime.ts +0 -39
  184. package/src/types/string-literals/Break.ts +0 -22
  185. package/src/types/string-literals/Concat.ts +0 -9
  186. package/src/types/string-literals/LeftWhitespace.ts +0 -13
  187. package/src/types/string-literals/Replace.ts +0 -17
  188. package/src/types/string-literals/RightWhitespace.ts +0 -13
  189. package/src/types/string-literals/StringLength.ts +0 -34
  190. package/src/types/string-literals/Trim.ts +0 -15
  191. package/src/types/string-literals/TrimLeft.ts +0 -14
  192. package/src/types/string-literals/TrimRight.ts +0 -14
  193. package/src/types/string-literals/form-fields.ts +0 -15
  194. package/src/types/string-literals/index.ts +0 -21
  195. package/src/types/tuples/DictArray.ts +0 -21
  196. package/src/types/tuples/FirstKey.ts +0 -10
  197. package/src/types/tuples/FirstKeyValue.ts +0 -9
  198. package/src/types/tuples/FirstOfEach.ts +0 -13
  199. package/src/types/tuples/FromDictArray.ts +0 -14
  200. package/src/types/tuples/SecondOfEach.ts +0 -13
  201. package/src/types/tuples/index.ts +0 -17
  202. package/src/types/type-conversion/TupleToUnion.ts +0 -9
  203. package/src/types/type-conversion/UnionToIntersection.ts +0 -9
  204. package/src/types/type-conversion/UnionToTuple.ts +0 -20
  205. package/src/types/type-conversion/Widen.ts +0 -22
  206. package/src/types/type-conversion/index.ts +0 -16
  207. package/src/types/type-testing.ts +0 -14
  208. package/tests/CamelCase-spec.ts +0 -20
  209. package/tests/Configurator-spec.hold +0 -106
  210. package/tests/ExplicitFunction-spec.ts +0 -50
  211. package/tests/IncludeAndRetain-spec.ts +0 -67
  212. package/tests/Includes-spec.ts +0 -36
  213. package/tests/KebabCase-spec.ts +0 -21
  214. package/tests/PascalCase-spec.ts +0 -22
  215. package/tests/Pluralize-spec.ts +0 -23
  216. package/tests/SnakeCase-spec.ts +0 -21
  217. package/tests/Where.spec.ts +0 -38
  218. package/tests/arrayToKeyLookup-spec.ts +0 -17
  219. package/tests/arrayToObject-spec.ts +0 -115
  220. package/tests/boolean-logic/Contains.test.ts +0 -55
  221. package/tests/boolean-logic/HasParameters.ts +0 -29
  222. package/tests/boolean-logic/IsLiteral.spec.ts +0 -65
  223. package/tests/boolean-logic/boolean.spec.ts +0 -21
  224. package/tests/boolean-logic/filter.spec.ts +0 -52
  225. package/tests/constructor.spec.ts +0 -42
  226. package/tests/createFnWithProps.spec.ts +0 -14
  227. package/tests/data/SimpleTable.hold +0 -21
  228. package/tests/data/index.ts +0 -12
  229. package/tests/data/playlist.hold +0 -25
  230. package/tests/data/song.hold +0 -23
  231. package/tests/defineType-spec.ts +0 -57
  232. package/tests/dictionary/DictChangeValue.test.ts +0 -30
  233. package/tests/dictionary/DictPartialApplication.test.ts +0 -43
  234. package/tests/dictionary/DictReturnValues.test.ts +0 -36
  235. package/tests/dictionary/Get.spec.ts +0 -28
  236. package/tests/dictionary/IntersectingKeys.test.ts +0 -42
  237. package/tests/dictionary/MutableProps.test.ts +0 -30
  238. package/tests/dictionary/OptionalKeys.test.ts +0 -24
  239. package/tests/dictionary/PrependValuesWithFunction.test.ts +0 -34
  240. package/tests/dictionary/RequireProps.test.ts +0 -21
  241. package/tests/dictionary/RequiredKeys.test.ts +0 -53
  242. package/tests/dictionary/TypeDefault.test.ts +0 -76
  243. package/tests/dictionary/mapTo.test.ts +0 -388
  244. package/tests/dictionary/merge.test.ts +0 -41
  245. package/tests/dictionaryTransform-spec.ts +0 -280
  246. package/tests/ifTypeOf-spec.ts +0 -191
  247. package/tests/kv/KeyValue-spec.ts +0 -22
  248. package/tests/kv/SameKeys-spec.ts +0 -35
  249. package/tests/kv/dict-to-kv-and-back.spec.ts +0 -169
  250. package/tests/kv/entries-spec.ts +0 -65
  251. package/tests/kv/keys.spec.ts +0 -66
  252. package/tests/kv/kv-spec.ts +0 -20
  253. package/tests/lists/First.test.ts +0 -43
  254. package/tests/lists/Length.test.ts +0 -19
  255. package/tests/lists/Split.test.ts +0 -29
  256. package/tests/lists/UniqueForProp.spec.ts +0 -59
  257. package/tests/lists/asArray.test.ts +0 -109
  258. package/tests/lists/dictArr.test.ts +0 -110
  259. package/tests/literal-spec.ts +0 -82
  260. package/tests/literals/AllCaps.spec.ts +0 -33
  261. package/tests/literals/CamelCase.spec.ts +0 -109
  262. package/tests/literals/Dasherize.spec.ts +0 -107
  263. package/tests/literals/EnsureStripLeadingTrailing.test.ts +0 -79
  264. package/tests/literals/HasUppercase.spec.ts +0 -33
  265. package/tests/literals/PascalCase.spec.ts +0 -109
  266. package/tests/literals/PathJoin.test.ts +0 -111
  267. package/tests/literals/SnakeCase.spec.ts +0 -109
  268. package/tests/literals/box.test.ts +0 -85
  269. package/tests/literals/whitespace-capture.spec.ts +0 -60
  270. package/tests/mapValues-spec.ts +0 -50
  271. package/tests/props-spec.ts +0 -234
  272. package/tests/runtime/condition.spec.ts +0 -19
  273. package/tests/runtime/if-is.spec.ts +0 -390
  274. package/tests/runtime/map-and-convert.test.ts +0 -31
  275. package/tests/runtime/type.spec.ts +0 -190
  276. package/tests/strArrayToDict-spec.ts +0 -40
  277. package/tests/tuples/TupleToUnion.spec.ts +0 -20
  278. package/tests/withValue.spec.ts +0 -173
  279. package/tsconfig.json +0 -36
  280. package/vitest.config.ts +0 -17
@@ -1,280 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { dictionaryTransform, ExplicitFunction } from "../src/runtime";
3
- import { Expect, Equal, NotEqual, ExpectExtends, ExpectFalse } from "@type-challenges/utils";
4
- import { ToFluent, Transformer } from "../src/types";
5
-
6
- describe("dictionaryTransform()", () => {
7
- type A = { foo: string; bar: string };
8
- const a: A = { foo: "1", bar: "2" };
9
- type F = { foo: () => string; bar: () => string };
10
- const f: F = { foo: () => "1", bar: () => "2" };
11
- type F2 = { foo: (n: number) => string; bar: (a: number, b: number) => string };
12
- // const f2: F2 = { foo: (n: number) => `${n}`, bar: (a: number, b: number) => `${a * b}` };
13
-
14
- // B typed
15
- type B = { foo: number; bar: number };
16
- // B typed as literal
17
- type BL = { foo: 1; bar: 2 };
18
- const b = { foo: 1, bar: 2 };
19
- // B inferred
20
- type BI = typeof b;
21
-
22
- const createMutationApi = (state: { foo: number }) => {
23
- const api = {
24
- increment() {
25
- return { ...state, foo: state.foo + 1 };
26
- },
27
- decrement() {
28
- return { ...state, foo: state.foo - 1 };
29
- },
30
- set(v: number) {
31
- return { ...state, foo: v };
32
- },
33
-
34
- getState() {
35
- return state;
36
- },
37
- };
38
-
39
- return api;
40
- };
41
-
42
- type State = { foo: number };
43
- const state: State = { foo: 0 };
44
-
45
- type MutApi = { inc: () => State; dec: () => State; set: (n: number) => State };
46
- const mutApi: MutApi = {
47
- inc() {
48
- return { ...state, foo: state.foo + 1 };
49
- },
50
- dec() {
51
- return { ...state, foo: state.foo - 1 };
52
- },
53
- set(n: number) {
54
- return { ...state, foo: n };
55
- },
56
- };
57
- type FluentApi = { inc: () => FluentApi; dec: () => FluentApi; set: (n: number) => FluentApi };
58
- const fluentApi: FluentApi = {
59
- inc() {
60
- state.foo = mutApi.inc().foo;
61
- return fluentApi;
62
- },
63
- dec() {
64
- state.foo = mutApi.dec().foo;
65
- return fluentApi;
66
- },
67
- set(n: number) {
68
- state.foo = mutApi.set(n).foo;
69
- return fluentApi;
70
- },
71
- };
72
- type SyntheticFluent = ToFluent<MutApi>;
73
-
74
- it("simple dictionary with strings converted to numbers", () => {
75
- const transform: Transformer<A, B> = (i, k) => {
76
- return Number(i[k]);
77
- };
78
-
79
- const t = dictionaryTransform(a, transform);
80
- type T = typeof t;
81
-
82
- type cases = [
83
- // wide type of string should now be number
84
- Expect<Equal<T, B>>,
85
- Expect<Equal<T, BI>>,
86
- Expect<ExpectExtends<T, B>>,
87
- Expect<ExpectExtends<T, BI>>,
88
- // literals will not be involved here
89
- Expect<NotEqual<T, BL>>,
90
- // the literal _does_ extend the wider type
91
- Expect<ExpectExtends<T, BL>>,
92
- // but not the reverse
93
- ExpectFalse<ExpectExtends<BL, T>>
94
- ];
95
-
96
- const cases: cases = [true, true, true, true, true, true, false];
97
- expect(cases).toBe(cases);
98
- });
99
-
100
- it("simple function based dictionary <F> converted to numbers <B>", () => {
101
- const transform: Transformer<F, B> = (i, k) => {
102
- return Number(i[k]());
103
- };
104
- const t = dictionaryTransform(f, transform);
105
- type T = typeof t;
106
-
107
- type cases = [
108
- // wide type of string should now be number
109
- Expect<Equal<T, B>>,
110
- Expect<Equal<T, BI>>,
111
- Expect<ExpectExtends<T, B>>,
112
- Expect<ExpectExtends<T, BI>>,
113
- // literals will not be involved here
114
- Expect<NotEqual<T, BL>>,
115
- // the literal _does_ extend the wider type
116
- Expect<ExpectExtends<T, BL>>,
117
- // but not the reverse
118
- ExpectFalse<ExpectExtends<BL, T>>
119
- ];
120
-
121
- const cases: cases = [true, true, true, true, true, true, false];
122
- expect(cases).toBe(cases);
123
- });
124
-
125
- it("function with variant parameters <F2> converted to numbers <B>", () => {
126
- const transform: Transformer<F2, B> = (i, k) => {
127
- switch (k) {
128
- case "foo":
129
- return Number(i[k](4));
130
- case "bar":
131
- return Number(i[k](1, 2));
132
- }
133
- };
134
- const t = dictionaryTransform(f, transform);
135
- type T = typeof t;
136
-
137
- type cases = [
138
- // wide type of string should now be number
139
- Expect<Equal<T, B>>,
140
- Expect<Equal<T, BI>>,
141
- Expect<ExpectExtends<T, B>>,
142
- Expect<ExpectExtends<T, BI>>,
143
- // literals will not be involved here
144
- Expect<NotEqual<T, BL>>,
145
- // the literal _does_ extend the wider type
146
- Expect<ExpectExtends<T, BL>>,
147
- // but not the reverse
148
- ExpectFalse<ExpectExtends<BL, T>>
149
- ];
150
-
151
- const cases: cases = [true, true, true, true, true, true, false];
152
- expect(cases).toBe(cases);
153
- });
154
-
155
- it("A mutation function can can be transformed into a fluent API", () => {
156
- const state = { foo: 0 };
157
- const api = createMutationApi(state);
158
- type A = typeof api;
159
- // the mutation api performs as expected
160
- // this includes returning the state after any call
161
- expect(api.increment().foo).toBe(1);
162
- expect(api.decrement().foo).toBe(-1);
163
- // the one exception is getState which just returns the value
164
- expect(api.getState().foo).toBe(0);
165
-
166
- // transform function
167
- const transform: Transformer<A, ToFluent<A>> = (i, k) => {
168
- switch (k) {
169
- case "getState":
170
- return () => {
171
- return dictionaryTransform(api, transform);
172
- };
173
- case "set":
174
- case "decrement":
175
- case "increment":
176
- const fn = ExplicitFunction(i[k]);
177
- return (...args: Parameters<typeof fn>) => {
178
- fn(...args);
179
- // this is cheating as runtime is not updated
180
- return dictionaryTransform(api, transform);
181
- };
182
- }
183
- };
184
-
185
- const t = dictionaryTransform(api, transform);
186
- type T = typeof t;
187
-
188
- // the transformed API is fluent and so calls to the API should return
189
- // the same API surface
190
- expect(typeof t.increment().increment).toBe("function");
191
- expect(typeof t.decrement().increment).toBe("function");
192
- // this even applies to getState() which no longer has any useful utility
193
- expect(typeof t.getState().increment).toBe("function");
194
- // this pattern should continue indefinitely
195
- expect(typeof t.increment().decrement().increment().decrement).toBe("function");
196
-
197
- // beyond the run-time system, we must check that all types are expected
198
- type cases = [
199
- // All functions return the same API defined by T
200
- Expect<Equal<ReturnType<T["increment"]>, T>>,
201
- Expect<Equal<ReturnType<T["decrement"]>, T>>,
202
- Expect<Equal<ReturnType<T["set"]>, T>>,
203
- Expect<Equal<ReturnType<T["getState"]>, T>>,
204
- // set() has a distinct set of parameters from other methods
205
- Expect<NotEqual<Parameters<T["increment"]>, Parameters<T["set"]>>>,
206
- // whereas the rest on this API are the same
207
- Expect<Equal<Parameters<T["increment"]>, Parameters<T["decrement"]>>>
208
- ];
209
- const cases: cases = [true, true, true, true, true, true];
210
- expect(cases).toBe(cases);
211
- });
212
-
213
- it("Explicit mutation API and fluent API", () => {
214
- const transform: Transformer<MutApi, FluentApi> = (i, k) => {
215
- switch (k) {
216
- case "dec":
217
- case "inc":
218
- return () => {
219
- i[k](); // mutate state
220
- return fluentApi;
221
- };
222
- case "set":
223
- return (n: number) => {
224
- i[k](n); // mutate state
225
- return fluentApi;
226
- };
227
- }
228
- };
229
-
230
- const t = dictionaryTransform(mutApi, transform);
231
- type T = typeof t;
232
-
233
- type cases = [
234
- // the explicit definition of the Fluent API is
235
- // the same as the synthetic version created with ToFluent
236
- Expect<Equal<FluentApi, SyntheticFluent>>,
237
- // the fluent API derived from the dictionary transform is
238
- // also the same as the explicit and synthetic
239
- Expect<Equal<FluentApi, T>>
240
- ];
241
- const cases: cases = [true, true];
242
- expect(cases).toBe(cases);
243
- });
244
-
245
- it("using dictionaryTransform recursively for fluent API works at both runtime and designtime", () => {
246
- const transform: Transformer<MutApi, FluentApi> = (i, k) => {
247
- switch (k) {
248
- case "dec":
249
- case "inc":
250
- return () => {
251
- state.foo = i[k]().foo; // mutate state, assign to global "state"
252
- return dictionaryTransform(mutApi, transform);
253
- };
254
- case "set":
255
- return (n: number) => {
256
- state.foo = i[k](n).foo; // mutate state
257
- return dictionaryTransform(mutApi, transform);
258
- };
259
- }
260
- };
261
-
262
- const t = dictionaryTransform(mutApi, transform);
263
- type T = typeof t;
264
-
265
- type cases = [
266
- // the fluent API derived from recursive calls to dictionaryTransform
267
- // is seen as the same type the explictly deinfined type.
268
- Expect<Equal<FluentApi, T>>
269
- ];
270
- const cases: cases = [true];
271
- expect(cases).toBe(cases);
272
-
273
- t.set(0);
274
- expect(state.foo).toBe(0);
275
- t.set(1);
276
- expect(state.foo).toBe(1);
277
- t.set(0).inc().inc();
278
- expect(state.foo).toBe(2);
279
- });
280
- });
@@ -1,191 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
-
3
- /* eslint-disable @typescript-eslint/no-unused-vars */
4
- import { Expect, Equal } from "@type-challenges/utils";
5
- import { defineType, literal } from "../src/runtime";
6
- import { ifTypeOf } from "src/runtime/type-checks/ifTypeOf";
7
-
8
- describe("ifTypeOf() utility", () => {
9
- it("base validation with extends() returns true/false", () => {
10
- const target = { foo: "", bar: 0 };
11
- const yup = ifTypeOf({ foo: "foo", bar: 42 }).extends(target);
12
- const nope = ifTypeOf({ foo: "foo", bar: "whoops" }).extends(target);
13
-
14
- expect(yup).toBe(true);
15
- expect(nope).toBe(false);
16
-
17
- type cases = [Expect<Equal<typeof yup, true>>, Expect<Equal<typeof nope, false>>];
18
- const cases: cases = [true, true];
19
- expect(cases).toBe(cases);
20
- });
21
-
22
- it("base validation of narrowlyExtends() returns true/false", () => {
23
- const target = defineType({ bar: 0 })({ foo: "foo" });
24
- const yup = ifTypeOf({ foo: "foo", bar: 0 }).extends(target);
25
- const yup2 = ifTypeOf({ foo: "foey", bar: 0 }).extends(target);
26
- const nope1 = ifTypeOf({ foo: "foo", bar: 42 }).narrowlyExtends(target);
27
- const nope2 = ifTypeOf({ foo: "foo", bar: "whoops" }).extends(target);
28
-
29
- expect(yup).toBe(true);
30
- expect(yup2).toBe(true);
31
- expect(nope1).toBe(false);
32
- expect(nope2).toBe(false);
33
-
34
- type cases = [
35
- Expect<Equal<typeof yup, true>>,
36
- Expect<Equal<typeof yup2, true>>,
37
- Expect<Equal<typeof nope1, false>>,
38
- Expect<Equal<typeof nope2, false>>
39
- ];
40
- const cases: cases = [true, true, true, true];
41
- expect(cases).toBe(cases);
42
- });
43
-
44
- it("validation of non-dictionary types works as expected too", () => {
45
- const target = 42 as number;
46
- const t2 = literal(42);
47
-
48
- const numToNum = ifTypeOf(55).extends(target);
49
- const wideNumCompare = ifTypeOf(0).extends(target);
50
- const narrowEquality = ifTypeOf(42).narrowlyExtends(t2);
51
- const stringIsNumber = ifTypeOf("foo").extends(target);
52
- const diffNumbersNarrowly = ifTypeOf(12).narrowlyExtends(t2);
53
-
54
- expect(numToNum).toBe(true);
55
- expect(wideNumCompare).toBe(true);
56
- expect(narrowEquality).toBe(true);
57
- expect(stringIsNumber).toBe(false);
58
- expect(diffNumbersNarrowly).toBe(false);
59
-
60
- type cases = [
61
- Expect<Equal<typeof numToNum, true>>,
62
- Expect<Equal<typeof wideNumCompare, true>>,
63
- Expect<Equal<typeof narrowEquality, true>>,
64
- Expect<Equal<typeof stringIsNumber, false>>,
65
- Expect<Equal<typeof diffNumbersNarrowly, false>>
66
- ];
67
- const cases: cases = [true, true, true, true, true];
68
- expect(cases).toBe(cases);
69
- });
70
-
71
- it("validation of function types works when expressed widely", () => {
72
- const target: Function = () => "";
73
- const fn = () => "hi";
74
- const fnExtends = ifTypeOf(fn).extends(target);
75
-
76
- expect(fnExtends).toBe(true);
77
-
78
- type cases = [Expect<Equal<typeof fnExtends, true>>];
79
- const cases: cases = [true];
80
- expect(cases).toBe(cases);
81
- });
82
-
83
- it("checklist example", () => {
84
- const noFoodOrDrink = ifTypeOf({ wakeUp: true }).extends({
85
- wakeUp: true,
86
- eatBreakfast: true,
87
- drinkCoffee: true,
88
- });
89
- const ready = ifTypeOf({ wakeUp: true, eatBreakfast: true, drinkCoffee: true }).extends({
90
- wakeUp: true,
91
- eatBreakfast: true,
92
- drinkCoffee: true,
93
- });
94
-
95
- // completely wrong
96
- const fullyBaked = ifTypeOf({ wakeUp: false, eatBreakfast: false, drinkCoffee: false }).extends(
97
- { wakeUp: true, eatBreakfast: true, drinkCoffee: true }
98
- );
99
-
100
- // half-right
101
- const halfBaked = ifTypeOf({ wakeUp: false, eatBreakfast: false, drinkCoffee: false }).extends({
102
- wakeUp: true,
103
- eatBreakfast: true,
104
- drinkCoffee: true,
105
- } as const);
106
-
107
- // back to right; at the cost of being very careful
108
- const lucid = ifTypeOf({
109
- wakeUp: false,
110
- eatBreakfast: false,
111
- drinkCoffee: false,
112
- }).narrowlyExtends({ wakeUp: true, eatBreakfast: true, drinkCoffee: true } as const);
113
-
114
- // run-time tests of False Positives
115
- // ---------------------------------
116
- expect(noFoodOrDrink).toBe(false);
117
- expect(ready).toBe(true);
118
-
119
- // here we'll show how narrow types need to be
120
- // made explicit to both type and run time systems
121
-
122
- // in "fullyBaked" both run-time and type system are wrong functionally
123
- // but they report as true
124
- expect(fullyBaked).toBe(true);
125
- // we can get to a half-way house by expressing the type as "as const" and making it's types
126
- // literals; now the type system report "false" and the runtime says "true"
127
- expect(halfBaked).toBe(true);
128
- // to get to a fully working solution we need to use the `narrowlyDefines` operator
129
- // along with the "as const" for the type system
130
- expect(lucid).toBe(false);
131
-
132
- // type tests
133
- type FalsePositives = [
134
- Expect<Equal<typeof noFoodOrDrink, false>>,
135
- Expect<Equal<typeof fullyBaked, true>>,
136
- Expect<Equal<typeof halfBaked, false>>,
137
- Expect<Equal<typeof lucid, false>>
138
- ];
139
- const falsePositives: FalsePositives = [true, true, true, true];
140
- expect(falsePositives).toBe(falsePositives);
141
-
142
- // but now we have to accept that the type might be a combination of both
143
- // literal types and broader types; this is not hard to express with types
144
- // but it makes our approach much more awkward and the API much more cumbersome
145
-
146
- // here we see a type that represents this challenge but how it fails with
147
- // with the runtime
148
-
149
- const literal = { foo: 1 } as const;
150
- const wide = { bar: "hi" };
151
- const hybrid = { ...literal, ...wide };
152
- const toughLuck = ifTypeOf({ foo: 1, bar: "bye" }).narrowlyExtends(hybrid);
153
-
154
- // toughLuck should be TRUE because both bar's are strings
155
- // but because we need to preserve run-time literal checking on "foo"
156
- // it is doing it on both
157
- expect(toughLuck).toBe(false);
158
-
159
- type HybridTests = [
160
- // foo is a literal, bar is wide
161
- Expect<Equal<typeof hybrid, { foo: 1; bar: string }>>,
162
- // and type system correctly evaluates
163
- Expect<Equal<typeof toughLuck, true>>
164
- ];
165
- const ToughLuck: HybridTests = [true, true];
166
- expect(ToughLuck).toBe(ToughLuck);
167
-
168
- // in addition to this hybrid issue, i'm not sure there is a good
169
- // way to do a narrow type check on a function; we can hit some use
170
- // cases by converting to a string but that's incomplete
171
- const fn = (_c: number) => "string";
172
- const fn2 = (_c: number) => "string";
173
- const genericFn: Function = () => "string";
174
-
175
- try {
176
- const narrow = ifTypeOf(fn).narrowlyExtends(fn2);
177
- const asWellAsGeneric = ifTypeOf(fn).narrowlyExtends(genericFn);
178
- // the type checks shows that the type system is fine
179
- type Functions = [
180
- Expect<Equal<typeof narrow, true>>,
181
- Expect<Equal<typeof asWellAsGeneric, true>>
182
- ];
183
- const functions: Functions = [true, true];
184
- expect(functions).toBe(functions);
185
- throw new Error("The attempt to run narrowlyExtends on a function should throw an error");
186
- } catch {
187
- // there is no way to narrow compare functions and so it throws
188
- // an error to the run time system
189
- }
190
- });
191
- });
@@ -1,22 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
-
3
- import { Equal, Expect } from "@type-challenges/utils";
4
- import { KeyValue } from "src/types";
5
-
6
- describe("KeyValue<T, K> type utility", () => {
7
- it("explicit KeyValue<T,K> definitions retain literal type info", () => {
8
- const obj = { foo: 1, bar: "hi", baz: { a: 1, b: 2 } } as const;
9
- type O = typeof obj;
10
- type Foo = KeyValue<O, "foo">;
11
- type Bar = KeyValue<O, "bar">;
12
- type Baz = KeyValue<O, "baz">;
13
-
14
- type cases = [
15
- Expect<Equal<Foo, ["foo", 1]>>,
16
- Expect<Equal<Bar, ["bar", "hi"]>>,
17
- Expect<Equal<Baz, ["baz", { readonly a: 1; readonly b: 2 }]>>
18
- ];
19
- const c: cases = [true, true, true];
20
- expect(c).toBe(c);
21
- });
22
- });
@@ -1,35 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
-
3
- import { Equal, Expect, ExpectFalse } from "@type-challenges/utils";
4
- import { SameKeys } from "src/types";
5
-
6
- describe("SameKeys<T> utility", () => {
7
- it("keys must be same type but value can be anything", () => {
8
- const origin = { id: "abc", favorite: false };
9
- type O = typeof origin;
10
- type SK = SameKeys<O>;
11
-
12
- type cases = [Expect<Equal<SK, { id: any; favorite: any }>>];
13
- const c: cases = [true];
14
- expect(c).toBe(c);
15
- });
16
-
17
- it("explicit assignment does enforce exhaustion of all keys", () => {
18
- const origin = { id: "abc", favorite: false };
19
- const partial = { id: "abc" };
20
- type O = typeof origin;
21
- type P = typeof partial;
22
-
23
- type cases = [
24
- // not surprisingly appling utility to both
25
- // does not reach equality
26
- ExpectFalse<Equal<SameKeys<O>, SameKeys<P>>>,
27
- // but more importantly P can not be assigned to SameKeys<O>
28
- // this ensures that you'd get a type error with:
29
- // `const p: SameKeys<O> = { id: "abc" }`
30
- ExpectFalse<Equal<SameKeys<O>, P>>
31
- ];
32
- const c: cases = [false, false];
33
- expect(c).toBe(c);
34
- });
35
- });
@@ -1,169 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
-
3
- import { Equal, Expect, NotEqual } from "@type-challenges/utils";
4
- import { dictToKv, kvToDict } from "src/runtime/dictionary";
5
- import { DictFromKv } from "src/types/kv";
6
- import { keys } from "src/runtime";
7
-
8
- describe("dictToKv()", () => {
9
- it.skip("basic structure is correct when forcing to Tuple structure", () => {
10
- const obj = { id: 123, foo: "bar" } as const;
11
- const val = dictToKv(obj, true);
12
-
13
- expect(Array.isArray(val)).toBeTruthy();
14
- expect(val).toHaveLength(2);
15
- expect(val.every((i) => Object.keys(i).includes("key"))).toBeTruthy();
16
- expect(val.every((i) => Object.keys(i).includes("value"))).toBeTruthy();
17
-
18
- for (const kv of val) {
19
- if (kv.key === "id") {
20
- type cases = [Expect<Equal<typeof kv.key, "id">>, Expect<Equal<typeof kv.value, 123>>];
21
- const c: cases = [true, true];
22
- expect(c).toBe(c);
23
- }
24
- }
25
-
26
- // TODO: this actually passes some of the time in CLI test and almost always in vs-code
27
-
28
- // type cases = [
29
- // Expect<
30
- // Equal<
31
- // Val,
32
- // [
33
- // {
34
- // key: "id";
35
- // value: 123;
36
- // },
37
- // {
38
- // key: "foo";
39
- // value: "bar";
40
- // }
41
- // ]
42
- // >
43
- // >
44
- // ];
45
-
46
- // const c: cases = [true];
47
- // expect(c).toBe(c);
48
- });
49
- });
50
-
51
- it("basic structure is correct when using array structure", () => {
52
- const obj = { id: 123, foo: "bar" } as const;
53
- const val = dictToKv(obj);
54
-
55
- expect(Array.isArray(val)).toBeTruthy();
56
- expect(val).toHaveLength(2);
57
- expect(val.every((i) => Object.keys(i).includes("key"))).toBeTruthy();
58
- expect(val.every((i) => Object.keys(i).includes("value"))).toBeTruthy();
59
-
60
- for (const kv of val) {
61
- if (kv.key === "id") {
62
- type cases = [Expect<Equal<typeof kv.key, "id">>, Expect<Equal<typeof kv.value, 123>>];
63
- const c: cases = [true, true];
64
- expect(c).toBe(c);
65
- }
66
- }
67
-
68
- // types are a bit ugly so skipping check when not Tuple type
69
- });
70
-
71
- describe("kvToDict()", () => {
72
- it("the DictFromKv<T> utility returns original object type", () => {
73
- const val = dictToKv({ id: 123, foo: "bar" });
74
- type Back = DictFromKv<typeof val>;
75
-
76
- type cases = [Expect<Equal<Back, { id: 123; foo: "bar" }>>];
77
- const c: cases = [true];
78
- expect(c).toBe(c);
79
- });
80
-
81
- it("originating KeyValue array converts to strongly typed dictionary", () => {
82
- const obj = kvToDict([
83
- { key: "id", value: "abcd" },
84
- { key: "color", value: "red" },
85
- { key: "favorite", value: true as boolean },
86
- ]);
87
- type Obj = typeof obj;
88
- type Keys = keyof Obj;
89
-
90
- expect(obj.id).toBe("abcd");
91
- expect(obj.color).toBe("red");
92
- expect(obj.favorite).toBe(true);
93
- expect(Object.keys(obj)).toHaveLength(3);
94
-
95
- type cases = [
96
- // Keys are known explicitly
97
- Expect<Equal<Keys, "id" | "color" | "favorite">>,
98
- // Values are literal values where available
99
- Expect<Equal<Obj["id"], "abcd">>,
100
- Expect<Equal<Obj["color"], "red">>,
101
- // if source is wide, then resolution is wide
102
- Expect<Equal<Obj["favorite"], boolean>>
103
- ];
104
-
105
- const c: cases = [true, true, true, true];
106
- expect(c).toBe(c);
107
- });
108
- });
109
-
110
- describe("kvToDict / dictToKv inverse", () => {
111
- it("run-time inverts correctly (starting with obj)", () => {
112
- const obj = { id: 123, foo: "bar" } as const;
113
- const inverse = kvToDict(dictToKv(obj));
114
-
115
- expect(keys(inverse).every((i) => inverse[i] === obj[i]));
116
- });
117
- it("run-time inverts correctly (starting with array)", () => {
118
- const arr = [
119
- { key: "id", value: 123 },
120
- { key: "foo", value: "bar" },
121
- ] as const;
122
- const inverse = dictToKv(kvToDict(arr));
123
-
124
- expect(inverse).toEqual(arr);
125
- });
126
-
127
- it("typing inverts correctly (starting with obj)", () => {
128
- const obj = { id: 123, foo: "bar" } as const;
129
- const inverse = kvToDict(dictToKv(obj));
130
- type Obj = typeof obj;
131
- type Inverse = typeof inverse;
132
-
133
- type cases = [
134
- // while not precisely equal (due to readonly)
135
- Expect<NotEqual<Inverse, Obj>>,
136
- // they are equal in each key/value pair
137
- Expect<Equal<Inverse["id"], Obj["id"]>>,
138
- Expect<Equal<Inverse["foo"], Obj["foo"]>>
139
- ];
140
- const c: cases = [true, true, true];
141
- expect(c).toBe(c);
142
- });
143
-
144
- it("typing inverts correctly (starting with arr)", () => {
145
- const arr = [
146
- { key: "id", value: 123 },
147
- { key: "foo", value: "bar" },
148
- ] as const;
149
- const inverse = dictToKv(
150
- kvToDict([
151
- { key: "id", value: 123 },
152
- { key: "foo", value: "bar" },
153
- ])
154
- );
155
- type Arr = typeof arr;
156
- type Inverse = typeof inverse[0];
157
-
158
- if (inverse[0].key === "id") {
159
- type cases = [
160
- // while not precisely equal (due to readonly)
161
- Expect<NotEqual<Inverse, Arr>>
162
- // they are equal in each key/value pair
163
- // Expect<ExpectExtends<Arr, Inverse>>
164
- ];
165
- const c: cases = [true];
166
- expect(c).toBe(c);
167
- }
168
- });
169
- });