functionalscript 0.12.10 → 0.13.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/ci/module.f.js +1 -1
- package/package.json +1 -1
- package/types/rtti/ts/module.f.d.ts +10 -4
- package/types/rtti/ts/module.f.js +29 -20
- package/types/rtti/ts/test.f.d.ts +7 -0
- package/types/rtti/ts/test.f.js +18 -3
- package/types/ts/module.f.d.ts +13 -4
- package/types/ts/module.f.js +10 -4
package/ci/module.f.js
CHANGED
|
@@ -69,7 +69,7 @@ const node = (version) => (extra) => basicNode(version)([
|
|
|
69
69
|
const findTgz = (v) => v === 'windows' ? '(Get-ChildItem *.tgz).FullName' : './*.tgz';
|
|
70
70
|
const playwrightVersion = '1.58.2';
|
|
71
71
|
const playwrightAndVersion = `playwright@${playwrightVersion}`;
|
|
72
|
-
const rustToolchain = '1.
|
|
72
|
+
const rustToolchain = '1.95.0';
|
|
73
73
|
const toSteps = (m) => {
|
|
74
74
|
const filter = (st) => m.flatMap((mt) => mt.type === st ? [mt.step] : []);
|
|
75
75
|
const aptGet = m.flatMap(v => v.type === 'apt-get' ? [v.package] : []).join(' ');
|
package/package.json
CHANGED
|
@@ -41,9 +41,10 @@ export type Ts<T extends Type> = T extends () => infer I ? (I extends readonly [
|
|
|
41
41
|
readonly [K in string]: Ts<E>;
|
|
42
42
|
} : I extends readonly ['or', ...infer A extends readonly Type[]] ? Ts<A[number]> : never) : ConstTs<T>;
|
|
43
43
|
/**
|
|
44
|
-
*
|
|
44
|
+
* Creates a printer that converts an RTTI schema `Type` to its TypeScript type expression as a string.
|
|
45
45
|
*
|
|
46
46
|
* Mirrors the compile-time `Ts<T>` mapped type at runtime.
|
|
47
|
+
* Pass `true` to emit mutable (non-`readonly`) types.
|
|
47
48
|
*
|
|
48
49
|
* **Note:** recursive schemas (e.g. `const list = () => ['array', list] as const`)
|
|
49
50
|
* will cause infinite recursion. Only acyclic schemas are supported.
|
|
@@ -53,14 +54,19 @@ export type Ts<T extends Type> = T extends () => infer I ? (I extends readonly [
|
|
|
53
54
|
*
|
|
54
55
|
* @example
|
|
55
56
|
* ```ts
|
|
57
|
+
* const toTs = printer()
|
|
56
58
|
* toTs(boolean) // 'boolean'
|
|
57
59
|
* toTs(array(number)) // 'readonly(number)[]'
|
|
58
|
-
* toTs(record(string)) // '{readonly[k
|
|
60
|
+
* toTs(record(string)) // '{readonly[k:string]:string}'
|
|
59
61
|
* toTs(or(string, number)) // 'string|number'
|
|
60
62
|
* toTs(42) // '42'
|
|
61
63
|
* toTs('hello') // '"hello"'
|
|
62
64
|
* toTs([boolean, number]) // 'readonly[boolean,number]'
|
|
63
|
-
* toTs({ x: string }) // '{readonly
|
|
65
|
+
* toTs({ x: string }) // '{readonly"x":string}'
|
|
66
|
+
*
|
|
67
|
+
* const toTsMut = printer(true)
|
|
68
|
+
* toTsMut(array(number)) // '(number)[]'
|
|
69
|
+
* toTsMut(record(string)) // '{[k:string]:string}'
|
|
64
70
|
* ```
|
|
65
71
|
*/
|
|
66
|
-
export declare const
|
|
72
|
+
export declare const printer: (mut?: true) => (rtti: Type) => string;
|
|
@@ -7,15 +7,12 @@
|
|
|
7
7
|
* The runtime `toTs` function mirrors `Ts<T>` at value level, returning a TypeScript
|
|
8
8
|
* type expression string for a given RTTI schema.
|
|
9
9
|
*/
|
|
10
|
-
import { primitive,
|
|
11
|
-
/** Serialises a `Const` schema to its TypeScript type expression. */
|
|
12
|
-
const constToTs = (rtti) => typeof rtti !== 'object' || rtti === null ? primitive(rtti) :
|
|
13
|
-
rtti instanceof Array ? tuple(rtti.map(toTs)) :
|
|
14
|
-
struct(Object.entries(rtti).map(([k, v]) => [k, toTs(v)]));
|
|
10
|
+
import { primitive, union, printer as tsPrinter } from "../../ts/module.f.js";
|
|
15
11
|
/**
|
|
16
|
-
*
|
|
12
|
+
* Creates a printer that converts an RTTI schema `Type` to its TypeScript type expression as a string.
|
|
17
13
|
*
|
|
18
14
|
* Mirrors the compile-time `Ts<T>` mapped type at runtime.
|
|
15
|
+
* Pass `true` to emit mutable (non-`readonly`) types.
|
|
19
16
|
*
|
|
20
17
|
* **Note:** recursive schemas (e.g. `const list = () => ['array', list] as const`)
|
|
21
18
|
* will cause infinite recursion. Only acyclic schemas are supported.
|
|
@@ -25,26 +22,38 @@ const constToTs = (rtti) => typeof rtti !== 'object' || rtti === null ? primitiv
|
|
|
25
22
|
*
|
|
26
23
|
* @example
|
|
27
24
|
* ```ts
|
|
25
|
+
* const toTs = printer()
|
|
28
26
|
* toTs(boolean) // 'boolean'
|
|
29
27
|
* toTs(array(number)) // 'readonly(number)[]'
|
|
30
|
-
* toTs(record(string)) // '{readonly[k
|
|
28
|
+
* toTs(record(string)) // '{readonly[k:string]:string}'
|
|
31
29
|
* toTs(or(string, number)) // 'string|number'
|
|
32
30
|
* toTs(42) // '42'
|
|
33
31
|
* toTs('hello') // '"hello"'
|
|
34
32
|
* toTs([boolean, number]) // 'readonly[boolean,number]'
|
|
35
|
-
* toTs({ x: string }) // '{readonly
|
|
33
|
+
* toTs({ x: string }) // '{readonly"x":string}'
|
|
34
|
+
*
|
|
35
|
+
* const toTsMut = printer(true)
|
|
36
|
+
* toTsMut(array(number)) // '(number)[]'
|
|
37
|
+
* toTsMut(record(string)) // '{[k:string]:string}'
|
|
36
38
|
* ```
|
|
37
39
|
*/
|
|
38
|
-
export const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
40
|
+
export const printer = (mut) => {
|
|
41
|
+
const { tuple, struct, array, record } = tsPrinter(mut);
|
|
42
|
+
const constToTs = (rtti) => typeof rtti !== 'object' || rtti === null ? primitive(rtti) :
|
|
43
|
+
rtti instanceof Array ? tuple(rtti.map(toTs)) :
|
|
44
|
+
struct(Object.entries(rtti).map(([k, v]) => [k, toTs(v)]));
|
|
45
|
+
const toTs = (rtti) => {
|
|
46
|
+
if (typeof rtti !== 'function') {
|
|
47
|
+
return constToTs(rtti);
|
|
48
|
+
}
|
|
49
|
+
const [tag, ...rest] = rtti();
|
|
50
|
+
switch (tag) {
|
|
51
|
+
case 'const': return constToTs(rest[0]);
|
|
52
|
+
case 'array': return array(toTs(rest[0]));
|
|
53
|
+
case 'record': return record(toTs(rest[0]));
|
|
54
|
+
case 'or': return union(rest.map(toTs));
|
|
55
|
+
default: return tag; // tag0: 'boolean' | 'number' | 'string' | 'bigint' | 'unknown'
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
return toTs;
|
|
50
59
|
};
|
package/types/rtti/ts/test.f.js
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { printer } from "./module.f.js";
|
|
2
2
|
import { boolean, number, string, bigint, unknown, array, record, or, option, never } from "../module.f.js";
|
|
3
|
+
const toTs = printer();
|
|
4
|
+
const toTsMut = printer(true);
|
|
5
|
+
const eqMut = (rtti, expected) => {
|
|
6
|
+
const result = toTsMut(rtti);
|
|
7
|
+
if (result !== expected) {
|
|
8
|
+
throw `expected ${JSON.stringify(expected)}, got ${JSON.stringify(result)}`;
|
|
9
|
+
}
|
|
10
|
+
};
|
|
3
11
|
const eq = (rtti, expected) => {
|
|
4
12
|
const result = toTs(rtti);
|
|
5
13
|
if (result !== expected) {
|
|
@@ -21,8 +29,8 @@ export default {
|
|
|
21
29
|
union: () => eq(array(or(number, string)), 'readonly(number|string)[]'),
|
|
22
30
|
},
|
|
23
31
|
record: {
|
|
24
|
-
primitive: () => eq(record(string), '{readonly[k
|
|
25
|
-
nested: () => eq(record(record(number)), '{readonly[k
|
|
32
|
+
primitive: () => eq(record(string), '{readonly[k:string]:string}'),
|
|
33
|
+
nested: () => eq(record(record(number)), '{readonly[k:string]:{readonly[k:string]:number}}'),
|
|
26
34
|
},
|
|
27
35
|
},
|
|
28
36
|
const: {
|
|
@@ -57,4 +65,11 @@ export default {
|
|
|
57
65
|
},
|
|
58
66
|
never: () => eq(never, 'never'),
|
|
59
67
|
option: () => eq(option(number), 'number|undefined'),
|
|
68
|
+
mut: {
|
|
69
|
+
array: () => eqMut(array(number), '(number)[]'),
|
|
70
|
+
nestedArray: () => eqMut(array(array(boolean)), '((boolean)[])[]'),
|
|
71
|
+
record: () => eqMut(record(string), '{[k:string]:string}'),
|
|
72
|
+
tuple: () => eqMut([12, true], '[12,true]'),
|
|
73
|
+
struct: () => eqMut({ a: number, b: string }, '{"a":number,"b":string}'),
|
|
74
|
+
},
|
|
60
75
|
};
|
package/types/ts/module.f.d.ts
CHANGED
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
export type Equal<A, B> = (<T>() => T extends A ? 1 : 2) extends (<T>() => T extends B ? 1 : 2) ? true : false;
|
|
2
2
|
export type Assert<T extends true> = T;
|
|
3
|
-
|
|
4
|
-
export
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
/** Functions for emitting TypeScript type expression strings. */
|
|
4
|
+
export type Printer = {
|
|
5
|
+
/** Emits a tuple type: `readonly[A, B]` or `[A, B]` when mutable. */
|
|
6
|
+
readonly tuple: (types: readonly string[]) => string;
|
|
7
|
+
/** Emits an object type with named fields: `{readonly"k":T}` or `{"k":T}` when mutable. */
|
|
8
|
+
readonly struct: (fields: readonly (readonly [string, string])[]) => string;
|
|
9
|
+
/** Emits an array type: `readonly(T)[]` or `(T)[]` when mutable. */
|
|
10
|
+
readonly array: (type: string) => string;
|
|
11
|
+
/** Emits an index-signature record type: `{readonly[k:string]:T}` or `{[k:string]:T}` when mutable. */
|
|
12
|
+
readonly record: (type: string) => string;
|
|
13
|
+
};
|
|
14
|
+
/** Creates a `Printer`. Pass `true` to emit mutable (non-`readonly`) types. */
|
|
15
|
+
export declare const printer: (mut?: true) => Printer;
|
|
7
16
|
export declare const primitive: (c: bigint | string | undefined | boolean | number | null) => string;
|
|
8
17
|
export declare const union: (types: readonly string[]) => string;
|
package/types/ts/module.f.js
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
const complex = (open, close) => (i) => `${open}${i.join(',')}${close}`;
|
|
2
|
-
export const tuple = complex('readonly[', ']');
|
|
3
2
|
const structX = complex('{', '}');
|
|
4
|
-
|
|
5
|
-
export const
|
|
6
|
-
|
|
3
|
+
/** Creates a `Printer`. Pass `true` to emit mutable (non-`readonly`) types. */
|
|
4
|
+
export const printer = (mut) => {
|
|
5
|
+
const ro = mut ? '' : 'readonly';
|
|
6
|
+
return {
|
|
7
|
+
tuple: (mut ? complex('[', ']') : complex('readonly[', ']')),
|
|
8
|
+
struct: (fields) => structX(fields.map(([k, v]) => `${ro}${JSON.stringify(k)}:${v}`)),
|
|
9
|
+
array: (type) => `${ro}(${type})[]`,
|
|
10
|
+
record: (type) => structX([`${ro}[k:string]:${type}`]),
|
|
11
|
+
};
|
|
12
|
+
};
|
|
7
13
|
export const primitive = (c) => {
|
|
8
14
|
if (c === null) {
|
|
9
15
|
return 'null';
|