objectmodel 4.3.1 → 4.4.0

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 (53) hide show
  1. package/.eslintignore +8 -8
  2. package/.eslintrc.json +25 -25
  3. package/.travis.yml +2 -2
  4. package/LICENSE +22 -22
  5. package/README.md +67 -67
  6. package/build/add-banner.js +13 -13
  7. package/build/bundle-entry.dev.js +2 -2
  8. package/build/bundle-entry.js +11 -11
  9. package/dist/object-model.cjs +462 -469
  10. package/dist/object-model.js +462 -469
  11. package/dist/object-model.js.map +1 -1
  12. package/dist/object-model.min.js +2 -2
  13. package/dist/object-model.min.js.map +1 -1
  14. package/index.html +4 -4
  15. package/package.json +9 -3
  16. package/rollup.config.js +13 -13
  17. package/src/array-model.d.ts +16 -0
  18. package/src/array-model.js +68 -68
  19. package/src/devtool-formatter.js +198 -198
  20. package/src/function-model.d.ts +24 -0
  21. package/src/function-model.js +58 -65
  22. package/src/helpers.js +43 -43
  23. package/src/index.js +4 -4
  24. package/src/list-model.js +43 -43
  25. package/src/map-model.d.ts +18 -0
  26. package/src/map-model.js +48 -48
  27. package/src/object-model.d.ts +74 -0
  28. package/src/set-model.d.ts +16 -0
  29. package/src/set-model.js +41 -41
  30. package/test/array-model.spec.cjs +291 -291
  31. package/test/array-model.test-d.ts +24 -0
  32. package/test/basic-model.spec.cjs +263 -263
  33. package/test/basic-model.test-d.ts +30 -0
  34. package/test/bench/array.html +51 -51
  35. package/test/bench/bench-lib.js +49 -49
  36. package/test/bench/map-no-cast.html +53 -53
  37. package/test/bench/map-set.html +52 -52
  38. package/test/bench/map.html +51 -51
  39. package/test/bench/object-models.html +87 -87
  40. package/test/function-model.spec.cjs +161 -162
  41. package/test/function-model.test-d.ts +18 -0
  42. package/test/index.cjs +13 -13
  43. package/test/map-model.spec.cjs +224 -224
  44. package/test/map-model.test-d.ts +21 -0
  45. package/test/model.spec.cjs +30 -30
  46. package/test/object-model.spec.cjs +1345 -1346
  47. package/test/object-model.test-d.ts +53 -0
  48. package/test/set-model.spec.cjs +213 -213
  49. package/test/set-model.test-d.ts +17 -0
  50. package/test/umd.html +25 -25
  51. package/types/definitions.d.ts +43 -0
  52. package/types/helpers.d.ts +4 -0
  53. package/types/index.d.ts +6 -128
