ppipe 2.6.3 → 2.6.6

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.
package/README.md CHANGED
@@ -1,322 +1,329 @@
1
- # [![PPIPE](logo/logo_s.png)](https://github.com/egeozcan/ppipe)
2
-
3
- [![build](https://travis-ci.org/egeozcan/ppipe.svg?branch=master)](https://travis-ci.org/egeozcan/ppipe)
4
- [![Coverage Status](https://coveralls.io/repos/github/egeozcan/ppipe/badge.svg?branch=master)](https://coveralls.io/github/egeozcan/ppipe?branch=master)
5
- [![npm](https://img.shields.io/npm/v/ppipe.svg)](https://www.npmjs.com/package/ppipe)
6
- [![npm](https://img.shields.io/npm/dt/ppipe.svg)](https://www.npmjs.com/package/ppipe)
7
- [![license](https://img.shields.io/github/license/egeozcan/ppipe.svg)](https://github.com/egeozcan/ppipe/blob/master/LICENSE)
8
- [![DeepScan Grade](https://deepscan.io/api/projects/565/branches/916/badge/grade.svg)](https://deepscan.io/dashboard/#view=project&pid=565&bid=916)
9
-
10
- pipes values through functions, an alternative to using the
11
- [proposed pipe operator](https://github.com/mindeavor/es-pipeline-operator) ( |>
12
- ) for ES.
13
-
14
- [Demo available on RunKit](https://runkit.com/egeozcan/ppipe).
15
-
16
- Supports functions returning promises too. In that case, the result of the chain
17
- will also be a promise. This is similar to the proposed support for await in the
18
- chained functions.
19
-
20
- ## Installation
21
-
22
- `npm install ppipe`
23
-
24
- ## Problems ppipe solves
25
-
26
- Let's assume you have these functions:
27
-
28
- ```javascript
29
- const add = (x, y) => x + y;
30
- const square = x => x * x;
31
- const divide = (x, y) => x / y;
32
- const double = x => x + x;
33
- ```
34
-
35
- How do you pass the results from one to another?
36
-
37
- ```javascript
38
- //good old single line solution
39
- add(divide(square(double(add(1, 1))), 8), 1);
40
- //try to get creative with variable names?
41
- const incremented = add(1, 1);
42
- const doubled = double(incremented);
43
- //...
44
- ```
45
-
46
- An ideal solution would have been having a pipe operator (|>) but we don't have
47
- it. Here is where ppipe comes in.
48
-
49
- _Order of arguments can be manipulated using the \_ property of ppipe function.
50
- The result of the previous function is inserted to its place if it exists in the
51
- arguments. It can also occur more than once if you want to pass the same
52
- parameter more than once. If, and only if, \_ doesn't exist among the arguments,
53
- the piped value will be inserted at the end._
54
-
55
- ```javascript
56
- const ppipe = require("ppipe");
57
- const _ = ppipe._;
58
- ppipe(1)(add, 1)(double)(square)(divide, _, 8)(add, 1)(); // 3
59
- ```
60
-
61
- If that is too lisp-y, you can also use ".pipe".
62
-
63
- ```javascript
64
- ppipe(1)
65
- .pipe(add, 1)
66
- .pipe(double)
67
- .pipe(square)
68
- .pipe(divide, _, 8)
69
- .pipe(add, 1)(); // 3
70
- ```
71
-
72
- And then you receive some new "requirements", which end up making the "double"
73
- function async...
74
-
75
- ```javascript
76
- async function asyncDouble(x) {
77
- const result = x * 2;
78
- await someAPICall(result);
79
- return result;
80
- }
81
- ```
82
-
83
- Here are the changes you need to make:
84
-
85
- ```javascript
86
- await ppipe(1)
87
- .pipe(add, 1)
88
- .pipe(asyncDouble)
89
- .pipe(square)
90
- .pipe(divide, _, 8)
91
- .pipe(add, 1); //3 (you can also use .then and .catch)
92
- ```
93
-
94
- Yes, ppipe automatically turns the end result into a promise, if one or more
95
- functions in the chain return a promise. It also waits for the resolution and
96
- passes the unwrapped value to the next function. You can also catch the errors
97
- with `.catch` like a standard promise or use try/catch in an async function. You
98
- meet the requirements and keep the code tidy.
99
-
100
- For consistency, the `.then` and `.catch` methods are always available, so you
101
- don't have to care if any function in the chain is async as long as you use
102
- those.
103
-
104
- So, later you receive some new "requirements", which make our now infamous
105
- double function return an object:
106
-
107
- ```javascript
108
- async function asyncComplexDouble(x) {
109
- const result = x * 2;
110
- const someInfo = await someAPICall(result);
111
- return { result, someInfo };
112
- }
113
- ```
114
-
115
- Still not a problem:
116
-
117
- ```javascript
118
- await ppipe(1)
119
- .pipe(add, 1)
120
- .pipe(asyncComplexDouble)
121
- //pipe._ is also a proxy which saves the property accesses to pluck the prop from the
122
- //previous function's result later
123
- .pipe(square, _.result)
124
- .pipe(divide, _, 8)
125
- .pipe(add, 1); //3
126
-
127
- //well, if you think that might not be clear, you can write it like this, too
128
- await ppipe(1)
129
- .pipe(add, 1)
130
- .pipe(asyncComplexDouble)
131
- .pipe(x => x.result)
132
- .pipe(square)
133
- .pipe(divide, _, 8)
134
- .pipe(add, 1); //3
135
-
136
- //this also works
137
- await ppipe(1)
138
- .pipe(add, 1)
139
- .pipe(asyncComplexDouble)
140
- //promises will be unboxed and properties will be returned as getter functions
141
- //the methods will be available in the chain as well, as shown in the next example
142
- .result()
143
- .pipe(square)
144
- .pipe(divide, _, 8)
145
- .pipe(add, 1); //3
146
- ```
147
-
148
- Let's go one step further; what if you need to access a method from the result?
149
-
150
- ```javascript
151
- async function advancedDouble(x) {
152
- const result = x * 2;
153
- const someInfo = await someAPICall(result);
154
- return {
155
- getResult() {
156
- return result;
157
- },
158
- someInfo
159
- };
160
- }
161
- ```
162
-
163
- There you go:
164
-
165
- ```javascript
166
- await ppipe(1)
167
- .pipe(add, 1)
168
- .pipe(advancedDouble)
169
- .getResult()
170
- .pipe(square)
171
- .pipe(divide, _, 8)
172
- .pipe(add, 1); //3
173
- ```
174
-
175
- ## Some More Examples
176
-
177
- It is possible to expand the iterable result
178
-
179
- ```javascript
180
- const addAll = (...x) => x.reduce((a, b) => a + b, 0)
181
- ppipe([1,2,3]).map(x => x + 1).pipe(addAll, ..._)(); //9
182
- ```
183
-
184
- It is possible to reach array members:
185
-
186
- ```javascript
187
- await ppipe(10)
188
- .pipe(asyncComplexDoubleArray)
189
- .pipe((x, y) => x + y, _[1], _[2]);
190
- ```
191
-
192
- Also object properties:
193
-
194
- ```javascript
195
- ppipe(10)
196
- .pipe(x => ({multipliers: [10,20], value: x}))
197
- .pipe((x, y) => x * y, _.multipliers[0], _.value)(); //100
198
- ```
199
-
200
- And you can omit the function altogether if you just want to extract values:
201
-
202
- ```javascript
203
- ppipe({multipliers: [10,20], value: 10}).pipe(_.value)(); //10
204
- await ppipe({multipliers: [10,20], value: 10}).pipe(_.value); //10
205
- ```
206
-
207
- And as you've seen before, you can always omit the ".pipe", as long as you
208
- know how to keep ASI in check:
209
-
210
- ```javascript
211
- ppipe({multipliers: [10,20], value: 10})(_.value)(); //10
212
- await ppipe({multipliers: [10,20], value: 10})(_.value); //10
213
- ```
214
-
215
- ## Advanced Functionality
216
-
217
- ### Chain Methods / Properties
218
-
219
- You can use these from the chain (after creating one with `ppipe(val)`).
220
-
221
- #### .with(ctx)
222
-
223
- Calls the following function in chain with the given `this` value (ctx). After
224
- calling `.with` the chain can be continued with the methods from the ctx.
225
-
226
- ```javascript
227
- class Example {
228
- constructor(myInt) {
229
- this.foo = Promise.resolve(myInt);
230
- }
231
- addToFoo(x) {
232
- return this.foo.then(foo => foo + x);
233
- }
234
- }
235
- await ppipe(10).with(new Example(5)).addToFoo(_); //15
236
- ```
237
-
238
- Look at the test/test.js for more examples.
239
-
240
- #### .val
241
-
242
- Gets the current value from the chain. Will be a promise if any function in the
243
- chain returns a promise. Calling the chain with no parameters achieves the same
244
- result.
245
-
246
- ### Extending Ppipe
247
-
248
- You can create an extended instance of ppipe via `.extend`.
249
-
250
- ```javascript
251
- const newPipe = ppipe.extend({
252
- divide (x, y) {
253
- return x / y;
254
- },
255
- log(...params) {
256
- console.log(...params);
257
- return params[params.length - 1];
258
- }
259
- });
260
- const res = await newPipe(10)
261
- .pipe(x => x + 1)
262
- .divide(_, 11)
263
- .log("here is our x: ") //logs "here is our x: 1"
264
- .pipe(x => x + 1) // 2
265
- ```
266
-
267
- You can also call `.extend` on the extended ppipes. It will create a new ppipe
268
- with the new and existing extensions merged.
269
-
270
- ## Testing
271
-
272
- All the functionality is tested, with 100% coverage. This is also integrated in the build process.
273
-
274
- To run the tests yourself, clone the repository, install the dev dependencies, and run the npm test command.
275
-
276
- `npm install`
277
-
278
- `npm test`
279
-
280
- ## Contributing
281
-
282
- See
283
- [CONTRIBUTING](https://github.com/egeozcan/ppipe/blob/master/.github/CONTRIBUTING.md).
284
-
285
- ## Changelog
286
-
287
- * v2.5.0 - placeholder can be the only argument to the .pipe, for just extracting a property or path
288
- * v2.4.0 - allow deep property extraction via the placeholder
289
- (\_.deeply.nested.prop) (test: should be able to extract array members)
290
- * v2.3.0 - now supports expanding the placeholder (...\_) (test: should support
291
- expanding the array result)
292
-
293
- ## Caveats
294
-
295
- * This library was not written with performance in mind. So, it makes next to no
296
- sense to use it in, say, a tight loop. Use in a web-server should be fine as
297
- long as you don't have tight response-time requirements. General rule of
298
- thumb: Test it before putting it into prod. There are a lot of tests written
299
- for ppipe but none of them measure performance. I may improve the performance
300
- in the future (some low-hanging fruits) but I'd rather avoid making any
301
- guarantees. Well, there is one good news:
302
- [Chrome team is working on performance improvements to the Proxy](https://v8project.blogspot.de/2017/10/optimizing-proxies.html)
303
- which will very positively affect ppipe performance.
304
-
305
- * It uses ES6 Proxies to do its magic. Proxies are not back-portable. 1.x.x
306
- versions of ppipe didn't use proxies. So you can try using an older version
307
- with a transpiler if evergreen sounds alien to you.
308
- [Here](https://github.com/egeozcan/ppipe/blob/1888e9269be90f549d5c00002f7e800598c6d539/index.js)
309
- is an older stable version without value extracting and context change
310
- support.
311
-
312
- * ppipe is not typed. No type definition exists for TypeScript nor Flow. I
313
- actually love TypeScript and would support it but the lack of variadic generic
314
- type parameters make it next to impossible to provide type definitions for
315
- ppipe. More can be read
316
- [here](https://github.com/Microsoft/TypeScript/issues/5453). Also, ppipe is as
317
- dynamic as it gets, giving the ability to access virtual properties/methods
318
- which may belong to the provided context, the processed value or any of the
319
- possible extensions.
320
- [TypeScripts Type System is Turing Complete](https://github.com/Microsoft/TypeScript/issues/14833),
321
- so, maybe there is a way to type all of this but I really need help about
322
- that.
1
+ # [![PPIPE](logo/logo_s.png)](https://github.com/egeozcan/ppipe)
2
+
3
+ [![build](https://travis-ci.org/egeozcan/ppipe.svg?branch=master)](https://travis-ci.org/egeozcan/ppipe)
4
+ [![Coverage Status](https://coveralls.io/repos/github/egeozcan/ppipe/badge.svg?branch=master)](https://coveralls.io/github/egeozcan/ppipe?branch=master)
5
+ [![npm](https://img.shields.io/npm/v/ppipe.svg)](https://www.npmjs.com/package/ppipe)
6
+ [![npm](https://img.shields.io/npm/dt/ppipe.svg)](https://www.npmjs.com/package/ppipe)
7
+ [![license](https://img.shields.io/github/license/egeozcan/ppipe.svg)](https://github.com/egeozcan/ppipe/blob/master/LICENSE)
8
+ [![DeepScan Grade](https://deepscan.io/api/projects/565/branches/916/badge/grade.svg)](https://deepscan.io/dashboard/#view=project&pid=565&bid=916)
9
+
10
+ _Please note that this library is considered "done". It is still maintained and will be in the foreseeable future, but,
11
+ other than adding Typescript support, no new functionality will be added. At least, there is no plan to do so.
12
+ This library has an extensive test suite with 100% coverage, and it is used by at least a few well-established
13
+ projects in production. The mythical "production-ready" seems to be reached :)_
14
+
15
+ _All bug reports and suggestions are still welcome!_
16
+
17
+ **pipes values through functions**, an alternative to using the
18
+ [proposed pipe operator](https://github.com/mindeavor/es-pipeline-operator) ( |>
19
+ ) for ES.
20
+
21
+ [Demo available on RunKit](https://runkit.com/egeozcan/ppipe).
22
+
23
+ Supports functions returning promises too. In that case, the result of the chain
24
+ will also be a promise. This is similar to the proposed support for await in the
25
+ chained functions.
26
+
27
+ ## Installation
28
+
29
+ `npm install ppipe`
30
+
31
+ ## Problems ppipe solves
32
+
33
+ Let's assume you have these functions:
34
+
35
+ ```javascript
36
+ const add = (x, y) => x + y;
37
+ const square = x => x * x;
38
+ const divide = (x, y) => x / y;
39
+ const double = x => x + x;
40
+ ```
41
+
42
+ How do you pass the results from one to another?
43
+
44
+ ```javascript
45
+ //good old single line solution
46
+ add(divide(square(double(add(1, 1))), 8), 1);
47
+ //try to get creative with variable names?
48
+ const incremented = add(1, 1);
49
+ const doubled = double(incremented);
50
+ //...
51
+ ```
52
+
53
+ An ideal solution would have been having a pipe operator (|>) but we don't have
54
+ it. Here is where ppipe comes in.
55
+
56
+ _Order of arguments can be manipulated using the \_ property of ppipe function.
57
+ The result of the previous function is inserted to its place if it exists in the
58
+ arguments. It can also occur more than once if you want to pass the same
59
+ parameter more than once. If, and only if, \_ doesn't exist among the arguments,
60
+ the piped value will be inserted at the end._
61
+
62
+ ```javascript
63
+ const ppipe = require("ppipe");
64
+ const _ = ppipe._;
65
+ ppipe(1)(add, 1)(double)(square)(divide, _, 8)(add, 1)(); // 3
66
+ ```
67
+
68
+ If that is too lisp-y, you can also use ".pipe".
69
+
70
+ ```javascript
71
+ ppipe(1)
72
+ .pipe(add, 1)
73
+ .pipe(double)
74
+ .pipe(square)
75
+ .pipe(divide, _, 8)
76
+ .pipe(add, 1)(); // 3
77
+ ```
78
+
79
+ And then you receive some new "requirements", which end up making the "double"
80
+ function async...
81
+
82
+ ```javascript
83
+ async function asyncDouble(x) {
84
+ const result = x * 2;
85
+ await someAPICall(result);
86
+ return result;
87
+ }
88
+ ```
89
+
90
+ Here are the changes you need to make:
91
+
92
+ ```javascript
93
+ await ppipe(1)
94
+ .pipe(add, 1)
95
+ .pipe(asyncDouble)
96
+ .pipe(square)
97
+ .pipe(divide, _, 8)
98
+ .pipe(add, 1); //3 (you can also use .then and .catch)
99
+ ```
100
+
101
+ Yes, ppipe automatically turns the end result into a promise, if one or more
102
+ functions in the chain return a promise. It also waits for the resolution and
103
+ passes the unwrapped value to the next function. You can also catch the errors
104
+ with `.catch` like a standard promise or use try/catch in an async function. You
105
+ meet the requirements and keep the code tidy.
106
+
107
+ For consistency, the `.then` and `.catch` methods are always available, so you
108
+ don't have to care if any function in the chain is async as long as you use
109
+ those.
110
+
111
+ So, later you receive some new "requirements", which make our now infamous
112
+ double function return an object:
113
+
114
+ ```javascript
115
+ async function asyncComplexDouble(x) {
116
+ const result = x * 2;
117
+ const someInfo = await someAPICall(result);
118
+ return { result, someInfo };
119
+ }
120
+ ```
121
+
122
+ Still not a problem:
123
+
124
+ ```javascript
125
+ await ppipe(1)
126
+ .pipe(add, 1)
127
+ .pipe(asyncComplexDouble)
128
+ //pipe._ is also a proxy which saves the property accesses to pluck the prop from the
129
+ //previous function's result later
130
+ .pipe(square, _.result)
131
+ .pipe(divide, _, 8)
132
+ .pipe(add, 1); //3
133
+
134
+ //well, if you think that might not be clear, you can write it like this, too
135
+ await ppipe(1)
136
+ .pipe(add, 1)
137
+ .pipe(asyncComplexDouble)
138
+ .pipe(x => x.result)
139
+ .pipe(square)
140
+ .pipe(divide, _, 8)
141
+ .pipe(add, 1); //3
142
+
143
+ //this also works
144
+ await ppipe(1)
145
+ .pipe(add, 1)
146
+ .pipe(asyncComplexDouble)
147
+ //promises will be unboxed and properties will be returned as getter functions
148
+ //the methods will be available in the chain as well, as shown in the next example
149
+ .result()
150
+ .pipe(square)
151
+ .pipe(divide, _, 8)
152
+ .pipe(add, 1); //3
153
+ ```
154
+
155
+ Let's go one step further; what if you need to access a method from the result?
156
+
157
+ ```javascript
158
+ async function advancedDouble(x) {
159
+ const result = x * 2;
160
+ const someInfo = await someAPICall(result);
161
+ return {
162
+ getResult() {
163
+ return result;
164
+ },
165
+ someInfo
166
+ };
167
+ }
168
+ ```
169
+
170
+ There you go:
171
+
172
+ ```javascript
173
+ await ppipe(1)
174
+ .pipe(add, 1)
175
+ .pipe(advancedDouble)
176
+ .getResult()
177
+ .pipe(square)
178
+ .pipe(divide, _, 8)
179
+ .pipe(add, 1); //3
180
+ ```
181
+
182
+ ## Some More Examples
183
+
184
+ It is possible to expand the iterable result
185
+
186
+ ```javascript
187
+ const addAll = (...x) => x.reduce((a, b) => a + b, 0)
188
+ ppipe([1,2,3]).map(x => x + 1).pipe(addAll, ..._)(); //9
189
+ ```
190
+
191
+ It is possible to reach array members:
192
+
193
+ ```javascript
194
+ await ppipe(10)
195
+ .pipe(asyncComplexDoubleArray)
196
+ .pipe((x, y) => x + y, _[1], _[2]);
197
+ ```
198
+
199
+ Also object properties:
200
+
201
+ ```javascript
202
+ ppipe(10)
203
+ .pipe(x => ({multipliers: [10,20], value: x}))
204
+ .pipe((x, y) => x * y, _.multipliers[0], _.value)(); //100
205
+ ```
206
+
207
+ And you can omit the function altogether if you just want to extract values:
208
+
209
+ ```javascript
210
+ ppipe({multipliers: [10,20], value: 10}).pipe(_.value)(); //10
211
+ await ppipe({multipliers: [10,20], value: 10}).pipe(_.value); //10
212
+ ```
213
+
214
+ And as you've seen before, you can always omit the ".pipe", as long as you
215
+ know how to keep ASI in check:
216
+
217
+ ```javascript
218
+ ppipe({multipliers: [10,20], value: 10})(_.value)(); //10
219
+ await ppipe({multipliers: [10,20], value: 10})(_.value); //10
220
+ ```
221
+
222
+ ## Advanced Functionality
223
+
224
+ ### Chain Methods / Properties
225
+
226
+ You can use these from the chain (after creating one with `ppipe(val)`).
227
+
228
+ #### .with(ctx)
229
+
230
+ Calls the following function in chain with the given `this` value (ctx). After
231
+ calling `.with` the chain can be continued with the methods from the ctx.
232
+
233
+ ```javascript
234
+ class Example {
235
+ constructor(myInt) {
236
+ this.foo = Promise.resolve(myInt);
237
+ }
238
+ addToFoo(x) {
239
+ return this.foo.then(foo => foo + x);
240
+ }
241
+ }
242
+ await ppipe(10).with(new Example(5)).addToFoo(_); //15
243
+ ```
244
+
245
+ Look at the test/test.js for more examples.
246
+
247
+ #### .val
248
+
249
+ Gets the current value from the chain. Will be a promise if any function in the
250
+ chain returns a promise. Calling the chain with no parameters achieves the same
251
+ result.
252
+
253
+ ### Extending Ppipe
254
+
255
+ You can create an extended instance of ppipe via `.extend`.
256
+
257
+ ```javascript
258
+ const newPipe = ppipe.extend({
259
+ divide (x, y) {
260
+ return x / y;
261
+ },
262
+ log(...params) {
263
+ console.log(...params);
264
+ return params[params.length - 1];
265
+ }
266
+ });
267
+ const res = await newPipe(10)
268
+ .pipe(x => x + 1)
269
+ .divide(_, 11)
270
+ .log("here is our x: ") //logs "here is our x: 1"
271
+ .pipe(x => x + 1) // 2
272
+ ```
273
+
274
+ You can also call `.extend` on the extended ppipes. It will create a new ppipe
275
+ with the new and existing extensions merged.
276
+
277
+ ## Testing
278
+
279
+ All the functionality is tested, with 100% coverage. This is also integrated in the build process.
280
+
281
+ To run the tests yourself, clone the repository, install the dev dependencies, and run the npm test command.
282
+
283
+ `npm install`
284
+
285
+ `npm test`
286
+
287
+ ## Contributing
288
+
289
+ See
290
+ [CONTRIBUTING](https://github.com/egeozcan/ppipe/blob/master/.github/CONTRIBUTING.md).
291
+
292
+ ## Changelog
293
+
294
+ * v2.5.0 - placeholder can be the only argument to the .pipe, for just extracting a property or path
295
+ * v2.4.0 - allow deep property extraction via the placeholder
296
+ (\_.deeply.nested.prop) (test: should be able to extract array members)
297
+ * v2.3.0 - now supports expanding the placeholder (...\_) (test: should support
298
+ expanding the array result)
299
+
300
+ ## Caveats
301
+
302
+ * This library was not written with performance in mind. So, it makes next to no
303
+ sense to use it in, say, a tight loop. Use in a web-server should be fine as
304
+ long as you don't have tight response-time requirements. General rule of
305
+ thumb: Test it before putting it into prod. There are a lot of tests written
306
+ for ppipe but none of them measure performance. I may improve the performance
307
+ in the future (some low-hanging fruits) but I'd rather avoid making any
308
+ guarantees. Well, there is one good news:
309
+ [Chrome team is working on performance improvements to the Proxy](https://v8project.blogspot.de/2017/10/optimizing-proxies.html)
310
+ which will very positively affect ppipe performance.
311
+
312
+ * It uses ES6 Proxies to do its magic. Proxies are not back-portable. 1.x.x
313
+ versions of ppipe didn't use proxies. So you can try using an older version
314
+ with a transpiler if evergreen sounds alien to you.
315
+ [Here](https://github.com/egeozcan/ppipe/blob/1888e9269be90f549d5c00002f7e800598c6d539/index.js)
316
+ is an older stable version without value extracting and context change
317
+ support.
318
+
319
+ * ppipe is not typed. No type definition exists for TypeScript nor Flow. I
320
+ actually love TypeScript and would support it but the lack of variadic generic
321
+ type parameters make it next to impossible to provide type definitions for
322
+ ppipe. More can be read
323
+ [here](https://github.com/Microsoft/TypeScript/issues/5453). Also, ppipe is as
324
+ dynamic as it gets, giving the ability to access virtual properties/methods
325
+ which may belong to the provided context, the processed value or any of the
326
+ possible extensions.
327
+ [TypeScripts Type System is Turing Complete](https://github.com/Microsoft/TypeScript/issues/14833),
328
+ so, maybe there is a way to type all of this but I really need help about
329
+ that.