@fulcro/types 0.1.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 (51) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +66 -0
  3. package/dist/bigInteger/index.d.ts +27 -0
  4. package/dist/bigInteger/index.js +76 -0
  5. package/dist/brand/index.d.ts +25 -0
  6. package/dist/brand/index.js +2 -0
  7. package/dist/decimal/arithmetic.d.ts +99 -0
  8. package/dist/decimal/arithmetic.js +388 -0
  9. package/dist/decimal/format.d.ts +55 -0
  10. package/dist/decimal/format.js +195 -0
  11. package/dist/decimal/index.d.ts +296 -0
  12. package/dist/decimal/index.js +407 -0
  13. package/dist/decimal/parse.d.ts +15 -0
  14. package/dist/decimal/parse.js +80 -0
  15. package/dist/decimal/parts.d.ts +83 -0
  16. package/dist/decimal/parts.js +103 -0
  17. package/dist/decimal/round.d.ts +32 -0
  18. package/dist/decimal/round.js +132 -0
  19. package/dist/doublePrecisionFloat/index.d.ts +19 -0
  20. package/dist/doublePrecisionFloat/index.js +12 -0
  21. package/dist/float/index.d.ts +25 -0
  22. package/dist/float/index.js +61 -0
  23. package/dist/halfPrecisionFloat/index.d.ts +20 -0
  24. package/dist/halfPrecisionFloat/index.js +63 -0
  25. package/dist/index.d.ts +22 -0
  26. package/dist/index.js +29 -0
  27. package/dist/integer/index.d.ts +163 -0
  28. package/dist/integer/index.js +402 -0
  29. package/dist/languageService/index.d.ts +21 -0
  30. package/dist/languageService/index.js +23 -0
  31. package/dist/layout/index.d.ts +33 -0
  32. package/dist/layout/index.js +2 -0
  33. package/dist/numericType/index.d.ts +174 -0
  34. package/dist/numericType/index.js +2 -0
  35. package/dist/roundingMode/index.d.ts +30 -0
  36. package/dist/roundingMode/index.js +29 -0
  37. package/dist/signedInteger/index.d.ts +40 -0
  38. package/dist/signedInteger/index.js +34 -0
  39. package/dist/singlePrecisionFloat/index.d.ts +20 -0
  40. package/dist/singlePrecisionFloat/index.js +15 -0
  41. package/dist/transformer/classify/index.d.ts +39 -0
  42. package/dist/transformer/classify/index.js +84 -0
  43. package/dist/transformer/index.d.ts +27 -0
  44. package/dist/transformer/index.js +30 -0
  45. package/dist/transformer/rewriter/index.d.ts +3 -0
  46. package/dist/transformer/rewriter/index.js +374 -0
  47. package/dist/unplugin/index.d.mts +15 -0
  48. package/dist/unplugin/index.mjs +31 -0
  49. package/dist/unsignedInteger/index.d.ts +36 -0
  50. package/dist/unsignedInteger/index.js +34 -0
  51. package/package.json +71 -0
