@jakobkg/shapes-ts 0.1.1 → 0.2.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.
- package/README.md +92 -1
- package/dist/shapes.d.ts +24 -17
- package/dist/shapes.d.ts.map +1 -1
- package/dist/shapes.js +195 -149
- package/package.json +7 -1
package/README.md
CHANGED
|
@@ -1,3 +1,94 @@
|
|
|
1
1
|
# shapes-ts
|
|
2
2
|
|
|
3
|
-
Toy library to create runtime safe types in TS
|
|
3
|
+
Toy library to create runtime safe types in TS.
|
|
4
|
+
|
|
5
|
+
When describing the shape of your data in shapes-ts, you get the corresponding TS type and a validation utility for free!
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
const Role = Shapes.object({
|
|
9
|
+
role: Shapes.string(),
|
|
10
|
+
actor: Shapes.string(),
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
const Movie = Shapes.object({
|
|
14
|
+
title: Shapes.string(),
|
|
15
|
+
rating: Shapes.number().where(
|
|
16
|
+
(n) => n >= 0 && n <= 5,
|
|
17
|
+
"rating must be in range 0.0-5.0",
|
|
18
|
+
),
|
|
19
|
+
cast: Shapes.array(Role),
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
// This infers as
|
|
23
|
+
// {
|
|
24
|
+
// title: string,
|
|
25
|
+
// rating: number,
|
|
26
|
+
// cast: { role: string, actor: string }[]
|
|
27
|
+
// }
|
|
28
|
+
type Movie = Shapes.Type<typeof Movie>;
|
|
29
|
+
|
|
30
|
+
const movieData: unknown = getFromIMDB("tt23289160");
|
|
31
|
+
|
|
32
|
+
if (!Movie.check(movieData)) {
|
|
33
|
+
throw new Error("Unexpected data from API");
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Past this point, movieData is typed as Movie
|
|
37
|
+
|
|
38
|
+
for (const member of movieData.cast) {
|
|
39
|
+
console.log(`${member.actor} as ${member.role}`);
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Supported types
|
|
44
|
+
|
|
45
|
+
### Primitives
|
|
46
|
+
|
|
47
|
+
- string
|
|
48
|
+
- number
|
|
49
|
+
- boolean
|
|
50
|
+
- object
|
|
51
|
+
- array
|
|
52
|
+
|
|
53
|
+
### Modified types
|
|
54
|
+
|
|
55
|
+
- Nullable types (`T | null`)
|
|
56
|
+
- Optional types (`T | undefined`)
|
|
57
|
+
- Unions (`A & B`)
|
|
58
|
+
- Intersections (`A | B`)
|
|
59
|
+
|
|
60
|
+
## Predicates
|
|
61
|
+
|
|
62
|
+
Shapes can have additional validation checks added to them. These do not affect the inferred type, but are still ran as part of a shape's `.check()` method to help enforce constraints that are not easily modeled using the type system.
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
const Username = Shapes.string().where(
|
|
66
|
+
(str) => str.length < 10,
|
|
67
|
+
"must be less than 10 characters long",
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
Username.check("jakob :)"); // true
|
|
71
|
+
Username.check("CptAmericaFan207"); // false
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Predicates can be used with all types of shapes, and they may be combined both by stacking them on a single shape and by combining shapes that already have predicates on them.
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
const Fizz = Shapes.number().where(
|
|
78
|
+
(n) => n % 3 === 0,
|
|
79
|
+
"must be divisible by 3",
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
const Buzz = Shapes.number().where(
|
|
83
|
+
(n) => n % 5 === 0,
|
|
84
|
+
"must be divisible by 5",
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
const FizzBuzz = Fizz.and(Buzz);
|
|
88
|
+
|
|
89
|
+
Fizz.check(3); // true
|
|
90
|
+
FizzBuzz.check(3); // false
|
|
91
|
+
Fizz.check(5); // false
|
|
92
|
+
Buzz.check(5); // true
|
|
93
|
+
FizzBuzz.check(15); //true
|
|
94
|
+
```
|
package/dist/shapes.d.ts
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
|
+
declare const Predicates: unique symbol;
|
|
2
|
+
declare const Optional: unique symbol;
|
|
3
|
+
declare const Properties: unique symbol;
|
|
4
|
+
declare const AllowUnknownProperties: unique symbol;
|
|
1
5
|
/**
|
|
2
6
|
* Bridge to convert a Shape into a TS type.
|
|
3
7
|
*/
|
|
4
|
-
export type Type<T extends Shape>
|
|
8
|
+
export type Type<T> = T extends Shape<infer U> ? U : never;
|
|
5
9
|
type ShapePredicate<T> = (x: T) => boolean;
|
|
6
|
-
interface Shape<T
|
|
10
|
+
interface Shape<T> {
|
|
7
11
|
readonly typename: string;
|
|
8
|
-
readonly
|
|
9
|
-
readonly
|
|
10
|
-
readonly predicates: ShapePredicate<T>[];
|
|
12
|
+
readonly [Optional]?: boolean;
|
|
13
|
+
readonly [Predicates]: ShapePredicate<T>[];
|
|
11
14
|
check(x: unknown): x is T;
|
|
12
15
|
/**
|
|
13
16
|
* Adds a custom validation predicate to the shape
|
|
@@ -20,15 +23,15 @@ interface Shape<T = any> {
|
|
|
20
23
|
or<U>(other: Shape<U>): UnionShape<T, U>;
|
|
21
24
|
}
|
|
22
25
|
interface ObjectShape<T = Record<string, unknown>> extends Shape<T> {
|
|
23
|
-
readonly
|
|
24
|
-
readonly
|
|
26
|
+
readonly [Properties]: Record<string, Shape<T>>;
|
|
27
|
+
readonly [AllowUnknownProperties]?: boolean;
|
|
25
28
|
}
|
|
26
29
|
interface ObjectShapeOptions {
|
|
27
30
|
readonly allowUnknownProperties?: boolean;
|
|
28
31
|
readonly additionalPermittedProperties?: Record<string, Shape<Record<string, unknown>>>;
|
|
29
32
|
}
|
|
30
|
-
interface ArrayShape<T
|
|
31
|
-
readonly inner: T
|
|
33
|
+
interface ArrayShape<T> extends Shape<Array<T>> {
|
|
34
|
+
readonly inner: Shape<T>;
|
|
32
35
|
}
|
|
33
36
|
interface UnionShape<Left, Right> extends Shape<Left | Right> {
|
|
34
37
|
left: Shape<Left>;
|
|
@@ -38,11 +41,11 @@ interface IntersectionShape<Left, Right> extends Shape<Left & Right> {
|
|
|
38
41
|
left: Shape<Left>;
|
|
39
42
|
right: Shape<Right>;
|
|
40
43
|
}
|
|
41
|
-
interface OptionalShape<T
|
|
42
|
-
readonly inner: T
|
|
44
|
+
interface OptionalShape<T> extends Shape<T | undefined> {
|
|
45
|
+
readonly inner: Shape<T>;
|
|
43
46
|
}
|
|
44
|
-
interface NullableShape<T
|
|
45
|
-
readonly inner: T
|
|
47
|
+
interface NullableShape<T> extends Shape<T | null> {
|
|
48
|
+
readonly inner: Shape<T>;
|
|
46
49
|
}
|
|
47
50
|
/**
|
|
48
51
|
* Creates a shape representing a JS `number`.
|
|
@@ -57,15 +60,18 @@ export declare function string(): Shape<string>;
|
|
|
57
60
|
* Creates a shape representing a JS `boolean`.
|
|
58
61
|
*/
|
|
59
62
|
export declare function boolean(): Shape<boolean>;
|
|
63
|
+
type Primitive = number | string | boolean | object | null | undefined;
|
|
64
|
+
export declare function literal<X extends Primitive, T extends Primitive extends X ? never : X>(x: X): Shape<T>;
|
|
60
65
|
/**
|
|
61
66
|
* Creates an array shape, representing `Array<T>` (aka `T[]`).
|
|
62
67
|
* Takes the shape representing `T` as a parameter.
|
|
63
68
|
*/
|
|
64
|
-
export declare function array<T
|
|
69
|
+
export declare function array<T>(shape: Shape<T>): ArrayShape<T>;
|
|
65
70
|
/**
|
|
66
71
|
* Creates an object shape.
|
|
67
72
|
*
|
|
68
73
|
* @example
|
|
74
|
+
* ```typescript
|
|
69
75
|
* const Group = Shapes.object({
|
|
70
76
|
* id: Shapes.number(),
|
|
71
77
|
* name: Shapes.string(),
|
|
@@ -78,19 +84,20 @@ export declare function array<T extends Shape>(shape: T): ArrayShape<T>;
|
|
|
78
84
|
* Shapes.array(Group)
|
|
79
85
|
* )
|
|
80
86
|
* });
|
|
87
|
+
* ```
|
|
81
88
|
*/
|
|
82
|
-
export declare function object<T extends Record<string, Shape
|
|
89
|
+
export declare function object<T extends Record<string, Shape<any>>>(properties: T, options?: ObjectShapeOptions): ObjectShape<{
|
|
83
90
|
[K in keyof T]: Type<T[K]>;
|
|
84
91
|
}>;
|
|
85
92
|
/**
|
|
86
93
|
* Creates a shape representing an optional type.
|
|
87
94
|
* `Shapes.optional(T)` corresponds to `T | undefined`
|
|
88
95
|
*/
|
|
89
|
-
export declare function optional<T
|
|
96
|
+
export declare function optional<T>(shape: Shape<T>): OptionalShape<T>;
|
|
90
97
|
/**
|
|
91
98
|
* Creates a shape representing a nullable type.
|
|
92
99
|
* `Shapes.nullable(T)` corresponds to `T | null`
|
|
93
100
|
*/
|
|
94
|
-
export declare function nullable<T
|
|
101
|
+
export declare function nullable<T>(shape: Shape<T>): NullableShape<T>;
|
|
95
102
|
export {};
|
|
96
103
|
//# sourceMappingURL=shapes.d.ts.map
|
package/dist/shapes.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shapes.d.ts","sourceRoot":"","sources":["../src/shapes/shapes.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"shapes.d.ts","sourceRoot":"","sources":["../src/shapes/shapes.ts"],"names":[],"mappings":"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"}
|
package/dist/shapes.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
/// TYPE GUARDS
|
|
3
|
-
// These are static functions to avoid allocating guards per Shape instance,
|
|
4
|
-
// Shapes may reference these instead
|
|
5
2
|
var __assign = (this && this.__assign) || function () {
|
|
6
3
|
__assign = Object.assign || function(t) {
|
|
7
4
|
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
@@ -13,14 +10,33 @@ var __assign = (this && this.__assign) || function () {
|
|
|
13
10
|
};
|
|
14
11
|
return __assign.apply(this, arguments);
|
|
15
12
|
};
|
|
13
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
14
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
15
|
+
if (ar || !(i in from)) {
|
|
16
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
17
|
+
ar[i] = from[i];
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
21
|
+
};
|
|
16
22
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
23
|
exports.number = number;
|
|
18
24
|
exports.string = string;
|
|
19
25
|
exports.boolean = boolean;
|
|
26
|
+
exports.literal = literal;
|
|
20
27
|
exports.array = array;
|
|
21
28
|
exports.object = object;
|
|
22
29
|
exports.optional = optional;
|
|
23
30
|
exports.nullable = nullable;
|
|
31
|
+
/// SYMBOLS
|
|
32
|
+
// These are here to hide some API bits from consumers
|
|
33
|
+
var Predicates = Symbol();
|
|
34
|
+
var Optional = Symbol();
|
|
35
|
+
var Properties = Symbol();
|
|
36
|
+
var AllowUnknownProperties = Symbol();
|
|
37
|
+
/// TYPE GUARDS
|
|
38
|
+
// These are static functions to avoid allocating guards per Shape instance,
|
|
39
|
+
// Shapes may reference these instead
|
|
24
40
|
function isString(input) {
|
|
25
41
|
return typeof input === "string";
|
|
26
42
|
}
|
|
@@ -43,54 +59,51 @@ function isUndefined(input) {
|
|
|
43
59
|
return input === undefined;
|
|
44
60
|
}
|
|
45
61
|
function makeUnion(left, right) {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
return this;
|
|
55
|
-
},
|
|
56
|
-
check
|
|
62
|
+
var _a;
|
|
63
|
+
return _a = {
|
|
64
|
+
typename: "".concat(left.typename, " | ").concat(right.typename),
|
|
65
|
+
left: left,
|
|
66
|
+
right: right
|
|
67
|
+
},
|
|
68
|
+
_a[Predicates] = [],
|
|
69
|
+
_a.where = function (predicate) {
|
|
70
|
+
return __assign(__assign({}, this), { predicates: __spreadArray(__spreadArray([], this[Predicates], true), [predicate], false) });
|
|
71
|
+
},
|
|
72
|
+
_a.check = function (x) {
|
|
57
73
|
return (left.check(x) || right.check(x)) &&
|
|
58
|
-
this.
|
|
59
|
-
},
|
|
60
|
-
and
|
|
74
|
+
this[Predicates].every(function (p) { return p(x); });
|
|
75
|
+
},
|
|
76
|
+
_a.and = function (other) {
|
|
61
77
|
return makeIntersection(this, other);
|
|
62
78
|
},
|
|
63
|
-
or
|
|
79
|
+
_a.or = function (other) {
|
|
64
80
|
return makeUnion(this, other);
|
|
65
81
|
},
|
|
66
|
-
|
|
82
|
+
_a;
|
|
67
83
|
}
|
|
68
84
|
function makeIntersection(left, right) {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
return this;
|
|
82
|
-
},
|
|
83
|
-
check: function (x) {
|
|
85
|
+
var _a, _b, _c;
|
|
86
|
+
return _a = {
|
|
87
|
+
typename: "".concat(left.typename, " | ").concat(right.typename),
|
|
88
|
+
left: __assign(__assign({}, left), (_b = {}, _b[Properties] = __assign(__assign({}, right[Properties]), left[Properties]), _b)),
|
|
89
|
+
right: __assign(__assign({}, right), (_c = {}, _c[Properties] = __assign(__assign({}, left[Properties]), right[Properties]), _c))
|
|
90
|
+
},
|
|
91
|
+
_a[Predicates] = [],
|
|
92
|
+
_a.where = function (predicate) {
|
|
93
|
+
var _a;
|
|
94
|
+
return __assign(__assign({}, this), (_a = {}, _a[Predicates] = __spreadArray(__spreadArray([], this[Predicates], true), [predicate], false), _a));
|
|
95
|
+
},
|
|
96
|
+
_a.check = function (x) {
|
|
84
97
|
return this.left.check(x) && this.right.check(x) &&
|
|
85
|
-
this.
|
|
98
|
+
this[Predicates].every(function (p) { return p(x); });
|
|
86
99
|
},
|
|
87
|
-
and
|
|
100
|
+
_a.and = function (other) {
|
|
88
101
|
return makeIntersection(this, other);
|
|
89
102
|
},
|
|
90
|
-
or
|
|
103
|
+
_a.or = function (other) {
|
|
91
104
|
return makeUnion(this, other);
|
|
92
105
|
},
|
|
93
|
-
|
|
106
|
+
_a;
|
|
94
107
|
}
|
|
95
108
|
/// PRIMITIVE SHAPE FACTORIES
|
|
96
109
|
/**
|
|
@@ -98,70 +111,94 @@ function makeIntersection(left, right) {
|
|
|
98
111
|
* Does not support BigInt.
|
|
99
112
|
*/
|
|
100
113
|
function number() {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
114
|
+
var _a;
|
|
115
|
+
return _a = {
|
|
116
|
+
typename: "number"
|
|
117
|
+
},
|
|
118
|
+
_a[Predicates] = [],
|
|
119
|
+
_a.check = function (x) {
|
|
120
|
+
return isNumber(x) && this[Predicates].every(function (p) { return p(x); });
|
|
121
|
+
},
|
|
122
|
+
_a.where = function (predicate) {
|
|
123
|
+
var _a;
|
|
124
|
+
return __assign(__assign({}, this), (_a = {}, _a[Predicates] = __spreadArray(__spreadArray([], this[Predicates], true), [predicate], false), _a));
|
|
125
|
+
},
|
|
126
|
+
_a.and = function (other) {
|
|
113
127
|
return makeIntersection(this, other);
|
|
114
128
|
},
|
|
115
|
-
or
|
|
129
|
+
_a.or = function (other) {
|
|
116
130
|
return makeUnion(this, other);
|
|
117
131
|
},
|
|
118
|
-
|
|
132
|
+
_a;
|
|
119
133
|
}
|
|
120
134
|
/**
|
|
121
135
|
* Creates a shape representing a JS `string`.
|
|
122
136
|
*/
|
|
123
137
|
function string() {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
138
|
+
var _a;
|
|
139
|
+
return _a = {
|
|
140
|
+
typename: "string",
|
|
141
|
+
check: function (x) {
|
|
142
|
+
return isString(x) && this[Predicates].every(function (p) { return p(x); });
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
_a[Predicates] = [],
|
|
146
|
+
_a.where = function (predicate) {
|
|
147
|
+
var _a;
|
|
148
|
+
return __assign(__assign({}, this), (_a = {}, _a[Predicates] = __spreadArray(__spreadArray([], this[Predicates], true), [predicate], false), _a));
|
|
149
|
+
},
|
|
150
|
+
_a.and = function (other) {
|
|
136
151
|
return makeIntersection(this, other);
|
|
137
152
|
},
|
|
138
|
-
or
|
|
153
|
+
_a.or = function (other) {
|
|
139
154
|
return makeUnion(this, other);
|
|
140
155
|
},
|
|
141
|
-
|
|
156
|
+
_a;
|
|
142
157
|
}
|
|
143
158
|
/**
|
|
144
159
|
* Creates a shape representing a JS `boolean`.
|
|
145
160
|
*/
|
|
146
161
|
function boolean() {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
162
|
+
var _a;
|
|
163
|
+
return _a = {
|
|
164
|
+
typename: "boolean",
|
|
165
|
+
check: function (x) {
|
|
166
|
+
return isBoolean(x) && this[Predicates].every(function (p) { return p(x); });
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
_a[Predicates] = [],
|
|
170
|
+
_a.where = function (predicate) {
|
|
171
|
+
var _a;
|
|
172
|
+
return __assign(__assign({}, this), (_a = {}, _a[Predicates] = __spreadArray(__spreadArray([], this[Predicates], true), [predicate], false), _a));
|
|
173
|
+
},
|
|
174
|
+
_a.and = function (other) {
|
|
159
175
|
return makeIntersection(this, other);
|
|
160
176
|
},
|
|
161
|
-
or
|
|
177
|
+
_a.or = function (other) {
|
|
162
178
|
return makeUnion(this, other);
|
|
163
179
|
},
|
|
164
|
-
|
|
180
|
+
_a;
|
|
181
|
+
}
|
|
182
|
+
function literal(x) {
|
|
183
|
+
var _a;
|
|
184
|
+
return _a = {
|
|
185
|
+
typename: JSON.stringify(x)
|
|
186
|
+
},
|
|
187
|
+
_a[Predicates] = [],
|
|
188
|
+
_a.check = function (input) {
|
|
189
|
+
return input === x && this[Predicates].every(function (p) { return p(input); });
|
|
190
|
+
},
|
|
191
|
+
_a.where = function (predicate) {
|
|
192
|
+
var _a;
|
|
193
|
+
return __assign(__assign({}, this), (_a = {}, _a[Predicates] = __spreadArray(__spreadArray([], this[Predicates], true), [predicate], false), _a));
|
|
194
|
+
},
|
|
195
|
+
_a.and = function (other) {
|
|
196
|
+
return makeIntersection(this, other);
|
|
197
|
+
},
|
|
198
|
+
_a.or = function (other) {
|
|
199
|
+
return makeUnion(this, other);
|
|
200
|
+
},
|
|
201
|
+
_a;
|
|
165
202
|
}
|
|
166
203
|
/// COMPLEX SHAPE FACTORIES
|
|
167
204
|
/**
|
|
@@ -169,39 +206,41 @@ function boolean() {
|
|
|
169
206
|
* Takes the shape representing `T` as a parameter.
|
|
170
207
|
*/
|
|
171
208
|
function array(shape) {
|
|
209
|
+
var _a;
|
|
172
210
|
var typename = "Array<".concat(shape.typename, ">");
|
|
173
|
-
return {
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
if (!isArray(input)) {
|
|
179
|
-
return false;
|
|
180
|
-
}
|
|
181
|
-
return input.every(function (entry) {
|
|
182
|
-
if (!shape.check(entry)) {
|
|
211
|
+
return _a = {
|
|
212
|
+
typename: typename,
|
|
213
|
+
inner: shape,
|
|
214
|
+
check: function (input) {
|
|
215
|
+
if (!isArray(input)) {
|
|
183
216
|
return false;
|
|
184
217
|
}
|
|
185
|
-
return
|
|
186
|
-
|
|
218
|
+
return input.every(function (entry) {
|
|
219
|
+
if (!shape.check(entry)) {
|
|
220
|
+
return false;
|
|
221
|
+
}
|
|
222
|
+
return true;
|
|
223
|
+
}) && this[Predicates].every(function (p) { return p(input); });
|
|
224
|
+
}
|
|
187
225
|
},
|
|
188
|
-
|
|
189
|
-
where
|
|
190
|
-
|
|
191
|
-
return this;
|
|
226
|
+
_a[Predicates] = [],
|
|
227
|
+
_a.where = function (predicate) {
|
|
228
|
+
var _a;
|
|
229
|
+
return __assign(__assign({}, this), (_a = {}, _a[Predicates] = __spreadArray(__spreadArray([], this[Predicates], true), [predicate], false), _a));
|
|
192
230
|
},
|
|
193
|
-
and
|
|
231
|
+
_a.and = function (other) {
|
|
194
232
|
return makeIntersection(this, other);
|
|
195
233
|
},
|
|
196
|
-
or
|
|
234
|
+
_a.or = function (other) {
|
|
197
235
|
return makeUnion(this, other);
|
|
198
236
|
},
|
|
199
|
-
|
|
237
|
+
_a;
|
|
200
238
|
}
|
|
201
239
|
/**
|
|
202
240
|
* Creates an object shape.
|
|
203
241
|
*
|
|
204
242
|
* @example
|
|
243
|
+
* ```typescript
|
|
205
244
|
* const Group = Shapes.object({
|
|
206
245
|
* id: Shapes.number(),
|
|
207
246
|
* name: Shapes.string(),
|
|
@@ -214,31 +253,35 @@ function array(shape) {
|
|
|
214
253
|
* Shapes.array(Group)
|
|
215
254
|
* )
|
|
216
255
|
* });
|
|
256
|
+
* ```
|
|
217
257
|
*/
|
|
258
|
+
// deno-lint-ignore no-explicit-any
|
|
218
259
|
function object(properties, options) {
|
|
260
|
+
var _a;
|
|
219
261
|
var allowUnknownProperties = options === null || options === void 0 ? void 0 : options.allowUnknownProperties;
|
|
220
|
-
return {
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
262
|
+
return _a = {
|
|
263
|
+
typename: "Object"
|
|
264
|
+
},
|
|
265
|
+
_a[AllowUnknownProperties] = allowUnknownProperties,
|
|
266
|
+
_a.check = function (input) {
|
|
224
267
|
// Check that input is an object
|
|
225
268
|
if (!isObject(input)) {
|
|
226
269
|
return false;
|
|
227
270
|
}
|
|
228
271
|
// Check for unknown properties
|
|
229
|
-
if (!this
|
|
272
|
+
if (!this[AllowUnknownProperties]) {
|
|
230
273
|
for (var inputProperty in input) {
|
|
231
|
-
if (!(inputProperty in this
|
|
274
|
+
if (!(inputProperty in this[Properties])) {
|
|
232
275
|
return false;
|
|
233
276
|
}
|
|
234
277
|
}
|
|
235
278
|
}
|
|
236
279
|
// Check required properties and their types
|
|
237
|
-
for (var property in
|
|
280
|
+
for (var property in this[Properties]) {
|
|
238
281
|
var field = input[property];
|
|
239
|
-
var propertyShape =
|
|
282
|
+
var propertyShape = this[Properties][property];
|
|
240
283
|
// Property presence check
|
|
241
|
-
if (!(property in input) && !propertyShape
|
|
284
|
+
if (!(property in input) && !propertyShape[Optional]) {
|
|
242
285
|
return false;
|
|
243
286
|
}
|
|
244
287
|
// Property type check
|
|
@@ -246,22 +289,21 @@ function object(properties, options) {
|
|
|
246
289
|
return false;
|
|
247
290
|
}
|
|
248
291
|
}
|
|
249
|
-
return this.
|
|
292
|
+
return this[Predicates].every(function (p) { return p(input); });
|
|
250
293
|
},
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
this
|
|
256
|
-
return this;
|
|
294
|
+
_a[Properties] = __assign(__assign({}, properties), options === null || options === void 0 ? void 0 : options.additionalPermittedProperties),
|
|
295
|
+
_a[Predicates] = [],
|
|
296
|
+
_a.where = function (predicate) {
|
|
297
|
+
var _a;
|
|
298
|
+
return __assign(__assign({}, this), (_a = {}, _a[Predicates] = __spreadArray(__spreadArray([], this[Predicates], true), [predicate], false), _a));
|
|
257
299
|
},
|
|
258
|
-
and
|
|
300
|
+
_a.and = function (other) {
|
|
259
301
|
return makeIntersection(this, other);
|
|
260
302
|
},
|
|
261
|
-
or
|
|
303
|
+
_a.or = function (other) {
|
|
262
304
|
return makeUnion(this, other);
|
|
263
305
|
},
|
|
264
|
-
|
|
306
|
+
_a;
|
|
265
307
|
}
|
|
266
308
|
/// TYPE MODIFIERS
|
|
267
309
|
/**
|
|
@@ -269,50 +311,54 @@ function object(properties, options) {
|
|
|
269
311
|
* `Shapes.optional(T)` corresponds to `T | undefined`
|
|
270
312
|
*/
|
|
271
313
|
function optional(shape) {
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
314
|
+
var _a;
|
|
315
|
+
return _a = {
|
|
316
|
+
typename: "".concat(shape.typename, " | undefined"),
|
|
317
|
+
inner: shape
|
|
318
|
+
},
|
|
319
|
+
_a[Optional] = true,
|
|
320
|
+
_a[Predicates] = [],
|
|
321
|
+
_a.check = function (input) {
|
|
322
|
+
return (isUndefined(input) || shape.check(input)) &&
|
|
323
|
+
this[Predicates].every(function (p) { return p(input); });
|
|
324
|
+
},
|
|
325
|
+
_a.where = function (predicate) {
|
|
326
|
+
var _a;
|
|
327
|
+
return __assign(__assign({}, this), (_a = {}, _a[Predicates] = __spreadArray(__spreadArray([], this[Predicates], true), [predicate], false), _a));
|
|
328
|
+
},
|
|
329
|
+
_a.and = function (other) {
|
|
286
330
|
return makeIntersection(this, other);
|
|
287
331
|
},
|
|
288
|
-
or
|
|
332
|
+
_a.or = function (other) {
|
|
289
333
|
return makeUnion(this, other);
|
|
290
334
|
},
|
|
291
|
-
|
|
335
|
+
_a;
|
|
292
336
|
}
|
|
293
337
|
/**
|
|
294
338
|
* Creates a shape representing a nullable type.
|
|
295
339
|
* `Shapes.nullable(T)` corresponds to `T | null`
|
|
296
340
|
*/
|
|
297
341
|
function nullable(shape) {
|
|
298
|
-
var
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
342
|
+
var _a;
|
|
343
|
+
var nullShape = (_a = {
|
|
344
|
+
typename: "".concat(shape.typename, " | null"),
|
|
345
|
+
check: function (input) {
|
|
346
|
+
return (isNull(input) || shape.check(input)) &&
|
|
347
|
+
this[Predicates].every(function (p) { return p(input); });
|
|
348
|
+
},
|
|
349
|
+
inner: shape
|
|
350
|
+
},
|
|
351
|
+
_a[Predicates] = [],
|
|
352
|
+
_a.where = function (predicate) {
|
|
353
|
+
var _a;
|
|
354
|
+
return __assign(__assign({}, this), (_a = {}, _a[Predicates] = __spreadArray(__spreadArray([], this[Predicates], true), [predicate], false), _a));
|
|
355
|
+
},
|
|
356
|
+
_a.and = function (other) {
|
|
311
357
|
return makeIntersection(this, other);
|
|
312
358
|
},
|
|
313
|
-
or
|
|
359
|
+
_a.or = function (other) {
|
|
314
360
|
return makeUnion(this, other);
|
|
315
361
|
},
|
|
316
|
-
|
|
362
|
+
_a);
|
|
317
363
|
return nullShape;
|
|
318
364
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jakobkg/shapes-ts",
|
|
3
|
-
"
|
|
3
|
+
"repository": {
|
|
4
|
+
"type": "git",
|
|
5
|
+
"url": "https://codeberg.org/jakobkg/shapes-ts"
|
|
6
|
+
},
|
|
7
|
+
"homepage": "https://codeberg.org/jakobkg/shapes-ts#readme",
|
|
8
|
+
"license": "BSD-3-Clause",
|
|
9
|
+
"version": "0.2.0",
|
|
4
10
|
"private": false,
|
|
5
11
|
"main": "dist/index.js",
|
|
6
12
|
"scripts": {
|