@@ -0,0 +1,53 @@
1
+ import {expectType} from 'tsd';
2
+ import { Model, ObjectModel } from "../src/object-model"
3
+
4
+ expectType<{ a: number, b: "b" }>(Model({ a: Number, b: <const>"b" })({ a: 1, b: "b" }))
5
+
6
+ expectType<{
7
+ product: {
8
+ name: string,
9
+ quantity: number
10
+ },
11
+ orderDate: Date
12
+ }>(new ObjectModel({
13
+ product: {
14
+ name: String,
15
+ quantity: Number,
16
+ },
17
+ orderDate: Date
18
+ })({
19
+ product: { name: "Apple Pie", quantity: 1 },
20
+ orderDate: new Date()
21
+ }))
22
+
23
+ const Person = ObjectModel({ name: String, female: Boolean })
24
+ const Man = Person.extend({ female: false })
25
+ const Mother = Person.extend({ female: true, child: Person })
26
+
27
+ let joanna = new Person({ name: "Joanna", female: true })
28
+ let joe = new Man({ name: "Joe" })
29
+ let ann = new Mother({ name: "Ann", child: joanna })
30
+ expectType<{ name: string, female: boolean }>(joanna)
31
+ expectType<{ name: string, female: boolean }>(joe)
32
+ expectType<{ name: string, female: boolean }>(ann.child)
33
+
34
+ class ClassPerson extends ObjectModel({ name: String, female: Boolean }){
35
+ constructor({ name, female }: { name: string, female: boolean }){
36
+ if(!female) name = `Mr ${name}`
37
+ super({ name, female })
38
+ }
39
+ }
40
+
41
+ class ClassMother extends ClassPerson.extend({ female: true, child: ClassPerson }){
42
+ constructor({ name, child }: { name: string, child: ClassPerson }){
43
+ super({ name: `Mrs ${name}`, female: true })
44
+ this.child = child
45
+ }
46
+ }
47
+
48
+ joanna = new ClassPerson({ name: "Joanna", female: true })
49
+ ann = new ClassMother({ name: "Ann", child: joanna })
50
+
51
+ expectType<ClassMother>(ann)
52
+ expectType<string>(ann.name)
53
+ expectType<ClassPerson>(ann.child)
@@ -1,214 +1,214 @@
1
- /* global QUnit, SetModel, ObjectModel */
2
-
3
- QUnit.module("Set Models");
4
-
5
- QUnit.test("constructor && proto", function (assert) {
6
-
7
- assert.ok(SetModel instanceof Function, "SetModel instanceof Function");
8
-
9
- const MySet = SetModel(String);
10
-
11
- assert.ok(MySet instanceof SetModel, "Set models can be declared");
12
-
13
- assert.ok(typeof MySet.extend === "function", "test Set model method extend");
14
- assert.ok(typeof MySet.assert === "function", "test Set model method assert");
15
- assert.ok(typeof MySet.test === "function", "test Set model method test");
16
- assert.ok(MySet.definition === String, "test Set model prop definition");
17
- assert.ok(typeof MySet.assertions === "object", "test Set model prop assertions");
18
-
19
- assert.ok(SetModel(undefined) instanceof SetModel, "SetModel can receive undefined as argument");
20
-
21
- });
22
-
23
- QUnit.test("instanciation && mutation methods watchers", function (assert) {
24
-
25
- const S = SetModel(Number).assert(s => s.size >= 2, "minsize assert");
26
- const s = S([1, 2]);
27
-
28
- assert.ok(s instanceof S && s instanceof Set, "Set models can be instanciated");
29
-
30
- s.add(3);
31
-
32
- assert.equal(s.add.name, "add", "proxyfied methods keep original properties");
33
-
34
- assert.throws(function () {
35
- s.add("four")
36
- }, /TypeError.*four/, "add calls are catched");
37
-
38
- assert.equal(s.size, 3, "set size change is ok 1/2");
39
-
40
- s.delete(3);
41
- assert.throws(function () {
42
- s.delete(2);
43
- }, /TypeError.*minsize assert/, "delete calls are catched");
44
-
45
- assert.throws(function () {
46
- s.clear();
47
- }, /TypeError.*minsize assert/, "clear calls are catched");
48
-
49
- assert.equal(s.size, 2, "set size change is ok 2/2");
50
-
51
- });
52
-
53
- QUnit.test("validation in constructor", function (assert) {
54
-
55
- const S = SetModel(String)
56
- const s = S(["one", "two"]);
57
- assert.equal(s.size, 2, "set size is ok");
58
-
59
- assert.throws(function () {
60
- S(["one", 2])
61
- }, /TypeError/, "validation in set model constructor 1/2");
62
-
63
- assert.throws(function () {
64
- S([1, "two"])
65
- }, /TypeError/, "validation in set model constructor 2/2");
66
-
67
- });
68
-
69
- QUnit.test("union types & submodels", function (assert) {
70
-
71
- const Question = ObjectModel({
72
- answer: Number
73
- });
74
-
75
- const Quiz = SetModel([Question, String, Boolean]);
76
- const s = Quiz(["test", true, { answer: 42 }]);
77
- s.add("is it real life ?");
78
- s.add(true);
79
- s.add({ answer: 43 });
80
- assert.throws(function () {
81
- s.add(42);
82
- }, /TypeError[\s\S]*got Number 42/m, "set invalid type on union type");
83
-
84
- });
85
-
86
- QUnit.test("union types & fixed values", function (assert) {
87
-
88
- const S = SetModel([true, 2, "3"]);
89
- assert.throws(function () {
90
- S(["3", 4]);
91
- }, /TypeError[\s\S]*Set.*Number 4/, "SetModel fixed values");
92
-
93
- S([2, true]);
94
- const S2 = S.extend().assert(s => s.size === 2);
95
- const s2 = new S2([2, '3']);
96
-
97
- assert.ok(Object.getPrototypeOf(S2.prototype) === S.prototype, "extension respect prototypal chain");
98
- assert.ok(s2 instanceof S2 && s2 instanceof S, "set model inheritance");
99
- S([2, true]).add("3");
100
- assert.throws(function () {
101
- S2([2, true]).add("3")
102
- }, /TypeError/, "min/max of inherit set model");
103
-
104
- const S3 = S2.extend("new", "val");
105
- S3(["val", true]);
106
- S3([true, "new"]);
107
- assert.throws(function () {
108
- S2(["val", true]);
109
- }, /TypeError/, "set model type extension");
110
-
111
- })
112
-
113
- QUnit.test("Child set models in object models", function (assert) {
114
-
115
- const Child = ObjectModel({ set: SetModel(Number) });
116
- const Parent = ObjectModel({ child: Child });
117
-
118
- const childO = Child({ set: new Set([1, 2, 3, 5, 8]) });
119
- assert.ok(childO.set instanceof Set, "child set model is instanceof Set");
120
- const parentO = Parent({ child: childO });
121
- assert.ok(parentO.child.set instanceof Set, "child set model from parent is Set");
122
-
123
- childO.set.add(13);
124
- assert.throws(function () {
125
- childO.set.add("21");
126
- }, /TypeError/, "child array model catches invalid set value");
127
-
128
- });
129
-
130
- QUnit.test("defaults values", function (assert) {
131
-
132
- const S = SetModel(Number).defaultTo(new Set([1, 2]));
133
- const a = S();
134
-
135
- assert.ok(a instanceof Set && a.size === 2, "Set model default value");
136
-
137
- S.default.add(3);
138
-
139
- const b = S();
140
-
141
- assert.ok(b.size === 3 && Array.from(b.values()).sort().join(";") === "1;2;3", "set model default value is mutable");
142
-
143
- S.default = "nope";
144
-
145
- assert.throws(function () {
146
- S()
147
- }, /TypeError/, "invalid default property still throws TypeError for set models");
148
-
149
- })
150
-
151
- QUnit.test("assertions", function (assert) {
152
-
153
- const SetMax3 = SetModel(String).assert(function maxEntries(set) {
154
- return set.size <= 3;
155
- });
156
-
157
- let set = SetMax3(["one", "two"]);
158
-
159
- set.add("three");
160
- assert.throws(function () {
161
- set.add("four");
162
- }, /TypeError[\s\S]*maxEntries/, "test assertion after set method");
163
-
164
- const AssertSet = SetModel(Number).assert(s => s.size > 0, "may throw exception");
165
-
166
- new AssertSet([1, 2]);
167
-
168
- assert.throws(function () { new AssertSet([]); },
169
- /assertion "may throw exception" returned false.*for value \[]/,
170
- "assertions catch exceptions on Set models"
171
- );
172
-
173
- })
174
-
175
- QUnit.test("Automatic model casting", function (assert) {
176
-
177
- const N = ObjectModel({ x: Number, y: [Number] }).defaultTo({ x: 5, y: 7 });
178
- const S = SetModel(N);
179
- const s = S([{ x: 9 }]);
180
-
181
- let n = Array.from(s.values())[0];
182
- assert.ok(n instanceof N, "test automatic model casting with set init 1/2")
183
- assert.equal(n.x * n.y, 63, "test automatic model casting with set init 2/2")
184
-
185
- s.add({ x: 3 });
186
- n = Array.from(s.values())[1];
187
-
188
- assert.ok(n instanceof N, "test automatic model casting with array mutator method 1/2")
189
- assert.equal(n.x * n.y, 21, "test automatic model casting with array mutator method 2/2")
190
- });
191
-
192
- QUnit.test("toString", function (assert) {
193
- assert.equal(SetModel(Number).toString(), "Set of Number", "SetModel toString for basic elements")
194
- assert.equal(SetModel([String, 42]).toString(), "Set of String or 42", "SetModel toString for union type elements")
195
- })
196
-
197
- QUnit.test("dynamic definition", function (assert) {
198
- let S = SetModel(String);
199
- let s1 = S(["hello", "world"])
200
- S.definition = Number;
201
- let s2 = S([1, 2, 3])
202
- assert.equal(S.test(s1), false, "definition can be dynamically changed 1/4")
203
- assert.equal(S.test(s2), true, "definition can be dynamically changed 2/4")
204
- s1.clear();
205
- assert.throws(() => s1.add("hello"), /TypeError/, "definition can be dynamically changed 3/4")
206
- s1.add(42);
207
- assert.ok(s1.has(42), "definition can be dynamically changed 4/4")
208
-
209
- let OM = ObjectModel({ n: Number });
210
- S.definition = OM;
211
- s1.clear();
212
- s1.add({ n: 42 });
213
- assert.ok([...s1][0] instanceof OM, "autocast still works after definition dynamically changed")
1
+ /* global QUnit, SetModel, ObjectModel */
2
+
3
+ QUnit.module("Set Models");
4
+
5
+ QUnit.test("constructor && proto", function (assert) {
6
+
7
+ assert.ok(SetModel instanceof Function, "SetModel instanceof Function");
8
+
9
+ const MySet = SetModel(String);
10
+
11
+ assert.ok(MySet instanceof SetModel, "Set models can be declared");
12
+
13
+ assert.ok(typeof MySet.extend === "function", "test Set model method extend");
14
+ assert.ok(typeof MySet.assert === "function", "test Set model method assert");
15
+ assert.ok(typeof MySet.test === "function", "test Set model method test");
16
+ assert.ok(MySet.definition === String, "test Set model prop definition");
17
+ assert.ok(typeof MySet.assertions === "object", "test Set model prop assertions");
18
+
19
+ assert.ok(SetModel(undefined) instanceof SetModel, "SetModel can receive undefined as argument");
20
+
21
+ });
22
+
23
+ QUnit.test("instanciation && mutation methods watchers", function (assert) {
24
+
25
+ const S = SetModel(Number).assert(s => s.size >= 2, "minsize assert");
26
+ const s = S([1, 2]);
27
+
28
+ assert.ok(s instanceof S && s instanceof Set, "Set models can be instanciated");
29
+
30
+ s.add(3);
31
+
32
+ assert.equal(s.add.name, "add", "proxyfied methods keep original properties");
33
+
34
+ assert.throws(function () {
35
+ s.add("four")
36
+ }, /TypeError.*four/, "add calls are catched");
37
+
38
+ assert.equal(s.size, 3, "set size change is ok 1/2");
39
+
40
+ s.delete(3);
41
+ assert.throws(function () {
42
+ s.delete(2);
43
+ }, /TypeError.*minsize assert/, "delete calls are catched");
44
+
45
+ assert.throws(function () {
46
+ s.clear();
47
+ }, /TypeError.*minsize assert/, "clear calls are catched");
48
+
49
+ assert.equal(s.size, 2, "set size change is ok 2/2");
50
+
51
+ });
52
+
53
+ QUnit.test("validation in constructor", function (assert) {
54
+
55
+ const S = SetModel(String)
56
+ const s = S(["one", "two"]);
57
+ assert.equal(s.size, 2, "set size is ok");
58
+
59
+ assert.throws(function () {
60
+ S(["one", 2])
61
+ }, /TypeError/, "validation in set model constructor 1/2");
62
+
63
+ assert.throws(function () {
64
+ S([1, "two"])
65
+ }, /TypeError/, "validation in set model constructor 2/2");
66
+
67
+ });
68
+
69
+ QUnit.test("union types & submodels", function (assert) {
70
+
71
+ const Question = ObjectModel({
72
+ answer: Number
73
+ });
74
+
75
+ const Quiz = SetModel([Question, String, Boolean]);
76
+ const s = Quiz(["test", true, { answer: 42 }]);
77
+ s.add("is it real life ?");
78
+ s.add(true);
79
+ s.add({ answer: 43 });
80
+ assert.throws(function () {
81
+ s.add(42);
82
+ }, /TypeError[\s\S]*got Number 42/m, "set invalid type on union type");
83
+
84
+ });
85
+
86
+ QUnit.test("union types & fixed values", function (assert) {
87
+
88
+ const S = SetModel([true, 2, "3"]);
89
+ assert.throws(function () {
90
+ S(["3", 4]);
91
+ }, /TypeError[\s\S]*Set.*Number 4/, "SetModel fixed values");
92
+
93
+ S([2, true]);
94
+ const S2 = S.extend().assert(s => s.size === 2);
95
+ const s2 = new S2([2, '3']);
96
+
97
+ assert.ok(Object.getPrototypeOf(S2.prototype) === S.prototype, "extension respect prototypal chain");
98
+ assert.ok(s2 instanceof S2 && s2 instanceof S, "set model inheritance");
99
+ S([2, true]).add("3");
100
+ assert.throws(function () {
101
+ S2([2, true]).add("3")
102
+ }, /TypeError/, "min/max of inherit set model");
103
+
104
+ const S3 = S2.extend("new", "val");
105
+ S3(["val", true]);
106
+ S3([true, "new"]);
107
+ assert.throws(function () {
108
+ S2(["val", true]);
109
+ }, /TypeError/, "set model type extension");
110
+
111
+ })
112
+
113
+ QUnit.test("Child set models in object models", function (assert) {
114
+
115
+ const Child = ObjectModel({ set: SetModel(Number) });
116
+ const Parent = ObjectModel({ child: Child });
117
+
118
+ const childO = Child({ set: new Set([1, 2, 3, 5, 8]) });
119
+ assert.ok(childO.set instanceof Set, "child set model is instanceof Set");
120
+ const parentO = Parent({ child: childO });
121
+ assert.ok(parentO.child.set instanceof Set, "child set model from parent is Set");
122
+
123
+ childO.set.add(13);
124
+ assert.throws(function () {
125
+ childO.set.add("21");
126
+ }, /TypeError/, "child array model catches invalid set value");
127
+
128
+ });
129
+
130
+ QUnit.test("defaults values", function (assert) {
131
+
132
+ const S = SetModel(Number).defaultTo(new Set([1, 2]));
133
+ const a = S();
134
+
135
+ assert.ok(a instanceof Set && a.size === 2, "Set model default value");
136
+
137
+ S.default.add(3);
138
+
139
+ const b = S();
140
+
141
+ assert.ok(b.size === 3 && Array.from(b.values()).sort().join(";") === "1;2;3", "set model default value is mutable");
142
+
143
+ S.default = "nope";
144
+
145
+ assert.throws(function () {
146
+ S()
147
+ }, /TypeError/, "invalid default property still throws TypeError for set models");
148
+
149
+ })
150
+
151
+ QUnit.test("assertions", function (assert) {
152
+
153
+ const SetMax3 = SetModel(String).assert(function maxEntries(set) {
154
+ return set.size <= 3;
155
+ });
156
+
157
+ let set = SetMax3(["one", "two"]);
158
+
159
+ set.add("three");
160
+ assert.throws(function () {
161
+ set.add("four");
162
+ }, /TypeError[\s\S]*maxEntries/, "test assertion after set method");
163
+
164
+ const AssertSet = SetModel(Number).assert(s => s.size > 0, "may throw exception");
165
+
166
+ new AssertSet([1, 2]);
167
+
168
+ assert.throws(function () { new AssertSet([]); },
169
+ /assertion "may throw exception" returned false.*for value \[]/,
170
+ "assertions catch exceptions on Set models"
171
+ );
172
+
173
+ })
174
+
175
+ QUnit.test("Automatic model casting", function (assert) {
176
+
177
+ const N = ObjectModel({ x: Number, y: [Number] }).defaultTo({ x: 5, y: 7 });
178
+ const S = SetModel(N);
179
+ const s = S([{ x: 9 }]);
180
+
181
+ let n = Array.from(s.values())[0];
182
+ assert.ok(n instanceof N, "test automatic model casting with set init 1/2")
183
+ assert.equal(n.x * n.y, 63, "test automatic model casting with set init 2/2")
184
+
185
+ s.add({ x: 3 });
186
+ n = Array.from(s.values())[1];
187
+
188
+ assert.ok(n instanceof N, "test automatic model casting with array mutator method 1/2")
189
+ assert.equal(n.x * n.y, 21, "test automatic model casting with array mutator method 2/2")
190
+ });
191
+
192
+ QUnit.test("toString", function (assert) {
193
+ assert.equal(SetModel(Number).toString(), "Set of Number", "SetModel toString for basic elements")
194
+ assert.equal(SetModel([String, 42]).toString(), "Set of String or 42", "SetModel toString for union type elements")
195
+ })
196
+
197
+ QUnit.test("dynamic definition", function (assert) {
198
+ let S = SetModel(String);
199
+ let s1 = S(["hello", "world"])
200
+ S.definition = Number;
201
+ let s2 = S([1, 2, 3])
202
+ assert.equal(S.test(s1), false, "definition can be dynamically changed 1/4")
203
+ assert.equal(S.test(s2), true, "definition can be dynamically changed 2/4")
204
+ s1.clear();
205
+ assert.throws(() => s1.add("hello"), /TypeError/, "definition can be dynamically changed 3/4")
206
+ s1.add(42);
207
+ assert.ok(s1.has(42), "definition can be dynamically changed 4/4")
208
+
209
+ let OM = ObjectModel({ n: Number });
210
+ S.definition = OM;
211
+ s1.clear();
212
+ s1.add({ n: 42 });
213
+ assert.ok([...s1][0] instanceof OM, "autocast still works after definition dynamically changed")
214
214
  })
@@ -0,0 +1,17 @@
1
+ import {expectType} from 'tsd';
2
+ import { ObjectModel } from '../src/object-model';
3
+ import { SetModel } from '../src/set-model';
4
+
5
+ expectType<Set<string>>(SetModel(String)(new Set(["one", "two"])));
6
+
7
+ const Question = ObjectModel({
8
+ answer: Number
9
+ });
10
+
11
+ const Quiz = SetModel([Question, String, Boolean]);
12
+
13
+ expectType<Set<{ answer: number } | string | boolean>>(Quiz(new Set()));
14
+
15
+ const SetModel1 = SetModel(String)
16
+ const SetModel2 = SetModel1.extend(Date, Number)
17
+ expectType<Set<string | Date | number>>(SetModel2([1,"2",new Date()]))
package/test/umd.html CHANGED
@@ -1,26 +1,26 @@
1
- <!DOCTYPE html>
2
- <html>
3
-
4
- <head>
5
- <meta charset="utf-8">
6
- <title>QUnit - ObjectModel unit tests</title>
7
- <link rel="stylesheet" href="lib/qunit.css">
8
- <script src="lib/qunit.js"></script>
9
- <script src="https://umd.cdn.pika.dev/objectmodel/v4"></script>
10
- <script>const { Model, BasicModel, ObjectModel, ArrayModel, FunctionModel, MapModel, SetModel, Any } = objectmodel</script>
11
- <script src="model.spec.cjs"></script>
12
- <script src="basic-model.spec.cjs"></script>
13
- <script src="any-model.spec.cjs"></script>
14
- <script src="object-model.spec.cjs"></script>
15
- <script src="array-model.spec.cjs"></script>
16
- <script src="function-model.spec.cjs"></script>
17
- <script src="map-model.spec.cjs"></script>
18
- <script src="set-model.spec.cjs"></script>
19
- </head>
20
-
21
- <body>
22
- <div id="qunit"></div>
23
- <div id="qunit-fixture"></div>
24
- </body>
25
-
1
+ <!DOCTYPE html>
2
+ <html>
3
+
4
+ <head>
5
+ <meta charset="utf-8">
6
+ <title>QUnit - ObjectModel unit tests</title>
7
+ <link rel="stylesheet" href="lib/qunit.css">
8
+ <script src="lib/qunit.js"></script>
9
+ <script src="https://umd.cdn.pika.dev/objectmodel/v4"></script>
10
+ <script>const { Model, BasicModel, ObjectModel, ArrayModel, FunctionModel, MapModel, SetModel, Any } = objectmodel</script>
11
+ <script src="model.spec.cjs"></script>
12
+ <script src="basic-model.spec.cjs"></script>
13
+ <script src="any-model.spec.cjs"></script>
14
+ <script src="object-model.spec.cjs"></script>
15
+ <script src="array-model.spec.cjs"></script>
16
+ <script src="function-model.spec.cjs"></script>
17
+ <script src="map-model.spec.cjs"></script>
18
+ <script src="set-model.spec.cjs"></script>
19
+ </head>
20
+
21
+ <body>
22
+ <div id="qunit"></div>
23
+ <div id="qunit-fixture"></div>
24
+ </body>
25
+
26
26
  </html>
@@ -0,0 +1,43 @@
1
+ import { ArrayModel } from "../src/array-model"
2
+ import { FunctionModel, FunctionSignature } from "../src/function-model"
3
+ import { MapModel } from "../src/map-model"
4
+ import { SetModel } from "../src/set-model"
5
+ import { BasicModel, ObjectModel } from "../src/object-model"
6
+ import { Class, Prev } from "./helpers"
7
+
8
+
9
+ export type ModelDefinition = any
10
+ export type ObjectModelDefinition = Record<string | number | symbol, unknown>
11
+
12
+ export type FromDefinition<T, Depth extends Prev[number] = 5> =
13
+ [Depth] extends [never] ? never /* Depth limit reached */
14
+ : T extends BasicModel<infer U> ? FromDefinition<U, Prev[Depth]>
15
+ : T extends ArrayModel<infer U> ? FromDefinition<U, Prev[Depth]>[]
16
+ : T extends ObjectModel<infer D> ? FromObjectModelDefinition<D>
17
+ : T extends FunctionModel<infer Args, infer Return> ? FunctionSignature<Args, Return>
18
+ : T extends MapModel<infer Key, infer Value> ? Map<FromDefinition<Key, Prev[Depth]>, FromDefinition<Value, Prev[Depth]>>
19
+ : T extends SetModel<infer U> ? Set<FromDefinition<U, Prev[Depth]>>
20
+ : T extends StringConstructor | RegExp ? string
21
+ : T extends NumberConstructor ? number
22
+ : T extends BooleanConstructor ? boolean
23
+ : T extends new () => infer ConstructorType ? ConstructorType
24
+ : T extends Class ? InstanceType<T>
25
+ : T extends ObjectModelDefinition ? FromObjectModelDefinition<T>
26
+ : T extends readonly [...infer U] ? FromUnionDefinition<U>
27
+ : T extends any[] ? FromDefinition<T[number], Prev[Depth]> // TypeScript can't infer array literals as tuples for now without <const> assertions, see https://github.com/microsoft/TypeScript/issues/16656
28
+ : T
29
+
30
+ export type FromObjectModelDefinition<D extends object> = { [K in keyof D]: FromDefinition<D[K]> }
31
+
32
+ export type FromUnionDefinition<T extends any[]> = T extends [infer X] ? Optional<X>
33
+ : FromDefinition<T[number]>
34
+
35
+ export type Optional<T> = FromDefinition<T> | undefined | null
36
+
37
+ export type ExtendObjectDefinition<D extends ObjectModelDefinition, E extends (ObjectModelDefinition | ObjectModel<any>)[]> =
38
+ E extends [infer F, ...infer Rest extends (ObjectModelDefinition | ObjectModel<any>)[]]
39
+ ? F extends ObjectModel<infer FD>
40
+ ? ExtendObjectDefinition<D & FD, Rest>
41
+ : F extends ObjectModelDefinition ? ExtendObjectDefinition<D & FromObjectModelDefinition<F>, Rest>
42
+ : never
43
+ : D
@@ -0,0 +1,4 @@
1
+ export type Class = abstract new (...args: any) => any
2
+
3
+ /* Used to depth-limit recursive types */
4
+ export type Prev = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9];