numtypes 0.0.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 (87) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/LICENSE +12 -0
  3. package/LICENSE-APACHE +201 -0
  4. package/LICENSE-MIT +21 -0
  5. package/README.md +652 -0
  6. package/dist/lib/index.d.ts +22 -0
  7. package/dist/lib/index.d.ts.map +1 -0
  8. package/dist/lib/index.js +2 -0
  9. package/dist/lib/index.js.map +1 -0
  10. package/dist/transformer/analyze/analyze-source-file.d.ts +15 -0
  11. package/dist/transformer/analyze/analyze-source-file.d.ts.map +1 -0
  12. package/dist/transformer/analyze/analyze-source-file.js +605 -0
  13. package/dist/transformer/analyze/analyze-source-file.js.map +1 -0
  14. package/dist/transformer/analyze/get-contextual-domain.d.ts +19 -0
  15. package/dist/transformer/analyze/get-contextual-domain.d.ts.map +1 -0
  16. package/dist/transformer/analyze/get-contextual-domain.js +197 -0
  17. package/dist/transformer/analyze/get-contextual-domain.js.map +1 -0
  18. package/dist/transformer/analyze/get-expression-domain.d.ts +26 -0
  19. package/dist/transformer/analyze/get-expression-domain.d.ts.map +1 -0
  20. package/dist/transformer/analyze/get-expression-domain.js +804 -0
  21. package/dist/transformer/analyze/get-expression-domain.js.map +1 -0
  22. package/dist/transformer/analyze/type-domain.d.ts +41 -0
  23. package/dist/transformer/analyze/type-domain.d.ts.map +1 -0
  24. package/dist/transformer/analyze/type-domain.js +260 -0
  25. package/dist/transformer/analyze/type-domain.js.map +1 -0
  26. package/dist/transformer/ast.d.ts +10 -0
  27. package/dist/transformer/ast.d.ts.map +1 -0
  28. package/dist/transformer/ast.js +115 -0
  29. package/dist/transformer/ast.js.map +1 -0
  30. package/dist/transformer/diagnostics.d.ts +17 -0
  31. package/dist/transformer/diagnostics.d.ts.map +1 -0
  32. package/dist/transformer/diagnostics.js +30 -0
  33. package/dist/transformer/diagnostics.js.map +1 -0
  34. package/dist/transformer/domains.d.ts +11 -0
  35. package/dist/transformer/domains.d.ts.map +1 -0
  36. package/dist/transformer/domains.js +32 -0
  37. package/dist/transformer/domains.js.map +1 -0
  38. package/dist/transformer/index.d.ts +10 -0
  39. package/dist/transformer/index.d.ts.map +1 -0
  40. package/dist/transformer/index.js +60 -0
  41. package/dist/transformer/index.js.map +1 -0
  42. package/dist/transformer/operators.d.ts +16 -0
  43. package/dist/transformer/operators.d.ts.map +1 -0
  44. package/dist/transformer/operators.js +44 -0
  45. package/dist/transformer/operators.js.map +1 -0
  46. package/dist/transformer/options.d.ts +19 -0
  47. package/dist/transformer/options.d.ts.map +1 -0
  48. package/dist/transformer/options.js +17 -0
  49. package/dist/transformer/options.js.map +1 -0
  50. package/dist/transformer/symbols.d.ts +56 -0
  51. package/dist/transformer/symbols.d.ts.map +1 -0
  52. package/dist/transformer/symbols.js +270 -0
  53. package/dist/transformer/symbols.js.map +1 -0
  54. package/dist/transformer/transform/erase-imports.d.ts +14 -0
  55. package/dist/transformer/transform/erase-imports.d.ts.map +1 -0
  56. package/dist/transformer/transform/erase-imports.js +174 -0
  57. package/dist/transformer/transform/erase-imports.js.map +1 -0
  58. package/dist/transformer/transform/generated-coercions.d.ts +9 -0
  59. package/dist/transformer/transform/generated-coercions.d.ts.map +1 -0
  60. package/dist/transformer/transform/generated-coercions.js +22 -0
  61. package/dist/transformer/transform/generated-coercions.js.map +1 -0
  62. package/dist/transformer/transform/optimize-coercions.d.ts +11 -0
  63. package/dist/transformer/transform/optimize-coercions.d.ts.map +1 -0
  64. package/dist/transformer/transform/optimize-coercions.js +1702 -0
  65. package/dist/transformer/transform/optimize-coercions.js.map +1 -0
  66. package/dist/transformer/transform/transform-declaration-file.d.ts +9 -0
  67. package/dist/transformer/transform/transform-declaration-file.d.ts.map +1 -0
  68. package/dist/transformer/transform/transform-declaration-file.js +376 -0
  69. package/dist/transformer/transform/transform-declaration-file.js.map +1 -0
  70. package/dist/transformer/transform/transform-expression.d.ts +24 -0
  71. package/dist/transformer/transform/transform-expression.d.ts.map +1 -0
  72. package/dist/transformer/transform/transform-expression.js +545 -0
  73. package/dist/transformer/transform/transform-expression.js.map +1 -0
  74. package/dist/transformer/transform/transform-source-file.d.ts +10 -0
  75. package/dist/transformer/transform/transform-source-file.d.ts.map +1 -0
  76. package/dist/transformer/transform/transform-source-file.js +52 -0
  77. package/dist/transformer/transform/transform-source-file.js.map +1 -0
  78. package/dist/transformer/ts-compat.d.ts +4 -0
  79. package/dist/transformer/ts-compat.d.ts.map +1 -0
  80. package/dist/transformer/ts-compat.js +24 -0
  81. package/dist/transformer/ts-compat.js.map +1 -0
  82. package/docs/implementation-plan.md +335 -0
  83. package/docs/lib-implementation.md +77 -0
  84. package/docs/lowering-optimization-spec.md +1020 -0
  85. package/docs/project-structure.md +52 -0
  86. package/docs/transform-spec.md +2114 -0
  87. package/package.json +83 -0
