functionalscript 0.46.1 → 0.47.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/fjs/basen/cbase32/module.f.mjs +18 -10
- package/fjs/basen/cbase32/proof.f.d.mts +3 -0
- package/fjs/basen/cbase32/proof.f.mjs +24 -2
- package/fjs/basen/proof.f.mjs +8 -16
- package/fjs/bnf/ll1/proof.f.d.mts +2 -0
- package/fjs/bnf/ll1/proof.f.mjs +33 -18
- package/fjs/bnf/module.f.d.mts +2 -2
- package/fjs/bnf/module.f.mjs +2 -2
- package/fjs/cas/proof.f.mjs +4 -26
- package/fjs/ci/common/module.f.mjs +6 -0
- package/fjs/ci/config/module.f.d.mts +7 -7
- package/fjs/ci/config/module.f.mjs +7 -7
- package/fjs/cli/module.f.mjs +14 -10
- package/fjs/crypto/vdf/module.f.d.mts +0 -1
- package/fjs/crypto/vdf/module.f.mjs +3 -14
- package/fjs/dev/module.f.mjs +10 -20
- package/fjs/djs/parser/module.f.d.mts +101 -53
- package/fjs/djs/parser/module.f.mjs +732 -525
- package/fjs/djs/parser/proof.f.d.mts +6 -0
- package/fjs/djs/parser/proof.f.mjs +315 -11
- package/fjs/djs/parser/types.d.ts +29 -2
- package/fjs/djs/tokenizer/module.f.mjs +122 -105
- package/fjs/djs/tokenizer/proof.f.mjs +17 -0
- package/fjs/djs/transpiler/module.f.mjs +4 -5
- package/fjs/djs/transpiler/proof.f.d.mts +2 -0
- package/fjs/djs/transpiler/proof.f.mjs +25 -0
- package/fjs/edag/amnesia/module.f.d.mts +20 -0
- package/fjs/edag/amnesia/module.f.mjs +303 -0
- package/fjs/edag/amnesia/proof.f.d.mts +79 -0
- package/fjs/edag/amnesia/proof.f.mjs +573 -0
- package/fjs/edag/amnesia/types.d.ts +15 -0
- package/fjs/edag/module.f.d.mts +410 -0
- package/fjs/edag/module.f.mjs +559 -0
- package/fjs/edag/proof.f.d.mts +116 -0
- package/fjs/edag/proof.f.mjs +686 -0
- package/fjs/edag/types.d.ts +55 -0
- package/fjs/effects/node/memory/module.d.mts +37 -3
- package/fjs/effects/node/memory/module.mjs +38 -4
- package/fjs/effects/node/memory/proof.d.mts +5 -2
- package/fjs/effects/node/memory/proof.mjs +36 -6
- package/fjs/effects/node/module.d.mts +9 -1
- package/fjs/effects/node/module.f.d.mts +39 -0
- package/fjs/effects/node/module.f.mjs +46 -0
- package/fjs/effects/node/module.mjs +234 -32
- package/fjs/effects/node/types.d.ts +28 -2
- package/fjs/effects/node/virtual/module.f.d.mts +19 -10
- package/fjs/effects/node/virtual/module.f.mjs +246 -32
- package/fjs/effects/node/virtual/proof.f.d.mts +17 -2
- package/fjs/effects/node/virtual/proof.f.mjs +232 -8
- package/fjs/effects/node/virtual/types.d.ts +57 -1
- package/fjs/emergent_testing/browser/proof.d.mts +55 -0
- package/fjs/emergent_testing/browser/proof.mjs +352 -0
- package/fjs/emergent_testing/browser/species.proof.d.mts +4 -0
- package/fjs/emergent_testing/browser/species.proof.mjs +45 -0
- package/fjs/emergent_testing/browser.d.mts +79 -0
- package/fjs/emergent_testing/browser.mjs +432 -0
- package/fjs/emergent_testing/proof.f.d.mts +1 -1
- package/fjs/emergent_testing/proof.f.mjs +2 -2
- package/fjs/js/string_escape/module.f.d.mts +47 -0
- package/fjs/js/string_escape/module.f.mjs +95 -0
- package/fjs/js/string_escape/proof.f.d.mts +8 -0
- package/fjs/js/string_escape/proof.f.mjs +68 -0
- package/fjs/js/tokenizer/module.f.mjs +14 -12
- package/fjs/mcp/cas/module.f.d.mts +1 -7
- package/fjs/mcp/cas/module.f.mjs +24 -15
- package/fjs/mcp/evo/module.f.mjs +9 -24
- package/fjs/mcp/module.f.d.mts +3 -1
- package/fjs/mcp/module.f.mjs +4 -2
- package/fjs/media/json/rtti/module.f.d.mts +2 -2
- package/fjs/media/json/rtti/module.f.mjs +1 -1
- package/fjs/media/json/schema/module.f.d.mts +15 -5
- package/fjs/media/json/schema/module.f.mjs +42 -15
- package/fjs/media/json/schema/proof.f.d.mts +10 -1
- package/fjs/media/json/schema/proof.f.mjs +88 -16
- package/fjs/media/json/serializer/module.f.mjs +14 -26
- package/fjs/media/json/types.d.ts +1 -1
- package/fjs/media/lock/module.f.d.mts +8 -3
- package/fjs/media/lock/module.f.mjs +9 -3
- package/fjs/media/lock/proof.f.d.mts +1 -1
- package/fjs/media/lock/proof.f.mjs +2 -2
- package/fjs/media/lock/types.d.ts +1 -3
- package/fjs/media/module.f.d.mts +20 -13
- package/fjs/media/module.f.mjs +29 -16
- package/fjs/media/note/module.f.d.mts +14 -7
- package/fjs/media/note/module.f.mjs +14 -7
- package/fjs/media/note/proof.f.mjs +1 -1
- package/fjs/media/proof.f.mjs +5 -5
- package/fjs/media/revision/module.f.d.mts +8 -2
- package/fjs/media/revision/module.f.mjs +9 -3
- package/fjs/media/revision/proof.f.mjs +1 -1
- package/fjs/media/revision/types.d.ts +1 -1
- package/fjs/media/type/module.f.d.mts +20 -0
- package/fjs/media/type/module.f.mjs +74 -0
- package/fjs/media/type/proof.f.d.mts +5 -0
- package/fjs/media/type/proof.f.mjs +24 -1
- package/fjs/module.f.mjs +6 -0
- package/fjs/path/module.f.d.mts +60 -3
- package/fjs/path/module.f.mjs +138 -14
- package/fjs/path/proof.f.d.mts +3 -0
- package/fjs/path/proof.f.mjs +298 -2
- package/fjs/protocol/json_rpc/module.f.d.mts +65 -28
- package/fjs/protocol/json_rpc/module.f.mjs +49 -13
- package/fjs/protocol/json_rpc/proof.f.d.mts +4 -0
- package/fjs/protocol/json_rpc/proof.f.mjs +29 -0
- package/fjs/protocol/json_rpc/types.d.ts +12 -2
- package/fjs/protocol/mcp/module.f.d.mts +89 -54
- package/fjs/protocol/mcp/module.f.mjs +110 -56
- package/fjs/protocol/mcp/proof.f.d.mts +13 -0
- package/fjs/protocol/mcp/proof.f.mjs +107 -7
- package/fjs/protocol/mcp/stdio/module.f.mjs +3 -4
- package/fjs/protocol/mcp/stdio/proof.f.mjs +2 -2
- package/fjs/protocol/mcp/types.d.ts +14 -2
- package/fjs/text/utf8/module.f.mjs +27 -1
- package/fjs/text/utf8/proof.f.mjs +37 -0
- package/fjs/types/array/module.f.mjs +18 -11
- package/fjs/types/array/proof.f.mjs +27 -1
- package/fjs/types/bigfloat/module.f.d.mts +48 -9
- package/fjs/types/bigfloat/module.f.mjs +147 -59
- package/fjs/types/bigfloat/proof.f.d.mts +2 -0
- package/fjs/types/bigfloat/proof.f.mjs +136 -4
- package/fjs/types/bigfloat/types.d.ts +17 -0
- package/fjs/types/function/module.f.d.mts +11 -2
- package/fjs/types/function/module.f.mjs +20 -2
- package/fjs/types/function/proof.f.mjs +5 -1
- package/fjs/types/phantom/types.d.ts +21 -0
- package/fjs/types/result/module.f.d.mts +4 -4
- package/fjs/types/result/module.f.mjs +2 -2
- package/fjs/types/result/proof.f.d.mts +6 -2
- package/fjs/types/result/proof.f.mjs +17 -1
- package/fjs/types/rtti/common/module.f.d.mts +78 -5
- package/fjs/types/rtti/common/module.f.mjs +168 -3
- package/fjs/types/rtti/common/proof.f.d.mts +14 -0
- package/fjs/types/rtti/common/proof.f.mjs +61 -2
- package/fjs/types/rtti/common/types.d.ts +23 -1
- package/fjs/types/rtti/data/module.f.d.mts +57 -1
- package/fjs/types/rtti/data/module.f.mjs +241 -47
- package/fjs/types/rtti/data/proof.f.d.mts +10 -0
- package/fjs/types/rtti/data/proof.f.mjs +272 -39
- package/fjs/types/rtti/data/types.d.ts +14 -7
- package/fjs/types/rtti/host.proof.d.mts +33 -0
- package/fjs/types/rtti/host.proof.mjs +170 -0
- package/fjs/types/rtti/module.f.d.mts +51 -6
- package/fjs/types/rtti/module.f.mjs +50 -3
- package/fjs/types/rtti/parse/module.f.d.mts +31 -24
- package/fjs/types/rtti/parse/module.f.mjs +197 -59
- package/fjs/types/rtti/parse/proof.f.d.mts +37 -2
- package/fjs/types/rtti/parse/proof.f.mjs +171 -47
- package/fjs/types/rtti/proof.f.d.mts +6 -0
- package/fjs/types/rtti/proof.f.mjs +42 -1
- package/fjs/types/rtti/ts/module.f.d.mts +9 -3
- package/fjs/types/rtti/ts/module.f.mjs +68 -15
- package/fjs/types/rtti/ts/proof.f.d.mts +42 -2
- package/fjs/types/rtti/ts/proof.f.mjs +139 -6
- package/fjs/types/rtti/ts/types.d.ts +164 -16
- package/fjs/types/rtti/types.d.ts +31 -3
- package/fjs/types/rtti/validate/module.f.d.mts +42 -25
- package/fjs/types/rtti/validate/module.f.mjs +187 -53
- package/fjs/types/rtti/validate/proof.f.d.mts +28 -2
- package/fjs/types/rtti/validate/proof.f.mjs +430 -75
- package/fjs/types/ts/types.d.ts +4 -0
- package/fjs/web/module.f.d.mts +115 -0
- package/fjs/web/module.f.mjs +581 -0
- package/fjs/web/proof.f.d.mts +39 -0
- package/fjs/web/proof.f.mjs +413 -0
- package/fjs/web/types.d.ts +39 -0
- package/fjs/website/browser-prepare.d.mts +5 -0
- package/fjs/website/browser-prepare.mjs +115 -0
- package/fjs/website/browser-source.d.mts +37 -0
- package/fjs/website/browser-source.mjs +202 -0
- package/fjs/website/browser-source.proof.d.mts +31 -0
- package/fjs/website/browser-source.proof.mjs +162 -0
- package/fjs/website/browser.d.mts +5 -0
- package/fjs/website/browser.mjs +8 -0
- package/fjs/website/module.f.d.mts +3 -3
- package/fjs/website/module.f.mjs +62 -9
- package/fjs/website/proof.f.d.mts +4 -0
- package/fjs/website/proof.f.mjs +18 -3
- package/package.json +2 -3
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
* @import { ValidationError } from '../common/types.ts'
|
|
3
3
|
* @import { Equal } from '../../ts/types.ts'
|
|
4
4
|
* @import { Ts } from '../ts/types.ts'
|
|
5
|
+
* @import { Parse } from './types.ts'
|
|
5
6
|
* @import { Unknown as DjsUnknown } from '../../../djs/types.ts'
|
|
6
7
|
* @import { Assert } from '../../../asserts/types.ts'
|
|
8
|
+
* @import { Phantom } from '../../phantom/types.ts'
|
|
7
9
|
*/
|
|
8
10
|
|
|
9
11
|
import { parse } from './module.f.mjs'
|
|
10
|
-
import { boolean, number, string, bigint, unknown, array, record, or, option } from '../module.f.mjs'
|
|
12
|
+
import { boolean, number, string, bigint, unknown, array, open, record, rest, or, option } from '../module.f.mjs'
|
|
11
13
|
import {
|
|
12
14
|
assert,
|
|
13
15
|
assertEq,
|
|
@@ -30,6 +32,23 @@ const unwrap = r => {
|
|
|
30
32
|
return /** @type {T} */ (r[1])
|
|
31
33
|
}
|
|
32
34
|
|
|
35
|
+
/** A container that contains itself: `[number, node?]`. */
|
|
36
|
+
/** @typedef {readonly [number, _Node | undefined]} _Node */
|
|
37
|
+
|
|
38
|
+
const _node = () => /** @type {const} */ (['const', [number, option(_node)]])
|
|
39
|
+
|
|
40
|
+
/** @type {Phantom<typeof _node, _Node>} */
|
|
41
|
+
const node = _node
|
|
42
|
+
|
|
43
|
+
/** A struct whose every undeclared key holds another one of these. */
|
|
44
|
+
/** @typedef {() => readonly ['rest', { readonly a: typeof number }, _Nest]} _Nest */
|
|
45
|
+
|
|
46
|
+
/** @type {_Nest} */
|
|
47
|
+
const _nest = () => ['rest', { a: number }, _nest]
|
|
48
|
+
|
|
49
|
+
/** @type {Phantom<_Nest, { readonly a: number }>} */
|
|
50
|
+
const nest = _nest
|
|
51
|
+
|
|
33
52
|
/** @type {(expected: readonly string[]) => (r: readonly [string, unknown]) => void} */
|
|
34
53
|
const assertErrorPath = expected =>
|
|
35
54
|
r => {
|
|
@@ -105,15 +124,15 @@ export const proof = {
|
|
|
105
124
|
error: () => assertError(parse(undefined)(null)),
|
|
106
125
|
},
|
|
107
126
|
number: {
|
|
108
|
-
ok: () => assertOk(parse(
|
|
109
|
-
error: () => assertError(parse(
|
|
127
|
+
ok: () => assertOk(parse(42)(42)),
|
|
128
|
+
error: () => assertError(parse(42)(43)),
|
|
110
129
|
},
|
|
111
130
|
nan: {
|
|
112
131
|
ok: () => assertOk(parse(NaN)(NaN)),
|
|
113
132
|
error: () => {
|
|
114
133
|
assertError(parse(NaN)(0))
|
|
115
|
-
assertError(parse(
|
|
116
|
-
assertError(parse(
|
|
134
|
+
assertError(parse(0)(NaN))
|
|
135
|
+
assertError(parse(42)(NaN))
|
|
117
136
|
},
|
|
118
137
|
},
|
|
119
138
|
infinity: {
|
|
@@ -129,44 +148,39 @@ export const proof = {
|
|
|
129
148
|
signedZero: {
|
|
130
149
|
// `Object.is` distinguishes +0 and -0; `===` treats them equal.
|
|
131
150
|
distinct: () => {
|
|
132
|
-
assertError(parse(
|
|
151
|
+
assertError(parse(0)(-0))
|
|
133
152
|
assertError(parse(-0)(0))
|
|
134
153
|
},
|
|
135
154
|
self: () => {
|
|
136
|
-
assertOk(parse(
|
|
155
|
+
assertOk(parse(0)(0))
|
|
137
156
|
assertOk(parse(-0)(-0))
|
|
138
157
|
},
|
|
139
158
|
},
|
|
140
159
|
string: {
|
|
141
|
-
ok: () => assertOk(parse(
|
|
142
|
-
error: () => assertError(parse(
|
|
160
|
+
ok: () => assertOk(parse('hello')('hello')),
|
|
161
|
+
error: () => assertError(parse('hello')('world')),
|
|
143
162
|
},
|
|
144
163
|
bigint: {
|
|
145
|
-
ok: () => assertOk(parse(
|
|
146
|
-
error: () => assertError(parse(
|
|
164
|
+
ok: () => assertOk(parse(7n)(7n)),
|
|
165
|
+
error: () => assertError(parse(7n)(8n)),
|
|
147
166
|
},
|
|
148
167
|
boolean: {
|
|
149
|
-
ok: () => assertOk(parse(
|
|
150
|
-
error: () => assertError(parse(
|
|
168
|
+
ok: () => assertOk(parse(true)(true)),
|
|
169
|
+
error: () => assertError(parse(true)(false)),
|
|
151
170
|
},
|
|
152
171
|
tuple: {
|
|
153
172
|
ok: () => {
|
|
154
|
-
const
|
|
155
|
-
const r = parse(t)([42, 'hello'])
|
|
173
|
+
const r = parse([42, 'hello'])([42, 'hello'])
|
|
156
174
|
assertStructurallySame(unwrap(r), [42, 'hello'])
|
|
157
175
|
},
|
|
158
|
-
// A tuple is
|
|
159
|
-
//
|
|
160
|
-
//
|
|
161
|
-
//
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
const r = parse(/** @type {const} */ ([42]))([42, 'extra'])
|
|
167
|
-
assertStructurallySame(unwrap(r), [42])
|
|
168
|
-
const long = parse(/** @type {const} */ ([42]))([42, 1, 2, 3])
|
|
169
|
-
assertStructurallySame(unwrap(long), [42])
|
|
176
|
+
// A tuple is CLOSED: a longer array is not one of its values —
|
|
177
|
+
// see "Structs and tuples are closed" in ../README.md. Under
|
|
178
|
+
// `open` it is accepted, and the extras are absent from what
|
|
179
|
+
// `parse` builds.
|
|
180
|
+
extraItemsRejected: () => {
|
|
181
|
+
assertError(parse([42])([42, 'extra']))
|
|
182
|
+
assertStructurallySame(unwrap(parse(open([42]))([42, 'extra'])), [42])
|
|
183
|
+
assertStructurallySame(unwrap(parse(open([42]))([42, 1, 2, 3])), [42])
|
|
170
184
|
},
|
|
171
185
|
// An absent member reads as `undefined`, so a position is required
|
|
172
186
|
// exactly when its set excludes `undefined` — the same rule the
|
|
@@ -176,28 +190,32 @@ export const proof = {
|
|
|
176
190
|
assertStructurallySame(unwrap(r), [42, undefined])
|
|
177
191
|
},
|
|
178
192
|
error: () => {
|
|
179
|
-
assertError(parse(
|
|
180
|
-
assertError(parse(
|
|
193
|
+
assertError(parse([42])([99]))
|
|
194
|
+
assertError(parse([42])({}))
|
|
181
195
|
// `42` excludes `undefined`, so position 0 is required.
|
|
182
|
-
assertError(parse(
|
|
196
|
+
assertError(parse([42])([]))
|
|
183
197
|
},
|
|
184
198
|
},
|
|
185
199
|
struct: {
|
|
200
|
+
// `parse` takes a `const` type parameter, so a struct literal keeps
|
|
201
|
+
// its literal members without an `@type {const}` cast at the call
|
|
202
|
+
// site: this is a reader for `{ a: 42, b: 'hello' }`, not for
|
|
203
|
+
// `{ a: number, b: string }`. Dropping the modifier is what makes
|
|
204
|
+
// the assertion fail.
|
|
186
205
|
ok: () => {
|
|
187
|
-
const
|
|
188
|
-
|
|
189
|
-
assertStructurallySame(unwrap(
|
|
206
|
+
const p = parse({ a: 42, b: 'hello' })
|
|
207
|
+
/** @typedef {Assert<Equal<typeof p, Parse<{ readonly a: 42, readonly b: 'hello' }>>>} _ConstParameter */
|
|
208
|
+
assertStructurallySame(unwrap(p({ a: 42, b: 'hello' })), { a: 42, b: 'hello' })
|
|
190
209
|
},
|
|
191
|
-
// A struct is
|
|
192
|
-
//
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
assertStructurallySame(unwrap(r), { a: 42 })
|
|
210
|
+
// A struct is CLOSED, on the same terms as a tuple. See "Structs
|
|
211
|
+
// and tuples are closed" in ../README.md.
|
|
212
|
+
extraKeysRejected: () => {
|
|
213
|
+
assertError(parse({ a: 42 })({ a: 42, b: 'extra' }))
|
|
214
|
+
assertStructurallySame(unwrap(parse(open({ a: 42 }))({ a: 42, b: 'extra' })), { a: 42 })
|
|
197
215
|
},
|
|
198
216
|
error: () => {
|
|
199
|
-
assertError(parse(
|
|
200
|
-
assertError(parse(
|
|
217
|
+
assertError(parse({ a: 42 })({ a: 99 }))
|
|
218
|
+
assertError(parse({ a: 42 })([]))
|
|
201
219
|
},
|
|
202
220
|
},
|
|
203
221
|
},
|
|
@@ -262,13 +280,13 @@ export const proof = {
|
|
|
262
280
|
or: {
|
|
263
281
|
consts: {
|
|
264
282
|
ok: () => {
|
|
265
|
-
const t = or(
|
|
283
|
+
const t = or(false, 42, 'hello')
|
|
266
284
|
assertOk(parse(t)(false))
|
|
267
285
|
assertOk(parse(t)(42))
|
|
268
286
|
assertOk(parse(t)('hello'))
|
|
269
287
|
},
|
|
270
288
|
error: () => {
|
|
271
|
-
const t = or(
|
|
289
|
+
const t = or(false, 42, 'hello')
|
|
272
290
|
assertError(parse(t)(true))
|
|
273
291
|
assertError(parse(t)(43))
|
|
274
292
|
assertError(parse(t)('world'))
|
|
@@ -289,10 +307,11 @@ export const proof = {
|
|
|
289
307
|
},
|
|
290
308
|
// First matching variant wins; the freshly-constructed value comes from that variant.
|
|
291
309
|
firstMatchWins: () => {
|
|
292
|
-
const t = or(
|
|
310
|
+
const t = or(open([number]), array(number))
|
|
293
311
|
/** @type {readonly number[]} */
|
|
294
312
|
const out = unwrap(parse(t)([1, 2, 3]))
|
|
295
|
-
// The
|
|
313
|
+
// The open tuple `open([number])` matches first and returns a
|
|
314
|
+
// length-1 result; the closed `[number]` would not match at all.
|
|
296
315
|
assertStructurallySame(out, [1])
|
|
297
316
|
},
|
|
298
317
|
},
|
|
@@ -319,10 +338,10 @@ export const proof = {
|
|
|
319
338
|
parse(array(array(number)))([[1, 'x'], [2, 3]])
|
|
320
339
|
),
|
|
321
340
|
tupleIndex: () => assertErrorPath(['1'])(
|
|
322
|
-
parse(
|
|
341
|
+
parse([number, number])([1, 'two'])
|
|
323
342
|
),
|
|
324
343
|
structKey: () => assertErrorPath(['b'])(
|
|
325
|
-
parse(
|
|
344
|
+
parse({ a: number, b: number })({ a: 1, b: 'two' })
|
|
326
345
|
),
|
|
327
346
|
deepStruct: () => {
|
|
328
347
|
const schema = /** @type {const} */ ({ user: { name: string, age: number } })
|
|
@@ -359,4 +378,109 @@ export const proof = {
|
|
|
359
378
|
assertError(v({ a: 42 }))
|
|
360
379
|
},
|
|
361
380
|
},
|
|
381
|
+
// A bare container is closed, and a stated rest widens acceptance without
|
|
382
|
+
// changing construction at all: the result carries the declared members
|
|
383
|
+
// either way. `../validate/proof.f.mjs` runs the acceptance half of this
|
|
384
|
+
// through all three readers.
|
|
385
|
+
closed: {
|
|
386
|
+
tuple: {
|
|
387
|
+
exact: () => {
|
|
388
|
+
const p = parse([number, string])
|
|
389
|
+
/** @typedef {Assert<Equal<typeof p, Parse<readonly [typeof number, typeof string]>>>} _ConstParameter */
|
|
390
|
+
assertStructurallySame(unwrap(p([1, 'a'])), [1, 'a'])
|
|
391
|
+
},
|
|
392
|
+
// The whole point of the default: `open` is what accepts this.
|
|
393
|
+
extraRejected: () => {
|
|
394
|
+
assertError(parse([number])([1, 2]))
|
|
395
|
+
assertStructurallySame(unwrap(parse(open([number]))([1, 2])), [1])
|
|
396
|
+
},
|
|
397
|
+
// A hole past the prefix is no member, so length is what catches it.
|
|
398
|
+
holePastThePrefixRejected: () => assertError(parse([number])([1, ,])),
|
|
399
|
+
// Nor is a key that is no position at all.
|
|
400
|
+
nonIndexKeyRejected: () =>
|
|
401
|
+
assertError(parse([number])(Object.assign([1], { foo: 2 }))),
|
|
402
|
+
// The rule for a missing member is unchanged: an absent position
|
|
403
|
+
// reads as `undefined`.
|
|
404
|
+
shortArray: () => {
|
|
405
|
+
assertError(parse([number])([]))
|
|
406
|
+
assertStructurallySame(unwrap(parse([number, option(string)])([1])), [1, undefined])
|
|
407
|
+
},
|
|
408
|
+
empty: () => {
|
|
409
|
+
assertStructurallySame(unwrap(parse([])([])), [])
|
|
410
|
+
assertError(parse([])([1]))
|
|
411
|
+
},
|
|
412
|
+
notAnArray: () => assertError(parse([number])({})),
|
|
413
|
+
},
|
|
414
|
+
struct: {
|
|
415
|
+
exact: () => assertStructurallySame(unwrap(parse({ a: number })({ a: 1 })), { a: 1 }),
|
|
416
|
+
extraRejected: () => {
|
|
417
|
+
assertError(parse({ a: number })({ a: 1, b: 2 }))
|
|
418
|
+
assertOk(parse(open({ a: number }))({ a: 1, b: 2 }))
|
|
419
|
+
},
|
|
420
|
+
// A key declared as `unknown` is a member the schema *has*, so a
|
|
421
|
+
// closed struct still admits it — the canonical form may not drop
|
|
422
|
+
// it the way an `open` struct's is dropped.
|
|
423
|
+
unknownMemberIsStillDeclared: () => {
|
|
424
|
+
assertOk(parse({ a: unknown })({ a: 1 }))
|
|
425
|
+
assertError(parse({ a: unknown })({ a: 1, b: 2 }))
|
|
426
|
+
},
|
|
427
|
+
empty: () => {
|
|
428
|
+
assertStructurallySame(unwrap(parse({})({})), {})
|
|
429
|
+
assertError(parse({})({ a: 1 }))
|
|
430
|
+
},
|
|
431
|
+
notAnObject: () => assertError(parse({ a: number })([])),
|
|
432
|
+
},
|
|
433
|
+
// With a `rest`, an undeclared member is legal when it belongs to it —
|
|
434
|
+
// and still not carried into what `parse` builds. `rest` says what an
|
|
435
|
+
// undeclared member must be, not that the reader should keep it.
|
|
436
|
+
rest: {
|
|
437
|
+
checkedAndDropped: () => {
|
|
438
|
+
assertStructurallySame(unwrap(parse(rest({ a: number }, string))({ a: 1, b: 'x' })), { a: 1 })
|
|
439
|
+
assertStructurallySame(unwrap(parse(rest([number], string))([1, 'x', 'y'])), [1])
|
|
440
|
+
},
|
|
441
|
+
rejected: () => {
|
|
442
|
+
assertErrorPath(['b'])(parse(rest({ a: number }, string))({ a: 1, b: 2 }))
|
|
443
|
+
assertErrorPath(['1'])(parse(rest([number], string))([1, 2]))
|
|
444
|
+
},
|
|
445
|
+
// An unconstrained rest is `open`.
|
|
446
|
+
unknownRestIsOpen: () => assertOk(parse(rest([number], unknown))([1, 'x'])),
|
|
447
|
+
// An empty one is the bare form: the length bound comes back.
|
|
448
|
+
emptyRestBoundsTheLength: () => {
|
|
449
|
+
assertError(parse(rest([number], or()))([1, ,]))
|
|
450
|
+
assertStructurallySame(unwrap(parse(rest([number], or()))([1])), [1])
|
|
451
|
+
},
|
|
452
|
+
},
|
|
453
|
+
// The declared members are read the same way whatever the rest is,
|
|
454
|
+
// error paths included.
|
|
455
|
+
path: () => {
|
|
456
|
+
assertErrorPath(['1'])(parse([number, number])([1, 'two']))
|
|
457
|
+
assertErrorPath(['a', '0'])(parse({ a: [number] })({ a: ['x'] }))
|
|
458
|
+
},
|
|
459
|
+
// A cycle through a container terminates. The schema is
|
|
460
|
+
// `Phantom`-wrapped for the usual reason (`Ts<>`'s structural walk
|
|
461
|
+
// would not terminate over a recursive container — see
|
|
462
|
+
// `../ts/types.ts`); it is the *value* half under test here.
|
|
463
|
+
recursive: () => {
|
|
464
|
+
const p = parse(node)
|
|
465
|
+
assertStructurallySame(unwrap(p([1])), [1, undefined])
|
|
466
|
+
assertStructurallySame(unwrap(p([1, [2]])), [1, [2, undefined]])
|
|
467
|
+
assertError(p([1, [2], 3]))
|
|
468
|
+
},
|
|
469
|
+
// A cycle through the `rest` itself: every key other than `a` holds
|
|
470
|
+
// another one of these.
|
|
471
|
+
recursiveRest: () => {
|
|
472
|
+
const p = parse(nest)
|
|
473
|
+
assertStructurallySame(unwrap(p({ a: 1, b: { a: 2 } })), { a: 1 })
|
|
474
|
+
assertError(p({ a: 1, b: { a: 'x' } }))
|
|
475
|
+
assertError(p({ a: 1, b: 2 }))
|
|
476
|
+
},
|
|
477
|
+
},
|
|
478
|
+
arrayOptional: () => {
|
|
479
|
+
const a = /** @type {const} */([number, option(string)])
|
|
480
|
+
const v = parse(a)
|
|
481
|
+
assertOk(v([5]))
|
|
482
|
+
assertError(v(["n"]))
|
|
483
|
+
assertOk(v([6, "3"]))
|
|
484
|
+
assertError(v([6, 9]))
|
|
485
|
+
}
|
|
362
486
|
}
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @import { StringMap } from '../object/types.ts'
|
|
3
|
+
* @import { Assert } from '../../asserts/types.ts'
|
|
4
|
+
* @import { Equal } from '../ts/types.ts'
|
|
5
|
+
* @import { Or, Rest, Type1, Unknown } from './types.ts'
|
|
3
6
|
*/
|
|
4
7
|
import type { StringMap } from '../object/types.ts';
|
|
5
8
|
export type _Tests = StringMap<readonly unknown[]>;
|
|
9
|
+
declare const constInference: () => void;
|
|
6
10
|
export declare const proof: {
|
|
11
|
+
constInference: typeof constInference;
|
|
7
12
|
typeof: {
|
|
8
13
|
[k: string]: (() => void)[];
|
|
9
14
|
};
|
|
10
15
|
};
|
|
16
|
+
export {};
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @import { StringMap } from '../object/types.ts'
|
|
3
|
+
* @import { Assert } from '../../asserts/types.ts'
|
|
4
|
+
* @import { Equal } from '../ts/types.ts'
|
|
5
|
+
* @import { Or, Rest, Type1, Unknown } from './types.ts'
|
|
3
6
|
*/
|
|
4
7
|
|
|
5
|
-
import { assertNotNullish } from '../../asserts/module.f.mjs'
|
|
8
|
+
import { assertNotNullish, assertStructurallySame } from '../../asserts/module.f.mjs'
|
|
9
|
+
import { array, number, open, option, or, record, rest, string, unknown } from './module.f.mjs'
|
|
6
10
|
|
|
7
11
|
/** @typedef {StringMap<readonly unknown[]>} _Tests */
|
|
8
12
|
|
|
@@ -17,7 +21,44 @@ const tests = {
|
|
|
17
21
|
function: [() => undefined]
|
|
18
22
|
}
|
|
19
23
|
|
|
24
|
+
// `or`, `option`, `array`, `record`, `rest` and `open` take `const` type
|
|
25
|
+
// parameters, so a literal written at the call site stays a literal: `or(42, string)`
|
|
26
|
+
// describes `42 | string`, not `number | string`. Without the modifier a caller
|
|
27
|
+
// has to pin every literal with an `@type {const}` cast, and the assertions
|
|
28
|
+
// below are what fail if one of the modifiers is dropped. Each is paired with
|
|
29
|
+
// the thunk's own output, so the schema a call *builds* is checked next to the
|
|
30
|
+
// type it is given.
|
|
31
|
+
const constInference = () => {
|
|
32
|
+
const orConst = or(42, string)
|
|
33
|
+
/** @typedef {Assert<Equal<typeof orConst, Or<readonly [42, typeof string]>>>} _OrConst */
|
|
34
|
+
assertStructurallySame(orConst(), ['or', 42, string])
|
|
35
|
+
|
|
36
|
+
const optionConst = option([42, string])
|
|
37
|
+
/** @typedef {Assert<Equal<typeof optionConst, Or<readonly [readonly [42, typeof string], undefined]>>>} _OptionConst */
|
|
38
|
+
assertStructurallySame(optionConst(), ['or', [42, string], undefined])
|
|
39
|
+
|
|
40
|
+
const arrayConst = array('hello')
|
|
41
|
+
/** @typedef {Assert<Equal<typeof arrayConst, Type1<'array', 'hello'>>>} _ArrayConst */
|
|
42
|
+
assertStructurallySame(arrayConst(), ['array', 'hello'])
|
|
43
|
+
|
|
44
|
+
const recordConst = record({ a: number })
|
|
45
|
+
/** @typedef {Assert<Equal<typeof recordConst, Type1<'record', { readonly a: typeof number }>>>} _RecordConst */
|
|
46
|
+
assertStructurallySame(recordConst(), ['record', { a: number }])
|
|
47
|
+
|
|
48
|
+
const restConst = rest({ a: 42 }, string)
|
|
49
|
+
/** @typedef {Assert<Equal<typeof restConst, Rest<{ readonly a: 42 }, typeof string>>>} _RestConst */
|
|
50
|
+
assertStructurallySame(restConst(), ['rest', { a: 42 }, string])
|
|
51
|
+
|
|
52
|
+
// `open` needs the modifier of its own — it is not `rest` partially
|
|
53
|
+
// applied, so dropping it there widens `[42, string]` to `Type[]` while
|
|
54
|
+
// every assertion above still passes.
|
|
55
|
+
const openConst = open([42, string])
|
|
56
|
+
/** @typedef {Assert<Equal<typeof openConst, Rest<readonly [42, typeof string], Unknown>>>} _OpenConst */
|
|
57
|
+
assertStructurallySame(openConst(), ['rest', [42, string], unknown])
|
|
58
|
+
}
|
|
59
|
+
|
|
20
60
|
export const proof = {
|
|
61
|
+
constInference,
|
|
21
62
|
typeof: Object.fromEntries(Object.entries(tests).map(([k, a]) => [k, assertNotNullish(a).map(v => () => {
|
|
22
63
|
if (typeof v !== k) { throw `typeof ${v} !== ${k}` }
|
|
23
64
|
})])),
|
|
@@ -64,9 +64,14 @@ export declare const dataToTs: (mut?: true) => (data: Data) => readonly [readonl
|
|
|
64
64
|
* definitions the expression references; a schema with no reference cycles
|
|
65
65
|
* needs none.
|
|
66
66
|
*
|
|
67
|
-
* **
|
|
68
|
-
* (TypeScript's built-in), whereas `Ts<>` maps it to
|
|
69
|
-
* `djs/module.f.ts`.
|
|
67
|
+
* **Two notes where this and `Ts<>` differ.** The `unknown` schema produces
|
|
68
|
+
* the string `'unknown'` (TypeScript's built-in), whereas `Ts<>` maps it to
|
|
69
|
+
* `DjsUnknown` from `djs/module.f.ts`. And this printer recognizes an empty
|
|
70
|
+
* rest **semantically** — the data form has already normalized one away — so
|
|
71
|
+
* `rest([42], [or()])` prints the exact `readonly[42]`, where `Ts<>` keeps a
|
|
72
|
+
* tail it cannot see through (`RestTs` in `./types.ts` says why, and in which
|
|
73
|
+
* direction). Both print the same thing for every rest a schema states
|
|
74
|
+
* directly.
|
|
70
75
|
*
|
|
71
76
|
* @example
|
|
72
77
|
* ```js
|
|
@@ -78,6 +83,7 @@ export declare const dataToTs: (mut?: true) => (data: Data) => readonly [readonl
|
|
|
78
83
|
* toTs(42) // '42'
|
|
79
84
|
* toTs('hello') // '"hello"'
|
|
80
85
|
* toTs([boolean, number]) // 'readonly[boolean,number]'
|
|
86
|
+
* toTs(open([boolean, number])) // 'readonly[boolean,number,...readonly(unknown)[]]'
|
|
81
87
|
* toTs({ x: string }) // '{readonly"x":string}'
|
|
82
88
|
*
|
|
83
89
|
* const list = () => ['array', list]
|
|
@@ -22,7 +22,7 @@ import { assertNotNullish } from '../../../asserts/module.f.mjs'
|
|
|
22
22
|
import { reservedWords, strictModeReservedWords } from '../../../js/keywords/module.f.mjs'
|
|
23
23
|
import { at, definedEntries } from '../../object/module.f.mjs'
|
|
24
24
|
import { primitive, union, printer as tsPrinter } from '../../ts/module.f.mjs'
|
|
25
|
-
import { cmp, toData, unitBit, unknown as top } from '../data/module.f.mjs'
|
|
25
|
+
import { cmp, never as bottom, toData, unitBit, unknown as top } from '../data/module.f.mjs'
|
|
26
26
|
|
|
27
27
|
const nullBit = unitBit(null)
|
|
28
28
|
const undefinedBit = unitBit(undefined)
|
|
@@ -145,28 +145,69 @@ const unitToTs = bits => [
|
|
|
145
145
|
/**
|
|
146
146
|
* A tuple prints its prefix, an array its element type, and a
|
|
147
147
|
* tuple-with-rest combines them with a rest element:
|
|
148
|
-
* `readonly[A,...readonly(R)[]]`.
|
|
148
|
+
* `readonly[A,...readonly(R|undefined)[]]`.
|
|
149
|
+
*
|
|
150
|
+
* A position the array may simply end before prints optional — the trailing
|
|
151
|
+
* run whose sets admit `undefined`, which is exactly what the array may stop
|
|
152
|
+
* at, arrays being contiguous. It mirrors the optional key `objectSetToTs`
|
|
153
|
+
* prints, and keeps the union rather than stripping `undefined` from it, as
|
|
154
|
+
* that one does.
|
|
155
|
+
*
|
|
156
|
+
* The **tail** admits `undefined` on top of what the `rest` states, because a
|
|
157
|
+
* hole past the prefix is no member: the readers check each present member
|
|
158
|
+
* against the `rest` and skip an absent one, so `rest([42], string)` accepts
|
|
159
|
+
* `[42, , ]` and index 1 reads `undefined`. `Ts<>` renders the same tail for
|
|
160
|
+
* the same reason (see `RestTs` in `./types.ts`). The open case pays nothing —
|
|
161
|
+
* `unknown` already admits `undefined` — and an empty rest never reaches here,
|
|
162
|
+
* the data form having normalized it away into the exact-length pattern.
|
|
163
|
+
*
|
|
164
|
+
* A pattern with **no prefix** is the uniform array, which `Ts<>` renders as
|
|
165
|
+
* `ArrayTs` — `readonly Ts<R>[]` — and this mirrors. A hole is no member there
|
|
166
|
+
* either, so that rendering has the same gap one element wider; it is
|
|
167
|
+
* `ArrayTs`'s to close, not this printer's, and closing it here alone would
|
|
168
|
+
* put the two renderers at odds on the commonest schema there is.
|
|
149
169
|
*
|
|
150
170
|
* @type {(ctx: _Ctx) => (p: ArraySet) => string}
|
|
151
171
|
*/
|
|
152
172
|
const arraySetToTs = ctx => p => {
|
|
153
|
-
const
|
|
173
|
+
const required = p.prefix.findLastIndex(n => !admitsUndefined(ctx)(n)) + 1
|
|
174
|
+
const items = p.prefix.map((n, i) => {
|
|
175
|
+
const ts = nodeToTs(ctx)(n)
|
|
176
|
+
return i < required ? ts : `(${ts})?`
|
|
177
|
+
})
|
|
154
178
|
const { rest } = p
|
|
155
179
|
if (rest === undefined) { return ctx.ts.tuple(items) }
|
|
156
|
-
const restTs =
|
|
157
|
-
|
|
180
|
+
const restTs = nodeToTs(ctx)(rest)
|
|
181
|
+
if (items.length === 0) { return ctx.ts.array(restTs) }
|
|
182
|
+
const tail = ctx.ts.array(admitsUndefined(ctx)(rest)
|
|
183
|
+
? restTs
|
|
184
|
+
: union(dedup([primitive(undefined), restTs])))
|
|
185
|
+
return ctx.ts.tuple([...items, `...${tail}`])
|
|
158
186
|
}
|
|
159
187
|
|
|
160
188
|
/**
|
|
161
|
-
*
|
|
162
|
-
*
|
|
189
|
+
* The node's own union, read through a reference (own-property only) if
|
|
190
|
+
* needed.
|
|
191
|
+
*
|
|
192
|
+
* @type {(ctx: _Ctx) => (n: Node) => UnionSet}
|
|
193
|
+
*/
|
|
194
|
+
const resolveNode = ctx => n =>
|
|
195
|
+
typeof n === 'string' ? assertNotNullish(at(n)(ctx.rules)) : n
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Whether the node's value set admits `undefined` — its unit bit.
|
|
163
199
|
*
|
|
164
200
|
* @type {(ctx: _Ctx) => (n: Node) => boolean}
|
|
165
201
|
*/
|
|
166
|
-
const admitsUndefined = ctx => n =>
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
202
|
+
const admitsUndefined = ctx => n =>
|
|
203
|
+
((resolveNode(ctx)(n).unit ?? 0) & undefinedBit) !== 0
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Whether the node's value set is empty.
|
|
207
|
+
*
|
|
208
|
+
* @type {(ctx: _Ctx) => (n: Node) => boolean}
|
|
209
|
+
*/
|
|
210
|
+
const isNever = ctx => n => cmp([{}, resolveNode(ctx)(n)])([{}, bottom]) === 0
|
|
170
211
|
|
|
171
212
|
/** @type {(list: readonly string[]) => readonly string[]} */
|
|
172
213
|
const dedup = list => list.filter((s, i) => list.indexOf(s) === i)
|
|
@@ -179,6 +220,12 @@ const dedup = list => list.filter((s, i) => list.indexOf(s) === i)
|
|
|
179
220
|
* declared keys too, so the index type widens to the union of the rest and
|
|
180
221
|
* the declared value types — the closest expressible supertype.
|
|
181
222
|
*
|
|
223
|
+
* An **empty** rest — what a bare, closed struct carries — prints as the
|
|
224
|
+
* fields alone. TypeScript object types are structurally open, so "and no
|
|
225
|
+
* other key" has no spelling there and the index signature would say the
|
|
226
|
+
* opposite of what is meant; the fields are the closest expressible
|
|
227
|
+
* supertype, exactly as `Ts<>` renders them.
|
|
228
|
+
*
|
|
182
229
|
* @type {(ctx: _Ctx) => (p: ObjectSet) => string}
|
|
183
230
|
*/
|
|
184
231
|
const objectSetToTs = ctx => p => {
|
|
@@ -188,7 +235,7 @@ const objectSetToTs = ctx => p => {
|
|
|
188
235
|
return admitsUndefined(ctx)(v) ? [k, ts, true] : [k, ts]
|
|
189
236
|
})
|
|
190
237
|
const { rest } = p
|
|
191
|
-
if (rest === undefined) { return ctx.ts.struct(fields) }
|
|
238
|
+
if (rest === undefined || isNever(ctx)(rest)) { return ctx.ts.struct(fields) }
|
|
192
239
|
const restTs = ctx.ts.record(union(dedup([...fields.map(([, v]) => v), nodeToTs(ctx)(rest)])))
|
|
193
240
|
return fields.length === 0 ? restTs : `${ctx.ts.struct(fields)}&${restTs}`
|
|
194
241
|
}
|
|
@@ -257,9 +304,14 @@ export const dataToTs = mut => ([rules, entry]) => {
|
|
|
257
304
|
* definitions the expression references; a schema with no reference cycles
|
|
258
305
|
* needs none.
|
|
259
306
|
*
|
|
260
|
-
* **
|
|
261
|
-
* (TypeScript's built-in), whereas `Ts<>` maps it to
|
|
262
|
-
* `djs/module.f.ts`.
|
|
307
|
+
* **Two notes where this and `Ts<>` differ.** The `unknown` schema produces
|
|
308
|
+
* the string `'unknown'` (TypeScript's built-in), whereas `Ts<>` maps it to
|
|
309
|
+
* `DjsUnknown` from `djs/module.f.ts`. And this printer recognizes an empty
|
|
310
|
+
* rest **semantically** — the data form has already normalized one away — so
|
|
311
|
+
* `rest([42], [or()])` prints the exact `readonly[42]`, where `Ts<>` keeps a
|
|
312
|
+
* tail it cannot see through (`RestTs` in `./types.ts` says why, and in which
|
|
313
|
+
* direction). Both print the same thing for every rest a schema states
|
|
314
|
+
* directly.
|
|
263
315
|
*
|
|
264
316
|
* @example
|
|
265
317
|
* ```js
|
|
@@ -271,6 +323,7 @@ export const dataToTs = mut => ([rules, entry]) => {
|
|
|
271
323
|
* toTs(42) // '42'
|
|
272
324
|
* toTs('hello') // '"hello"'
|
|
273
325
|
* toTs([boolean, number]) // 'readonly[boolean,number]'
|
|
326
|
+
* toTs(open([boolean, number])) // 'readonly[boolean,number,...readonly(unknown)[]]'
|
|
274
327
|
* toTs({ x: string }) // '{readonly"x":string}'
|
|
275
328
|
*
|
|
276
329
|
* const list = () => ['array', list]
|
|
@@ -1,8 +1,30 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @import { Type } from '../types.ts'
|
|
2
|
+
* @import { Or, Type } from '../types.ts'
|
|
3
3
|
* @import { Data } from '../data/types.ts'
|
|
4
|
+
* @import { Ts, TupleTs } from './types.ts'
|
|
5
|
+
* @import { Assert } from '../../../asserts/types.ts'
|
|
6
|
+
* @import { Equal } from '../../ts/types.ts'
|
|
4
7
|
*/
|
|
5
|
-
import {
|
|
8
|
+
import type { Or } from '../types.ts';
|
|
9
|
+
import type { Ts, TupleTs } from './types.ts';
|
|
10
|
+
import type { Assert } from '../../../asserts/types.ts';
|
|
11
|
+
import type { Equal } from '../../ts/types.ts';
|
|
12
|
+
import { boolean, number, string, bigint } from '../module.f.mjs';
|
|
13
|
+
export type _NonFixedLength = Assert<Equal<Ts<readonly (typeof number | typeof bigint)[]>, readonly (number | bigint)[]>>;
|
|
14
|
+
export type _OptionBoolean = Or<readonly [typeof boolean, undefined]>;
|
|
15
|
+
export type _OptionString = Or<readonly [typeof string, undefined]>;
|
|
16
|
+
export type _VariadicSchema = readonly [...(typeof number)[], _OptionString];
|
|
17
|
+
export type _VariadicPrefixRejectsMixedPrefix = Assert<readonly [1, 'x', 2] extends Ts<_VariadicSchema> ? false : true>;
|
|
18
|
+
export type _VariadicPrefixAdmitsItsOwnShape = Assert<readonly [1, 2, 'x'] extends Ts<_VariadicSchema> ? true : false>;
|
|
19
|
+
export type _RestTuple = Assert<Equal<Ts<readonly [typeof number, ...(typeof string)[]]>, readonly [number, ...string[]]>>;
|
|
20
|
+
export type _OptionalMember = Assert<Equal<Ts<readonly [typeof number, (typeof string)?]>, readonly [number, string?]>>;
|
|
21
|
+
export type _BranchA = readonly [typeof number, _OptionString];
|
|
22
|
+
export type _BranchB = readonly [typeof string, _OptionBoolean, _OptionNumber];
|
|
23
|
+
export type _OptionNumber = Or<readonly [typeof number, undefined]>;
|
|
24
|
+
export type _UnionKeepsBranchCorrelation = Assert<readonly [1, true] extends TupleTs<_BranchA | _BranchB> ? false : true>;
|
|
25
|
+
export type _UnionAdmitsItsOwnBranches = Assert<readonly [1, 'x'] extends TupleTs<_BranchA | _BranchB> ? true : false>;
|
|
26
|
+
export type _OptionalTail = Assert<Equal<Ts<readonly [typeof number, typeof bigint, _OptionBoolean, _OptionString]>, readonly [number, bigint, (boolean | undefined)?, (string | undefined)?]>>;
|
|
27
|
+
export type _InteriorStaysRequired = Assert<Equal<Ts<readonly [_OptionString, typeof number]>, readonly [string | undefined, number]>>;
|
|
6
28
|
export type _List = () => readonly ['array', _List];
|
|
7
29
|
export type _Tree = () => readonly ['or', typeof number, _Forest];
|
|
8
30
|
export type _Forest = () => readonly ['array', _Tree];
|
|
@@ -42,7 +64,10 @@ export declare const proof: {
|
|
|
42
64
|
bigint: () => void;
|
|
43
65
|
emptyTuple: () => void;
|
|
44
66
|
tuple: () => void;
|
|
67
|
+
optionalTuplePosition: () => void;
|
|
68
|
+
allOptionalTuple: () => void;
|
|
45
69
|
emptyStruct: () => void;
|
|
70
|
+
unknownProp: () => void;
|
|
46
71
|
struct: () => void;
|
|
47
72
|
nestedStruct: () => void;
|
|
48
73
|
quotedKey: () => void;
|
|
@@ -59,7 +84,21 @@ export declare const proof: {
|
|
|
59
84
|
thunks: () => void;
|
|
60
85
|
mixed: () => void;
|
|
61
86
|
};
|
|
87
|
+
open: {
|
|
88
|
+
emptyTuple: () => void;
|
|
89
|
+
unconstrainedTuple: () => void;
|
|
90
|
+
tuple: () => void;
|
|
91
|
+
emptyStruct: () => void;
|
|
92
|
+
struct: () => void;
|
|
93
|
+
unknownProp: () => void;
|
|
94
|
+
tupleRest: () => void;
|
|
95
|
+
structRest: () => void;
|
|
96
|
+
openIsAnUnconstrainedRest: () => void;
|
|
97
|
+
emptyRestIsTheBareForm: () => void;
|
|
98
|
+
mut: () => void;
|
|
99
|
+
};
|
|
62
100
|
never: () => void;
|
|
101
|
+
arrayOfNever: () => void;
|
|
63
102
|
option: () => void;
|
|
64
103
|
normalization: {
|
|
65
104
|
booleanFromConsts: () => void;
|
|
@@ -86,6 +125,7 @@ export declare const proof: {
|
|
|
86
125
|
};
|
|
87
126
|
data: {
|
|
88
127
|
tupleWithRest: () => void;
|
|
128
|
+
exactLengthTuple: () => void;
|
|
89
129
|
structWithRest: () => void;
|
|
90
130
|
optionalByReference: () => void;
|
|
91
131
|
wholeKinds: () => void;
|