@@ -0,0 +1,174 @@
1
+ /**
2
+ * The runtime side of a numeric type: how a value becomes one, how one is
3
+ * recognised, and the arithmetic that keeps it one.
4
+ *
5
+ * A type is erased on the way to JavaScript, so `SignedInteger<32>` alone cannot
6
+ * check anything. Each numeric type therefore comes with a descriptor
7
+ * implementing this contract, and the descriptor carries the same name as the
8
+ * type:
9
+ *
10
+ * ```ts
11
+ * const Int32 = SignedInteger(32);
12
+ * const total: SignedInteger<32> = Int32.add(Int32.from(1), Int32.from(2));
13
+ * ```
14
+ *
15
+ * The arithmetic is here, rather than left to the operators, because the
16
+ * operators cannot keep the type's promise: `a + b` on two 32-bit integers is a
17
+ * `number` that may no longer fit in 32 bits, and on two single precision
18
+ * floats it is a double precision result nobody rounded. Every operation below
19
+ * returns a value of the type or throws.
20
+ *
21
+ * @template T Type of the values this descriptor produces.
22
+ * @template TSource What `from` accepts.
23
+ */
24
+ export interface NumericType<T, TSource> {
25
+ /** Name of the type, as it reads in an error message. */
26
+ readonly name: string;
27
+ /**
28
+ * Converts a value into this type.
29
+ *
30
+ * @param value Value to convert.
31
+ * @returns The value, as this type.
32
+ * @throws {RangeError} When the value cannot be represented, for the types
33
+ * that refuse rather than round.
34
+ * @throws {TypeError} When the value is not of an accepted kind.
35
+ */
36
+ from(value: TSource): T;
37
+ /**
38
+ * Tells whether a value already is of this type.
39
+ *
40
+ * @param value Value to inspect.
41
+ * @returns `true` when `from` would return the value unchanged.
42
+ */
43
+ is(value: unknown): value is T;
44
+ /**
45
+ * Adds two values.
46
+ *
47
+ * @param left First operand.
48
+ * @param right Second operand.
49
+ * @returns The sum, as this type.
50
+ */
51
+ add(left: T, right: T): T;
52
+ /**
53
+ * Subtracts one value from another.
54
+ *
55
+ * @param left Value subtracted from.
56
+ * @param right Value subtracted.
57
+ * @returns The difference, as this type.
58
+ */
59
+ subtract(left: T, right: T): T;
60
+ /**
61
+ * Multiplies two values.
62
+ *
63
+ * @param left First operand.
64
+ * @param right Second operand.
65
+ * @returns The product, as this type.
66
+ */
67
+ multiply(left: T, right: T): T;
68
+ /**
69
+ * Divides one value by another.
70
+ *
71
+ * @param left Dividend.
72
+ * @param right Divisor.
73
+ * @returns The quotient, as this type.
74
+ */
75
+ divide(left: T, right: T): T;
76
+ /**
77
+ * The remainder of a division, carrying the sign of the dividend as `%`
78
+ * does.
79
+ *
80
+ * @param left Dividend.
81
+ * @param right Divisor.
82
+ * @returns The remainder, as this type.
83
+ */
84
+ remainder(left: T, right: T): T;
85
+ /**
86
+ * Raises a value to a power, as `**` does.
87
+ *
88
+ * @param base Value raised.
89
+ * @param exponent Power it is raised to, of the same type.
90
+ * @returns The power, as this type.
91
+ * @throws {RangeError} For an integer type, on a negative exponent or a
92
+ * result outside the range.
93
+ */
94
+ power(base: T, exponent: T): T;
95
+ /**
96
+ * The value with its sign flipped, as unary `-` does.
97
+ *
98
+ * @param value Value negated.
99
+ * @returns The negation, as this type.
100
+ * @throws {RangeError} For an integer type whose range cannot hold it: the
101
+ * minimum of a signed type, and anything but zero of an unsigned one.
102
+ */
103
+ negate(value: T): T;
104
+ /**
105
+ * The value plus one, as `++` computes it.
106
+ *
107
+ * @param value Value incremented.
108
+ * @returns The next value, as this type.
109
+ */
110
+ increment(value: T): T;
111
+ /**
112
+ * The value minus one, as `--` computes it.
113
+ *
114
+ * @param value Value decremented.
115
+ * @returns The previous value, as this type.
116
+ */
117
+ decrement(value: T): T;
118
+ /**
119
+ * Tells whether two values are equal, as `===` does: `NaN` equals nothing,
120
+ * and `0` equals `-0`.
121
+ *
122
+ * @param left First operand.
123
+ * @param right Second operand.
124
+ * @returns `true` when they are equal.
125
+ */
126
+ equals(left: T, right: T): boolean;
127
+ /**
128
+ * @param left First operand.
129
+ * @param right Second operand.
130
+ * @returns `true` when `left` is smaller, as `<` answers.
131
+ */
132
+ lessThan(left: T, right: T): boolean;
133
+ /**
134
+ * @param left First operand.
135
+ * @param right Second operand.
136
+ * @returns `true` when `left` is smaller or equal, as `<=` answers.
137
+ */
138
+ lessThanOrEqual(left: T, right: T): boolean;
139
+ /**
140
+ * @param left First operand.
141
+ * @param right Second operand.
142
+ * @returns `true` when `left` is larger, as `>` answers.
143
+ */
144
+ greaterThan(left: T, right: T): boolean;
145
+ /**
146
+ * @param left First operand.
147
+ * @param right Second operand.
148
+ * @returns `true` when `left` is larger or equal, as `>=` answers.
149
+ */
150
+ greaterThanOrEqual(left: T, right: T): boolean;
151
+ }
152
+ /**
153
+ * A numeric type with a largest and a smallest value: every type here except
154
+ * `BigInteger`, whose values are as large as memory allows.
155
+ *
156
+ * `minimum` is the most negative finite value, not the smallest positive one —
157
+ * the meaning `Number.MIN_VALUE` gives the name, and the one that makes a
158
+ * range check with it wrong. For an unsigned integer it is zero.
159
+ *
160
+ * ```ts
161
+ * HalfPrecisionFloat.maximum; // 65504
162
+ * HalfPrecisionFloat.minimum; // -65504
163
+ * UnsignedInteger(8).minimum; // 0
164
+ * ```
165
+ *
166
+ * @template T Type of the values this descriptor produces.
167
+ * @template TSource What `from` accepts.
168
+ */
169
+ export interface BoundedNumericType<T, TSource> extends NumericType<T, TSource> {
170
+ /** Smallest finite value of the type. */
171
+ readonly minimum: T;
172
+ /** Largest finite value of the type. */
173
+ readonly maximum: T;
174
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,30 @@
1
+ /**
2
+ * How a value that falls between two representable ones is resolved.
3
+ *
4
+ * The five rounding directions IEEE 754 defines, spelled out:
5
+ *
6
+ * | Mode | Resolves to | IEEE 754 |
7
+ * | -------------------- | ----------------------------------------------- | ------------------------ |
8
+ * | `'ceiling'` | the neighbour towards +∞ | roundTowardPositive |
9
+ * | `'floor'` | the neighbour towards −∞ | roundTowardNegative |
10
+ * | `'truncate'` | the neighbour towards zero | roundTowardZero |
11
+ * | `'halfEven'` | the nearest, and on a tie the even neighbour | roundTiesToEven |
12
+ * | `'halfAwayFromZero'` | the nearest, and on a tie the one further out | roundTiesToAway |
13
+ *
14
+ * `'halfEven'` is the default wherever a mode is optional. It is the IEEE
15
+ * default and the one that does not drift: rounding many ties the same way
16
+ * biases a sum, and alternating them by parity does not.
17
+ */
18
+ export type RoundingMode = 'ceiling' | 'floor' | 'truncate' | 'halfEven' | 'halfAwayFromZero';
19
+ /**
20
+ * Refuses a mode that is not one of {@link RoundingMode}.
21
+ *
22
+ * A caller passing `'halfUp'` from untyped code would otherwise be rounded by
23
+ * whichever branch happened to be the default, silently.
24
+ *
25
+ * @param operation Operation being performed, for the message.
26
+ * @param mode Mode it was handed.
27
+ * @returns The mode, typed.
28
+ * @throws {RangeError} When the mode is not recognised.
29
+ */
30
+ export declare const requireRoundingMode: (operation: string, mode: unknown) => RoundingMode;
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.requireRoundingMode = void 0;
4
+ /** Every mode, for validating one that arrived from outside the type system. */
5
+ const ROUNDING_MODES = new Set([
6
+ 'ceiling',
7
+ 'floor',
8
+ 'truncate',
9
+ 'halfEven',
10
+ 'halfAwayFromZero',
11
+ ]);
12
+ /**
13
+ * Refuses a mode that is not one of {@link RoundingMode}.
14
+ *
15
+ * A caller passing `'halfUp'` from untyped code would otherwise be rounded by
16
+ * whichever branch happened to be the default, silently.
17
+ *
18
+ * @param operation Operation being performed, for the message.
19
+ * @param mode Mode it was handed.
20
+ * @returns The mode, typed.
21
+ * @throws {RangeError} When the mode is not recognised.
22
+ */
23
+ const requireRoundingMode = (operation, mode) => {
24
+ if (typeof mode === 'string' && ROUNDING_MODES.has(mode)) {
25
+ return mode;
26
+ }
27
+ throw new RangeError(`${operation}: expected a rounding mode of ${[...ROUNDING_MODES].join(', ')}, received ${JSON.stringify(mode) ?? String(mode)}.`);
28
+ };
29
+ exports.requireRoundingMode = requireRoundingMode;
@@ -0,0 +1,40 @@
1
+ import type { Branded } from '../brand/index.js';
2
+ import { type ByteSize, type IntegerRepresentation, type IntegerType, type IntegerWidth } from '../integer/index.js';
3
+ import type { Layout } from '../layout/index.js';
4
+ /**
5
+ * A two's complement integer of `N` bits: from -2^(N-1) to 2^(N-1) - 1.
6
+ *
7
+ * ```ts
8
+ * const index: SignedInteger<32> = SignedInteger(32).from(42);
9
+ * ```
10
+ *
11
+ * Carried by a `number` up to 32 bits and by a `bigint` from 64, so the type of
12
+ * the value already says which operators it takes. Widths are a parameter, not
13
+ * a list of names: there is no `SignedInteger32`, and no `i32`.
14
+ *
15
+ * A `SignedInteger<8>` is not a `SignedInteger<32>`, even though every value of
16
+ * one fits in the other. Widening goes through `from`, where it is visible.
17
+ *
18
+ * @template N Width, in bits.
19
+ */
20
+ export type SignedInteger<N extends IntegerWidth> = Branded<IntegerRepresentation<N>, `SignedInteger${N}`> & Layout<ByteSize<N>, ByteSize<N>>;
21
+ /**
22
+ * The descriptor of a signed integer width: conversion, recognition and checked
23
+ * arithmetic.
24
+ *
25
+ * ```ts
26
+ * const Int32 = SignedInteger(32);
27
+ *
28
+ * Int32.from(2 ** 31); // RangeError: outside [-2147483648, 2147483647]
29
+ * Int32.wrap(2 ** 31); // -2147483648
30
+ * Int32.add(Int32.maximum, Int32.from(1)); // RangeError
31
+ * ```
32
+ *
33
+ * Calling it twice with the same width returns the same object.
34
+ *
35
+ * @template N Width, in bits.
36
+ * @param width Width, in bits.
37
+ * @returns The descriptor of that width.
38
+ * @throws {RangeError} When the width is not 8, 16, 32, 64 or 128.
39
+ */
40
+ export declare const SignedInteger: <N extends IntegerWidth>(width: N) => IntegerType<SignedInteger<N>>;
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SignedInteger = void 0;
4
+ const integer_1 = require("../integer/index.js");
5
+ /** Descriptors already built, so a width is described by one object. */
6
+ const descriptors = new Map();
7
+ /**
8
+ * The descriptor of a signed integer width: conversion, recognition and checked
9
+ * arithmetic.
10
+ *
11
+ * ```ts
12
+ * const Int32 = SignedInteger(32);
13
+ *
14
+ * Int32.from(2 ** 31); // RangeError: outside [-2147483648, 2147483647]
15
+ * Int32.wrap(2 ** 31); // -2147483648
16
+ * Int32.add(Int32.maximum, Int32.from(1)); // RangeError
17
+ * ```
18
+ *
19
+ * Calling it twice with the same width returns the same object.
20
+ *
21
+ * @template N Width, in bits.
22
+ * @param width Width, in bits.
23
+ * @returns The descriptor of that width.
24
+ * @throws {RangeError} When the width is not 8, 16, 32, 64 or 128.
25
+ */
26
+ const SignedInteger = (width) => {
27
+ let descriptor = descriptors.get(width);
28
+ if (descriptor === undefined) {
29
+ descriptor = (0, integer_1.createIntegerType)(true, width, `SignedInteger<${width}>`);
30
+ descriptors.set(width, descriptor);
31
+ }
32
+ return descriptor;
33
+ };
34
+ exports.SignedInteger = SignedInteger;
@@ -0,0 +1,20 @@
1
+ import type { Branded } from '../brand/index.js';
2
+ import type { Layout } from '../layout/index.js';
3
+ import type { BoundedNumericType } from '../numericType/index.js';
4
+ /**
5
+ * An IEEE 754 binary32 value: 24 bits of precision, 8 of exponent.
6
+ *
7
+ * Carried by a `number` holding a value the format can represent exactly, so it
8
+ * reads, compares and prints like any other number. Converting rounds to the
9
+ * nearest such value, ties to even, as `Math.fround` does.
10
+ */
11
+ export type SinglePrecisionFloat = Branded<number, 'SinglePrecisionFloat'> & Layout<4, 4>;
12
+ /**
13
+ * The descriptor of {@link SinglePrecisionFloat}.
14
+ *
15
+ * ```ts
16
+ * SinglePrecisionFloat.from(0.1); // 0.10000000149011612
17
+ * SinglePrecisionFloat.from(1e39); // Infinity
18
+ * ```
19
+ */
20
+ export declare const SinglePrecisionFloat: BoundedNumericType<SinglePrecisionFloat, number>;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SinglePrecisionFloat = void 0;
4
+ const float_1 = require("../float/index.js");
5
+ /**
6
+ * The descriptor of {@link SinglePrecisionFloat}.
7
+ *
8
+ * ```ts
9
+ * SinglePrecisionFloat.from(0.1); // 0.10000000149011612
10
+ * SinglePrecisionFloat.from(1e39); // Infinity
11
+ * ```
12
+ */
13
+ exports.SinglePrecisionFloat = (0, float_1.createFloatType)('SinglePrecisionFloat',
14
+ // (2 - 2^-23) × 2^127
15
+ 3.4028234663852886e38, Math.fround);
@@ -0,0 +1,39 @@
1
+ import typescript from 'typescript';
2
+ /**
3
+ * Which of this package's numeric types a checker type is, if any.
4
+ *
5
+ * The rewrite of the operators must claim only this package's types. A
6
+ * consumer's own `number` and `bigint` arithmetic is none of its business, and
7
+ * a brand that merely looks like ours — a property with the same name in some
8
+ * other library — is not ours either. So a type is recognised by where its
9
+ * brand was **declared**: the `brand` module of this package, as source in this
10
+ * repository and as `dist` in a consumer's `node_modules`.
11
+ */
12
+ /** How the operators of one numeric type are written out. */
13
+ export type NumericKind = {
14
+ /** Called through a descriptor: `SignedInteger(32).add(a, b)`. */
15
+ readonly family: 'descriptor';
16
+ /** The descriptor, as an expression under the namespace import. */
17
+ readonly descriptor: string;
18
+ /** Whether the bit operators apply. */
19
+ readonly integer: boolean;
20
+ /** Name of the brand, which tells two kinds apart. */
21
+ readonly name: string;
22
+ } | {
23
+ /** Called as methods of the value: `a.add(b)`. */
24
+ readonly family: 'decimal';
25
+ readonly name: 'Decimal';
26
+ };
27
+ /**
28
+ * Classifies a type.
29
+ *
30
+ * A union is never one of ours, even a union of our types: `SignedInteger<8> |
31
+ * SignedInteger<16>` has no one descriptor to call, and `Decimal | undefined`
32
+ * has to be narrowed first, which the checker already insists on.
33
+ *
34
+ * @param type Type to classify.
35
+ * @param checker Checker of the program.
36
+ * @param location Node the type was read at.
37
+ * @returns The kind, or `null` when the type is not one of this package's.
38
+ */
39
+ export declare const classify: (type: typescript.Type, checker: typescript.TypeChecker, location: typescript.Node) => NumericKind | null;
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.classify = void 0;
4
+ /** The module declaring the brand every primitive-backed type carries. */
5
+ const BRAND_MODULE = /\/types\/(?:dist|src)\/brand\/index\.(?:d\.)?ts$/;
6
+ /** The module declaring `Decimal`. */
7
+ const DECIMAL_MODULE = /\/types\/(?:dist|src)\/decimal\/index\.(?:d\.)?ts$/;
8
+ /** A brand of a fixed-width integer, and its parts. */
9
+ const INTEGER_BRAND = /^(Signed|Unsigned)Integer(8|16|32|64|128)$/;
10
+ /** Brands whose descriptor is a value of the same name. */
11
+ const NAMED_BRANDS = new Set([
12
+ 'HalfPrecisionFloat',
13
+ 'SinglePrecisionFloat',
14
+ 'DoublePrecisionFloat',
15
+ 'BigInteger',
16
+ ]);
17
+ /**
18
+ * Tells whether a declaration was made in a module of this package.
19
+ *
20
+ * @param declaration Declaration of a symbol.
21
+ * @param module Pattern of the module.
22
+ * @returns `true` when it was.
23
+ */
24
+ const declaredIn = (declaration, module) => module.test(declaration.getSourceFile().fileName.replace(/\\/g, '/'));
25
+ /**
26
+ * The kind a brand stands for.
27
+ *
28
+ * @param brand Value of the brand property.
29
+ * @returns The kind, or `null` for a brand this rewrite does not know.
30
+ */
31
+ const kindOfBrand = (brand) => {
32
+ const integer = INTEGER_BRAND.exec(brand);
33
+ if (integer !== null) {
34
+ return {
35
+ family: 'descriptor',
36
+ descriptor: `${integer[1]}Integer(${integer[2]})`,
37
+ integer: true,
38
+ name: brand,
39
+ };
40
+ }
41
+ if (NAMED_BRANDS.has(brand)) {
42
+ return {
43
+ family: 'descriptor',
44
+ descriptor: brand,
45
+ integer: false,
46
+ name: brand,
47
+ };
48
+ }
49
+ return null;
50
+ };
51
+ /**
52
+ * Classifies a type.
53
+ *
54
+ * A union is never one of ours, even a union of our types: `SignedInteger<8> |
55
+ * SignedInteger<16>` has no one descriptor to call, and `Decimal | undefined`
56
+ * has to be narrowed first, which the checker already insists on.
57
+ *
58
+ * @param type Type to classify.
59
+ * @param checker Checker of the program.
60
+ * @param location Node the type was read at.
61
+ * @returns The kind, or `null` when the type is not one of this package's.
62
+ */
63
+ const classify = (type, checker, location) => {
64
+ if (type.isUnion())
65
+ return null;
66
+ const symbol = type.getSymbol();
67
+ if (symbol?.getName() === 'Decimal' &&
68
+ (symbol.declarations ?? []).some((declaration) => declaredIn(declaration, DECIMAL_MODULE))) {
69
+ return { family: 'decimal', name: 'Decimal' };
70
+ }
71
+ for (const property of checker.getPropertiesOfType(type)) {
72
+ // The brand is keyed by a unique symbol, which the checker names
73
+ // `__@brand@<id>`; the declaration settles whose it is.
74
+ if (!String(property.escapedName).startsWith('__@'))
75
+ continue;
76
+ const ours = (property.declarations ?? []).some((declaration) => declaredIn(declaration, BRAND_MODULE));
77
+ if (!ours)
78
+ continue;
79
+ const brand = checker.getTypeOfSymbolAtLocation(property, location);
80
+ return brand.isStringLiteral() ? kindOfBrand(brand.value) : null;
81
+ }
82
+ return null;
83
+ };
84
+ exports.classify = classify;
@@ -0,0 +1,27 @@
1
+ import { type ProgramTransformer } from '@fulcro/transform-core';
2
+ /**
3
+ * The `tsc` plugin giving the operators their meaning on this package's
4
+ * numeric types.
5
+ *
6
+ * A program transformer, not an ordinary one, and the tsconfig entry has to say
7
+ * so: the rewrite must happen before the program is type checked, or
8
+ * `decimal * decimal` has been reported as an error before anything could
9
+ * rewrite it. Wire it through `ts-patch`:
10
+ *
11
+ * ```json
12
+ * {
13
+ * "compilerOptions": {
14
+ * "plugins": [{ "transform": "@fulcro/types/transformer", "transformProgram": true }]
15
+ * }
16
+ * }
17
+ * ```
18
+ *
19
+ * For a bundler use `@fulcro/types/unplugin`, and for the editor
20
+ * `@fulcro/types/language-service`.
21
+ *
22
+ * Without it, the operators are the language's own: a primitive-backed type
23
+ * does plain, unchecked arithmetic on its `number` or `bigint`, and a `Decimal`
24
+ * is refused by the checker and throws at runtime.
25
+ */
26
+ declare const transformer: ProgramTransformer;
27
+ export default transformer;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const transform_core_1 = require("@fulcro/transform-core");
4
+ const rewriter_1 = require("./rewriter/index.js");
5
+ /**
6
+ * The `tsc` plugin giving the operators their meaning on this package's
7
+ * numeric types.
8
+ *
9
+ * A program transformer, not an ordinary one, and the tsconfig entry has to say
10
+ * so: the rewrite must happen before the program is type checked, or
11
+ * `decimal * decimal` has been reported as an error before anything could
12
+ * rewrite it. Wire it through `ts-patch`:
13
+ *
14
+ * ```json
15
+ * {
16
+ * "compilerOptions": {
17
+ * "plugins": [{ "transform": "@fulcro/types/transformer", "transformProgram": true }]
18
+ * }
19
+ * }
20
+ * ```
21
+ *
22
+ * For a bundler use `@fulcro/types/unplugin`, and for the editor
23
+ * `@fulcro/types/language-service`.
24
+ *
25
+ * Without it, the operators are the language's own: a primitive-backed type
26
+ * does plain, unchecked arithmetic on its `number` or `bigint`, and a `Decimal`
27
+ * is refused by the checker and throws at runtime.
28
+ */
29
+ const transformer = (0, transform_core_1.createProgramTransformer)(rewriter_1.OPERATOR_REWRITER);
30
+ exports.default = transformer;
@@ -0,0 +1,3 @@
1
+ import { type ExpressionRewriter } from '@fulcro/transform-core';
2
+ /** The rewriter of the operators on this package's numeric types. */
3
+ export declare const OPERATOR_REWRITER: ExpressionRewriter;