@@ -0,0 +1,24 @@
1
+ import * as ts from "typescript";
2
+ export function isImportClauseTypeOnly(importClause) {
3
+ const fields = getImportClauseCompatFields(importClause);
4
+ if ("phaseModifier" in fields) {
5
+ return fields.phaseModifier === ts.SyntaxKind.TypeKeyword;
6
+ }
7
+ return fields.isTypeOnly === true;
8
+ }
9
+ export function updateImportClauseCompat(factory, importClause, name, namedBindings) {
10
+ const fields = getImportClauseCompatFields(importClause);
11
+ if ("phaseModifier" in fields) {
12
+ return factory.updateImportClause(importClause, fields.phaseModifier, name, namedBindings);
13
+ }
14
+ return updateImportClauseWithIsTypeOnly(factory, importClause, fields.isTypeOnly === true, name, namedBindings);
15
+ }
16
+ function updateImportClauseWithIsTypeOnly(factory, importClause, isTypeOnly, name, namedBindings) {
17
+ // TypeScript 5.8 exposes only the boolean import-clause update overload.
18
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
19
+ return factory.updateImportClause(importClause, isTypeOnly, name, namedBindings);
20
+ }
21
+ function getImportClauseCompatFields(importClause) {
22
+ return importClause;
23
+ }
24
+ //# sourceMappingURL=ts-compat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ts-compat.js","sourceRoot":"","sources":["../../src/transformer/ts-compat.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAgBjC,MAAM,UAAU,sBAAsB,CAAC,YAA6B;IAClE,MAAM,MAAM,GACV,2BAA2B,CAAC,YAAY,CAAC,CAAC;IAE5C,IAAI,eAAe,IAAI,MAAM,EAAE,CAAC;QAC9B,OAAO,MAAM,CAAC,aAAa,KAAK,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC;IAC5D,CAAC;IAED,OAAO,MAAM,CAAC,UAAU,KAAK,IAAI,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,wBAAwB,CACtC,OAAuB,EACvB,YAA6B,EAC7B,IAA+B,EAC/B,aAAiD;IAEjD,MAAM,MAAM,GACV,2BAA2B,CAAC,YAAY,CAAC,CAAC;IAE5C,IAAI,eAAe,IAAI,MAAM,EAAE,CAAC;QAC9B,OAAQ,OAA4C,CAAC,kBAAkB,CACrE,YAAY,EACZ,MAAM,CAAC,aAAa,EACpB,IAAI,EACJ,aAAa,CACd,CAAC;IACJ,CAAC;IAED,OAAO,gCAAgC,CACrC,OAAO,EACP,YAAY,EACZ,MAAM,CAAC,UAAU,KAAK,IAAI,EAC1B,IAAI,EACJ,aAAa,CACd,CAAC;AACJ,CAAC;AAED,SAAS,gCAAgC,CACvC,OAAuB,EACvB,YAA6B,EAC7B,UAAmB,EACnB,IAA+B,EAC/B,aAAiD;IAEjD,yEAAyE;IACzE,4DAA4D;IAC5D,OAAO,OAAO,CAAC,kBAAkB,CAC/B,YAAY,EACZ,UAAU,EACV,IAAI,EACJ,aAAa,CACd,CAAC;AACJ,CAAC;AAED,SAAS,2BAA2B,CAClC,YAA6B;IAE7B,OAAO,YAAY,CAAC;AACtB,CAAC"}
@@ -0,0 +1,335 @@
1
+ # Implementation Plan
2
+
3
+ This document describes the staged implementation plan for the transformer.
4
+
5
+ The core constraint is that TypeScript widens most branded numeric operations
6
+ back to `number`. For example, if `a: i32` and `b: i32`, TypeScript evaluates
7
+ `a + b` as `number`, not `i32`. The transformer must therefore maintain its own
8
+ numeric-domain analysis instead of relying only on `checker.getTypeAtLocation`.
9
+
10
+ ## Terminology
11
+
12
+ `TypeScript type` means the type reported by the TypeScript checker.
13
+
14
+ `Numeric domain` means the transformer's internal classification:
15
+
16
+ ```text
17
+ i32 | u32 | f32 | f64 | plain-number | unknown
18
+ ```
19
+
20
+ `Domain-bound expression` means an expression whose result is known by the
21
+ transformer to be closed over one numeric domain, even if TypeScript reports the
22
+ expression as `number`.
23
+
24
+ `Domain storage` means an lvalue location whose TypeScript type records a
25
+ numeric domain for later operation dispatch. It does not guarantee that the
26
+ stored JavaScript value has already been coerced into that domain.
27
+
28
+ - a variable, parameter, property, or return position annotated with a numtypes
29
+ branded type;
30
+ - a value inferred from a checked cast call such as `i32(expr)` or an unchecked
31
+ TypeScript assertion such as `expr as i32`;
32
+ - a symbol already recorded by the transformer as domain storage.
33
+
34
+ `Domain leak` means assigning a domain-bound expression into storage that
35
+ TypeScript treats as plain `number`. Domain leaks are compile errors unless the
36
+ user explicitly escapes the domain with a non-numtypes assertion such as
37
+ `(a + b) as number`, `(a + b) as unknown`, or `(a + b) as any`. The operation
38
+ itself is still lowered according to the operand domain; only the storage escape
39
+ is explicit.
40
+
41
+ Wrappers that do not change the value domain, such as non-null assertions and
42
+ `satisfies` clauses, are not escapes. Domain-leak detection must unwrap them and
43
+ inspect the real storage boundary.
44
+
45
+ The transformer intentionally does not duplicate every check that TypeScript's
46
+ type system already performs. When a normal TypeScript assignment or call
47
+ signature rejects `number` where a branded type is required, that TypeScript
48
+ diagnostic is part of the library contract. The transformer adds diagnostics for
49
+ numtypes-specific semantics that TypeScript cannot express, such as arithmetic
50
+ domain tracking, erased cast marker misuse, implicit widening boundaries, and
51
+ ambiguous numeric unions.
52
+
53
+ Because arithmetic over branded operands has TypeScript type `number`, a raw
54
+ operation result cannot be assigned or returned directly where a branded type is
55
+ required. Users must cross that TypeScript boundary with a checked cast call,
56
+ for example `return f64(a / b)` rather than `return a / b` in a function declared
57
+ as returning `f64`.
58
+
59
+ Unchecked assertions are trusted TypeScript assertions. They may satisfy a
60
+ branded boundary and select a domain for later analysis, but they never insert a
61
+ runtime coercion by themselves. `(a + b) as i32` lowers the `a + b` operation
62
+ only if that operation is already domain-bound by its operands. `(a + b) as i32`
63
+ with plain `number` operands emits as `a + b`.
64
+
65
+ Checked cast calls are boundary conversions, not implicit contexts for every
66
+ nested operation. `i32(readNumber())` is valid because the whole plain-number
67
+ expression is cast. `i32(a + b)` is still invalid when `a: i32` and `b: number`;
68
+ the user must write `i32(a + i32(b))`.
69
+
70
+ ## Phase 1: Symbol Resolution
71
+
72
+ Resolve the actual package symbols before doing any analysis.
73
+
74
+ Tasks:
75
+
76
+ - detect imports from `numtypes`;
77
+ - resolve `i32`, `u32`, `f32`, and `f64` through the TypeScript checker;
78
+ - reject lookalike local functions or variables with the same names;
79
+ - build a per-source-file symbol table for cast calls and imported types;
80
+ - preserve enough import metadata so the transform phase can remove phantom
81
+ imports later.
82
+
83
+ Tests:
84
+
85
+ - imported `i32` is recognized;
86
+ - local `function i32(...)` is not recognized;
87
+ - aliased imports such as `import { i32 as int }` are recognized;
88
+ - type-only imports are recognized for annotations.
89
+
90
+ ## Phase 2: Domain Extraction From Types
91
+
92
+ Implement helpers that map TypeScript types and type nodes to numeric domains.
93
+
94
+ Tasks:
95
+
96
+ - detect branded type aliases from `numtypes`;
97
+ - read annotations on parameters, variables, properties, and return types;
98
+ - read numtypes references inside arrays, tuples, object properties, and generic
99
+ type arguments for type surface preservation/erasure;
100
+ - detect inferred branded types from checked cast calls and unchecked
101
+ TypeScript assertions;
102
+ - classify plain `number` separately from `unknown`;
103
+ - preserve storage unions that contain numtypes domains, and add diagnostics for
104
+ ambiguous intersections.
105
+
106
+ Initial rule:
107
+
108
+ ```text
109
+ i32/u32/f32/f64 annotation -> matching numeric domain
110
+ plain number annotation -> plain-number
111
+ missing annotation -> infer from initializer only if TypeScript already infers a branded type
112
+ ```
113
+
114
+ This phase must not infer `const x = a + b` as `i32` just because the initializer
115
+ is an `i32` operation. That expression is domain-bound, but the storage is still
116
+ plain `number` unless the user explicitly casts it. For branded storage,
117
+ `const x: i32 = i32(a + b)` is the valid TypeScript form.
118
+
119
+ ## Phase 3: Expression Domain Analysis
120
+
121
+ Implement a recursive expression analyzer that returns both the TypeScript type
122
+ and the internal numeric domain for each expression.
123
+
124
+ Suggested result shape:
125
+
126
+ ```typescript
127
+ interface ExpressionDomainResult {
128
+ readonly domain: NumericDomain | "plain-number" | "unknown";
129
+ readonly isDomainBound: boolean;
130
+ readonly requiresClosure: boolean;
131
+ }
132
+ ```
133
+
134
+ Rules:
135
+
136
+ - identifier/property access: use the storage domain recorded for the symbol or
137
+ the branded TypeScript type;
138
+ - checked cast call: source expression is analyzed first, then the target
139
+ domain is applied and emitted as a runtime coercion;
140
+ - unchecked TypeScript assertion: the asserted domain is applied for analysis,
141
+ but the assertion itself emits no runtime coercion and is treated as a
142
+ trusted operand for later operations;
143
+ - checked cast call argument: analyze the argument normally; the cast converts
144
+ the final argument value to the target domain, but it does not automatically
145
+ make mixed branded/plain operations inside the argument valid;
146
+ - numeric literal: may be contextually coerced only when a target domain is
147
+ available;
148
+ - unary arithmetic: domain follows the operand when the operator is supported;
149
+ - binary arithmetic: same-domain operands produce a domain-bound expression of
150
+ that domain;
151
+ - integer bitwise: allowed only for `i32` and `u32`;
152
+ - mixed branded domains require explicit casts;
153
+ - branded domain plus plain `number` requires an explicit cast unless the plain
154
+ side is an allowed contextual literal;
155
+ - unsupported expressions return `unknown` and are rejected when a numeric
156
+ domain is required.
157
+
158
+ The analyzer should cache results by `ts.Node` identity within one source file.
159
+
160
+ ## Phase 4: Contextual Domain Analysis
161
+
162
+ Implement target-domain discovery for expression positions.
163
+
164
+ Contextual domains:
165
+
166
+ - variable initializer target from declaration annotation or inferred branded
167
+ cast result, only after the source has passed TypeScript's branded boundary;
168
+ - assignment target from the resolved lvalue symbol, only after the source has
169
+ passed TypeScript's branded boundary;
170
+ - return expression target from containing function return annotation, only
171
+ after the source has passed TypeScript's branded boundary;
172
+ - argument target only from known numtypes cast functions;
173
+ - conditional expression branch target from the containing target domain;
174
+ - array/property element target only when its declared type is a numtypes domain.
175
+
176
+ Compile errors:
177
+
178
+ - domain-bound expression assigned to plain `number` storage;
179
+ - domain-bound expression returned from an unannotated function;
180
+ - domain-bound expression passed to a plain `number` parameter without explicit
181
+ escape or cast;
182
+ - same-domain arithmetic stored in an unannotated variable when TypeScript would
183
+ infer plain `number`.
184
+
185
+ Do not treat a branded lvalue annotation as permission to accept TypeScript
186
+ invalid source such as `const x: i32 = a + b` or `return a / b` from a `f64`
187
+ function. Those cases must be written with checked casts.
188
+
189
+ Normal function and method parameters are not implicit domain contexts. A call
190
+ such as `values.push(a + b)` for `values: i32[]` is intentionally rejected by
191
+ TypeScript because `a + b` has TypeScript type `number`; users must write
192
+ `values.push(i32(a + b))` when they want to cross that call boundary. This keeps
193
+ call arguments explicit and avoids hidden contextual lowering through arbitrary
194
+ signatures.
195
+
196
+ Generic type arguments that contain numtypes domains are allowed as type surface,
197
+ but they do not create special runtime semantics. The transformer should preserve
198
+ or erase types such as `Array<i32>`, `[i32, f32]`, `Promise<i32>`, `Map<string,
199
+ i32>`, and `Box<i32>`, but it should not interpret arbitrary generic methods,
200
+ callbacks, or asynchronous resolution. Calls through those APIs rely on
201
+ TypeScript signatures and explicit checked casts at value boundaries.
202
+
203
+ Example:
204
+
205
+ ```typescript
206
+ function f(a: i32, b: i32) {
207
+ const x = a + b;
208
+ }
209
+ ```
210
+
211
+ must produce:
212
+
213
+ ```text
214
+ error: result of i32 operation is assigned to untyped variable 'x'; use a checked cast such as i32(...) at the boundary or explicitly escape to a non-numtypes type
215
+ ```
216
+
217
+ Allowed forms:
218
+
219
+ ```typescript
220
+ function f(a: i32, b: i32): i32 {
221
+ const x: i32 = i32(a + b);
222
+ return x;
223
+ }
224
+
225
+ function g(a: i32, b: i32) {
226
+ const x = i32(a + b);
227
+ return x;
228
+ }
229
+ ```
230
+
231
+ ## Phase 5: Diagnostics Pass
232
+
233
+ Run a pre-transform analysis pass that reports all errors before rewriting.
234
+
235
+ Tasks:
236
+
237
+ - traverse source files once and collect domain diagnostics;
238
+ - include source spans and stable diagnostic codes;
239
+ - make diagnostics deterministic and fixture-testable;
240
+ - fail transform when diagnostics exist.
241
+
242
+ Important diagnostic categories:
243
+
244
+ - implicit cast from branded domain to plain `number`;
245
+ - implicit cast between different branded domains;
246
+ - mixed branded/plain operands inside an operation, even when the whole
247
+ expression is later wrapped in a checked cast;
248
+ - bitwise operation on `f32` or `f64`;
249
+ - domain-bound result escaping through unannotated storage;
250
+ - unresolved or shadowed numtypes symbols;
251
+ - erased cast marker misuse, such as storing or value-re-exporting `i32`;
252
+ - unsupported expression shape in a domain-required context.
253
+
254
+ ## Phase 6: Expression Rewriting
255
+
256
+ After diagnostics pass, rewrite expressions according to the domain analysis.
257
+
258
+ Tasks:
259
+
260
+ - insert operand coercions;
261
+ - insert result closures;
262
+ - lower integer multiplication to `Math.imul`;
263
+ - preserve source evaluation order;
264
+ - preserve prefix/postfix update value semantics;
265
+ - preserve single evaluation for complex assignment targets;
266
+ - do not treat compound assignments such as `a += b` as accepted branded-source
267
+ syntax; TypeScript rejects them for branded lvalues, so users must write
268
+ checked assignments such as `a = i32(a + b)`;
269
+ - erase checked cast calls into coercion idioms;
270
+ - erase unchecked TypeScript assertions without adding coercions;
271
+ - remove phantom imports when no runtime import remains.
272
+
273
+ The rewrite should use the cached domain analysis rather than re-deriving
274
+ domains during emit.
275
+
276
+ ## Phase 7: Fixture Test Runner
277
+
278
+ Build the source-to-source fixture runner.
279
+
280
+ Fixture types:
281
+
282
+ - `*.input.ts` and `*.output.ts` for successful transforms;
283
+ - `*.input.ts` and `*.errors.txt` for diagnostics;
284
+ - grouped directories for `i32`, `u32`, `f32`, `f64`, mixed domains,
285
+ assignments, and imports.
286
+
287
+ The runner should normalize line endings and use TypeScript's printer so output
288
+ is stable.
289
+
290
+ ## Phase 8: V8 Lowering Probes
291
+
292
+ Add opt-in engine probes after the transform output is stable.
293
+
294
+ Tasks:
295
+
296
+ - generate small JS probes from fixture output;
297
+ - run them under Node with explicit V8 flags;
298
+ - record the Node and V8 versions in test output;
299
+ - assert narrow, version-aware facts only;
300
+ - keep these probes out of the default test command.
301
+
302
+ Candidate probes:
303
+
304
+ - i32 addition closure;
305
+ - i32/u32 `Math.imul` multiplication;
306
+ - u32 logical right shift;
307
+ - f32 `Math.fround` arithmetic;
308
+ - f64 unary-plus arithmetic.
309
+
310
+ ## Phase 9: Benchmarks
311
+
312
+ Add opt-in benchmarks after correctness tests are meaningful.
313
+
314
+ Benchmark groups:
315
+
316
+ - transformer throughput on large files;
317
+ - emitted i32/u32/f32/f64 runtime shapes;
318
+ - baseline JavaScript versus transformed JavaScript;
319
+ - compile-time overhead of diagnostics and domain analysis caching.
320
+
321
+ Benchmarks should not gate normal correctness tests until there is a stable
322
+ baseline and variance policy.
323
+
324
+ ## Implementation Order
325
+
326
+ 1. Symbol resolution.
327
+ 2. Type-to-domain extraction.
328
+ 3. Expression domain analyzer for identifiers, literals, casts, unary, binary.
329
+ 4. Contextual target-domain analyzer for variable declarations and returns.
330
+ 5. Diagnostics for implicit plain-number leaks.
331
+ 6. Fixture runner and first failing diagnostics fixtures.
332
+ 7. Expression rewrite for casts and simple binary arithmetic.
333
+ 8. Assignment/update rewrite.
334
+ 9. Import erasure.
335
+ 10. V8 probes and benchmark expansion.
@@ -0,0 +1,77 @@
1
+ # Lib Implementation
2
+
3
+ The authoritative public symbol surface is `src/lib/index.ts`. This document
4
+ must stay aligned with that file.
5
+
6
+ These symbols are phantom runtime markers: user code imports and calls the
7
+ function symbols before transformation, but the transformer must lower every
8
+ function call to the matching JavaScript coercion idiom and remove the package
9
+ import when no runtime value remains.
10
+
11
+ The function symbols are only valid as direct checked cast calls such as
12
+ `i32(value)` or namespace-qualified direct calls such as `nt.i32(value)`.
13
+ Because the package root has no runtime implementation, users must not store,
14
+ pass, object-shorthand, optional-call, optional-access, spread-call,
15
+ type-argument-call, parenthesized-callee-call, or value-re-export these function
16
+ symbols. Type-only re-exports of the branded type aliases are allowed.
17
+
18
+ The exported type aliases are type-only domain markers. A TypeScript assertion
19
+ such as `value as i32` or `<i32>value` is unchecked and must not insert a runtime
20
+ coercion by itself. It only changes the domain that later numtypes operations
21
+ use for dispatch. Use the function form, such as `i32(value)`, when runtime
22
+ coercion is required at that expression boundary.
23
+
24
+ The package root intentionally has no executable implementation. The emitted
25
+ JavaScript for `src/lib/index.ts` should remain effectively empty.
26
+
27
+ ## Public Surface
28
+
29
+ ```typescript
30
+ declare const i32Brand: unique symbol;
31
+ declare const u32Brand: unique symbol;
32
+ declare const f32Brand: unique symbol;
33
+ declare const f64Brand: unique symbol;
34
+
35
+ export type i32 = number & {
36
+ readonly [i32Brand]: never;
37
+ };
38
+
39
+ export type u32 = number & {
40
+ readonly [u32Brand]: never;
41
+ };
42
+
43
+ export type f32 = number & {
44
+ readonly [f32Brand]: never;
45
+ };
46
+
47
+ export type f64 = number & {
48
+ readonly [f64Brand]: never;
49
+ };
50
+
51
+ export declare function i32(value: number): i32;
52
+
53
+ export declare function u32(value: number): u32;
54
+
55
+ export declare function f32(value: number): f32;
56
+
57
+ export declare function f64(value: number): f64;
58
+ ```
59
+
60
+ ## Transformer Lowering
61
+
62
+ The runtime behavior for checked cast calls is produced by the transformer, not
63
+ by these declarations.
64
+
65
+ ```typescript
66
+ i32(value) => value | 0
67
+ u32(value) => value >>> 0
68
+ f32(value) => Math.fround(value)
69
+ f64(value) => +value
70
+ ```
71
+
72
+ Unchecked TypeScript assertions erase like normal TypeScript syntax.
73
+
74
+ ```typescript
75
+ value as i32 => value
76
+ <i32>value => value
77
+ ```