@esportsplus/reactivity 0.32.0 → 0.34.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # @esportsplus/reactivity
2
2
 
3
+ Project doc bundle: [docs/index.md](./docs/index.md) — rejected dead-ends, skip reasons, completed-work index.
4
+
3
5
  A fine-grained reactivity system with compile-time transformations. Write reactive code with natural JavaScript syntax while the compiler generates optimized signal-based code.
4
6
 
5
7
  ## Installation
@@ -313,6 +315,34 @@ All standard array methods (`push`, `pop`, `shift`, `unshift`, `splice`, `sort`,
313
315
  | `splice` | `{ start, deleteCount, items }` | Array was spliced |
314
316
  | `unshift` | `{ items: T[] }` | Items were unshifted |
315
317
 
318
+ ## Architecture
319
+
320
+ - `src/system.ts` — the core signal/computed/effect engine: height-bucketed heap scheduler,
321
+ generation-version dependency dedup (read-version dedup), and iterative (non-recursive)
322
+ notify/update/dispose walks. Also supports async (Promise/AsyncIterable) computeds and
323
+ per-key selector signals (`signal.selector`).
324
+ - `src/constants.ts` — shared state bitmasks and symbol constants consumed by every other module.
325
+ - `src/types.ts` — shared `Signal`/`Computed`/`Link`/`Reactive` types.
326
+ - `src/reactive/index.ts`, `src/reactive/array.ts`, `src/reactive/object.ts` — the runtime
327
+ `reactive()` dispatch and the `ReactiveObject`/`ReactiveArray` classes it builds on.
328
+ - `src/compiler/*` — the build-time transform pipeline (`constants.ts`, `primitives.ts`,
329
+ `object.ts`, `array.ts`, `index.ts`) plus the `plugins/tsc.ts` and `plugins/vite.ts`
330
+ entrypoints that wire it into a build (see Transformer Plugins above).
331
+
332
+ ## Development
333
+
334
+ ```bash
335
+ pnpm install
336
+ pnpm build # tsc
337
+ pnpm test # vitest run
338
+ pnpm bench # vitest bench --run
339
+ ```
340
+
341
+ `agent:test` (`tsc --noEmit && vitest run`) and `agent:bench` (`vitest bench --run`) are the
342
+ CI-facing aliases of the same build/test/bench commands.
343
+
316
344
  ## License
317
345
 
318
346
  MIT
347
+
348
+ <!-- claude-code:readme-source-hash: 189167a17e9be8c6 -->
@@ -1,5 +1,5 @@
1
1
  import { ts } from '@esportsplus/typescript';
2
2
  import type { ReplacementIntent } from '@esportsplus/typescript/compiler';
3
3
  import type { Bindings } from './types.js';
4
- declare const _default: (sourceFile: ts.SourceFile, bindings: Bindings, checker?: ts.TypeChecker) => ReplacementIntent[];
5
4
  export default _default;
5
+ declare function _default(sourceFile: ts.SourceFile, bindings: Bindings, checker?: ts.Checker): ReplacementIntent[];
@@ -160,7 +160,7 @@ function visit(ctx, node) {
160
160
  node.operatorToken.kind === ts.SyntaxKind.EqualsToken &&
161
161
  ts.isIdentifier(node.left)) {
162
162
  let name = node.left.text, right = node.right;
163
- while (ts.isAsExpression(right) || ts.isTypeAssertionExpression(right)) {
163
+ while (ts.isAsExpression(right) || ts.isTypeAssertion(right)) {
164
164
  right = right.expression;
165
165
  }
166
166
  if (ctx.bindings.get(name) === TYPES.Array && ts.isArrayLiteralExpression(right)) {
@@ -172,7 +172,7 @@ function visit(ctx, node) {
172
172
  });
173
173
  }
174
174
  }
175
- ts.forEachChild(node, n => visit(ctx, n));
175
+ node.forEachChild(n => visit(ctx, n));
176
176
  }
177
177
  export default (sourceFile, bindings, checker) => {
178
178
  let ctx = {
@@ -27,7 +27,7 @@ function hasReactiveCalls(checker, node) {
27
27
  return true;
28
28
  }
29
29
  let found = false;
30
- ts.forEachChild(node, child => {
30
+ node.forEachChild(child => {
31
31
  if (!found && hasReactiveCalls(checker, child)) {
32
32
  found = true;
33
33
  }
@@ -41,7 +41,7 @@ function visit(ctx, node) {
41
41
  node
42
42
  });
43
43
  }
44
- ts.forEachChild(node, n => visit(ctx, n));
44
+ node.forEachChild(n => visit(ctx, n));
45
45
  }
46
46
  export default {
47
47
  patterns: ['reactive(', 'reactive<'],
@@ -5,5 +5,5 @@ type ObjectTransformResult = {
5
5
  prepend: string[];
6
6
  replacements: ReplacementIntent[];
7
7
  };
8
- declare const _default: (sourceFile: ts.SourceFile, bindings: Bindings, checker?: ts.TypeChecker) => ObjectTransformResult;
9
8
  export default _default;
9
+ declare function _default(sourceFile: ts.SourceFile, bindings: Bindings, checker?: ts.Checker): ObjectTransformResult;
@@ -13,10 +13,10 @@ function analyzeProperty(prop, sourceFile) {
13
13
  return null;
14
14
  }
15
15
  let unwrapped = prop.initializer, value = unwrapped, valueText = value.getText(sourceFile);
16
- while (ts.isAsExpression(unwrapped) || ts.isTypeAssertionExpression(unwrapped) || ts.isParenthesizedExpression(unwrapped)) {
16
+ while (ts.isAsExpression(unwrapped) || ts.isTypeAssertion(unwrapped) || ts.isParenthesizedExpression(unwrapped)) {
17
17
  unwrapped = unwrapped.expression;
18
18
  }
19
- if (ts.isAsExpression(value) || ts.isTypeAssertionExpression(value)) {
19
+ if (ts.isAsExpression(value) || ts.isTypeAssertion(value)) {
20
20
  let type = value.type;
21
21
  if (ts.isArrayTypeNode(type) ||
22
22
  (ts.isTypeReferenceNode(type) &&
@@ -161,12 +161,12 @@ function visit(ctx, node) {
161
161
  for (let i = 0, n = props.length; i < n; i++) {
162
162
  let prop = props[i];
163
163
  if (ts.isSpreadAssignment(prop)) {
164
- ts.forEachChild(node, n => visit(ctx, n));
164
+ node.forEachChild(n => visit(ctx, n));
165
165
  return;
166
166
  }
167
167
  let analyzed = analyzeProperty(prop, ctx.sourceFile);
168
168
  if (!analyzed) {
169
- ts.forEachChild(node, n => visit(ctx, n));
169
+ node.forEachChild(n => visit(ctx, n));
170
170
  return;
171
171
  }
172
172
  properties.push(analyzed);
@@ -183,7 +183,7 @@ function visit(ctx, node) {
183
183
  });
184
184
  }
185
185
  }
186
- ts.forEachChild(node, n => visit(ctx, n));
186
+ node.forEachChild(n => visit(ctx, n));
187
187
  }
188
188
  export default (sourceFile, bindings, checker) => {
189
189
  let ctx = {
@@ -1,12 +1,14 @@
1
1
  declare const _default: ({ root }?: {
2
2
  root?: string;
3
3
  }) => {
4
+ closeBundle: () => void;
5
+ closeWatcher: () => void;
4
6
  configResolved: (config: unknown) => void;
5
- enforce: "pre";
7
+ enforce: 'pre';
6
8
  name: string;
7
9
  transform: (code: string, id: string) => {
8
10
  code: string;
9
- map: null;
11
+ map: import("@esportsplus/typescript/compiler").SourceMapV3;
10
12
  } | null;
11
13
  watchChange: (id: string) => void;
12
14
  };
@@ -1,5 +1,5 @@
1
1
  import { ts } from '@esportsplus/typescript';
2
2
  import type { ReplacementIntent } from '@esportsplus/typescript/compiler';
3
3
  import type { Bindings } from './types.js';
4
- declare const _default: (sourceFile: ts.SourceFile, bindings: Bindings, isReactiveCall: (node: ts.Node) => boolean) => ReplacementIntent[];
5
4
  export default _default;
5
+ declare function _default(sourceFile: ts.SourceFile, bindings: Bindings, isReactiveCall: (node: ts.Node) => boolean): ReplacementIntent[];
@@ -37,7 +37,7 @@ function visit(ctx, node) {
37
37
  }
38
38
  else {
39
39
  let unwrapped = arg;
40
- while (ts.isAsExpression(unwrapped) || ts.isParenthesizedExpression(unwrapped) || ts.isTypeAssertionExpression(unwrapped)) {
40
+ while (ts.isAsExpression(unwrapped) || ts.isParenthesizedExpression(unwrapped) || ts.isTypeAssertion(unwrapped)) {
41
41
  unwrapped = unwrapped.expression;
42
42
  }
43
43
  if (ts.isArrayLiteralExpression(unwrapped) || ts.isObjectLiteralExpression(unwrapped)) {
@@ -48,7 +48,7 @@ function visit(ctx, node) {
48
48
  generate: () => `${NAMESPACE}.reactive`,
49
49
  node: call.expression
50
50
  });
51
- ts.forEachChild(node, n => visit(ctx, n));
51
+ node.forEachChild(n => visit(ctx, n));
52
52
  return;
53
53
  }
54
54
  }
@@ -97,7 +97,7 @@ function visit(ctx, node) {
97
97
  node.parent &&
98
98
  !(ts.isVariableDeclaration(node.parent) && node.parent.name === node)) {
99
99
  if (ts.isPropertyAccessExpression(node.parent) && node.parent.name === node) {
100
- ts.forEachChild(node, n => visit(ctx, n));
100
+ node.forEachChild(n => visit(ctx, n));
101
101
  return;
102
102
  }
103
103
  let bindings = ctx.scopedBindings, binding, name = node.text;
@@ -178,7 +178,7 @@ function visit(ctx, node) {
178
178
  }
179
179
  }
180
180
  }
181
- ts.forEachChild(node, n => visit(ctx, n));
181
+ node.forEachChild(n => visit(ctx, n));
182
182
  }
183
183
  export default (sourceFile, bindings, isReactiveCall) => {
184
184
  let ctx = {
@@ -41,6 +41,9 @@ declare class ReactiveArray<T> extends Array<T> {
41
41
  private _length;
42
42
  listeners: Listeners<T>;
43
43
  constructor(...items: T[]);
44
+ static get [Symbol.species](): ArrayConstructor;
45
+ get $length(): number;
46
+ set $length(value: number);
44
47
  $set(i: number, value: T): void;
45
48
  clear(): void;
46
49
  concat(...items: ConcatArray<T>[]): ReactiveArray<T>;
@@ -56,7 +59,5 @@ declare class ReactiveArray<T> extends Array<T> {
56
59
  sort(fn?: (a: T, b: T) => number): this;
57
60
  splice(start: number, deleteCount?: number, ...items: T[]): T[];
58
61
  unshift(...items: T[]): number;
59
- get $length(): number;
60
- set $length(value: number);
61
62
  }
62
63
  export { ReactiveArray };
@@ -14,6 +14,18 @@ class ReactiveArray extends Array {
14
14
  super(...items);
15
15
  this._length = signal(items.length);
16
16
  }
17
+ static get [Symbol.species]() {
18
+ return Array;
19
+ }
20
+ get $length() {
21
+ return read(this._length);
22
+ }
23
+ set $length(value) {
24
+ if (value > this.length) {
25
+ throw Error(`@esportsplus/reactivity: cannot set length to a value larger than the current length, use splice instead.`);
26
+ }
27
+ this.splice(value, this.length);
28
+ }
17
29
  $set(i, value) {
18
30
  let prev = this[i];
19
31
  if (prev === value) {
@@ -146,29 +158,34 @@ class ReactiveArray extends Array {
146
158
  return item;
147
159
  }
148
160
  sort(fn) {
149
- let n = this.length, before = new Array(n);
150
- for (let i = 0; i < n; i++) {
151
- before[i] = this[i];
152
- }
153
- super.sort(fn);
154
- let buckets = new Map(), order = new Array(n);
155
- for (let i = 0; i < n; i++) {
156
- let value = before[i], list = buckets.get(value);
157
- if (!list) {
158
- buckets.set(value, [i]);
161
+ if (this.listeners.sort === undefined) {
162
+ super.sort(fn);
163
+ }
164
+ else {
165
+ let n = this.length, before = new Array(n);
166
+ for (let i = 0; i < n; i++) {
167
+ before[i] = this[i];
159
168
  }
160
- else {
161
- list.push(i);
169
+ super.sort(fn);
170
+ let buckets = new Map(), order = new Array(n);
171
+ for (let i = 0; i < n; i++) {
172
+ let value = before[i], list = buckets.get(value);
173
+ if (!list) {
174
+ buckets.set(value, [i]);
175
+ }
176
+ else {
177
+ list.push(i);
178
+ }
162
179
  }
163
- }
164
- for (let i = 0; i < n; i++) {
165
- let list = buckets.get(this[i]);
166
- order[i] = list.length === 1 ? list[0] : list[list.length - 1];
167
- if (list.length > 1) {
168
- list.pop();
180
+ for (let i = 0; i < n; i++) {
181
+ let list = buckets.get(this[i]);
182
+ order[i] = list.length === 1 ? list[0] : list[list.length - 1];
183
+ if (list.length > 1) {
184
+ list.pop();
185
+ }
169
186
  }
187
+ this.dispatch('sort', { order });
170
188
  }
171
- this.dispatch('sort', { order });
172
189
  return this;
173
190
  }
174
191
  splice(start, deleteCount = this.length, ...items) {
@@ -191,15 +208,6 @@ class ReactiveArray extends Array {
191
208
  this.dispatch('unshift', { items });
192
209
  return length;
193
210
  }
194
- get $length() {
195
- return read(this._length);
196
- }
197
- set $length(value) {
198
- if (value > this.length) {
199
- throw Error(`@esportsplus/reactivity: cannot set length to a value larger than the current length, use splice instead.`);
200
- }
201
- this.splice(value, this.length);
202
- }
203
211
  }
204
212
  Object.defineProperty(ReactiveArray.prototype, REACTIVE_ARRAY, { value: true });
205
213
  export { ReactiveArray };
@@ -4,7 +4,7 @@ import { ReactiveArray } from './array.js';
4
4
  declare class ReactiveObject<T extends Record<PropertyKey, unknown>> {
5
5
  protected disposers: VoidFunction[] | null;
6
6
  constructor(data: T | null);
7
- protected [COMPUTED]<T extends Computed<ReturnType<T>>['fn']>(value: T): Computed<import("../types.js").Settled<ReturnType<T>>>;
7
+ protected [COMPUTED]<T extends Computed<ReturnType<T>>['fn']>(value: T): import("../types.js").ComputedResult<ReturnType<T>>;
8
8
  protected [REACTIVE_ARRAY]<U>(value: U[]): ReactiveArray<U>;
9
9
  protected [SIGNAL]<T>(value: T): import("../types.js").Signal<T>;
10
10
  dispose(): void;
package/build/system.d.ts CHANGED
@@ -1,25 +1,25 @@
1
- import { Computed, Settled, Signal } from './types.js';
1
+ import { Computed, ComputedResult, Settled, Signal } from './types.js';
2
2
  declare const batch: <T>(fn: () => T) => T;
3
- declare const computed: {
4
- <T>(fn: Computed<T>["fn"], equals?: ((a: Settled<T>, b: Settled<T>) => boolean) | null): Computed<Settled<T>>;
5
- invalidate<T>(c: Computed<T>): void;
6
- };
3
+ declare function computed<T>(fn: Computed<T>['fn'], equals?: ((a: Settled<T>, b: Settled<T>) => boolean) | null): ComputedResult<T>;
4
+ declare namespace computed {
5
+ var invalidate: <T>(c: Computed<T>) => void;
6
+ }
7
7
  declare const dispose: <T>(computed: Computed<T>) => void;
8
- declare const effect: <T>(fn: Computed<T>["fn"], onError?: (e: unknown) => void) => () => void;
8
+ declare const effect: <T>(fn: Computed<T>['fn'], apply?: (value: T, prev: T | undefined) => void) => () => void;
9
9
  declare const flush: () => void;
10
10
  declare const isComputed: (value: unknown) => value is Computed<unknown>;
11
11
  declare const isSignal: (value: unknown) => value is Signal<unknown>;
12
12
  declare const onCleanup: (fn: VoidFunction) => typeof fn;
13
13
  declare const peek: <T>(node: Signal<T> | Computed<T>) => T;
14
14
  declare const read: <T>(node: Signal<T> | Computed<T>) => T;
15
- declare const root: {
16
- <T>(fn: ((dispose: VoidFunction) => T) | (() => T)): T;
17
- disposables: number;
18
- };
19
- declare const signal: {
20
- <T>(value: T, equals?: ((a: T, b: T) => boolean) | null): Signal<T>;
21
- selector<T>(node: Signal<T>, key: T): boolean;
22
- };
15
+ declare function root<T>(fn: ((dispose: VoidFunction) => T) | (() => T)): T;
16
+ declare namespace root {
17
+ var disposables: number;
18
+ }
19
+ declare function signal<T>(value: T, equals?: ((a: T, b: T) => boolean) | null): Signal<T>;
20
+ declare namespace signal {
21
+ var selector: <T>(node: Signal<T>, key: T) => boolean;
22
+ }
23
23
  declare const untrack: <T>(fn: () => T) => T;
24
24
  declare const write: <T>(signal: Signal<T>, value: T) => void;
25
25
  export { batch, computed, dispose, effect, flush, isComputed, isSignal, onCleanup, peek, read, root, signal, untrack, write };
package/build/system.js CHANGED
@@ -412,18 +412,23 @@ function update(root) {
412
412
  }
413
413
  }
414
414
  function makeAsyncComputed(factory) {
415
- let error = signal(undefined), node = signal(undefined), v = 0;
415
+ let error = signal(undefined), node = signal(undefined), pending = signal(false), v = 0;
416
416
  let stop = effect(() => {
417
417
  let fail = (e) => {
418
418
  if (id === v && !(factory.state & (STATE_IN_HEAP | STATE_NOTIFY_MASK))) {
419
419
  write(error, e === undefined ? new Error('reactivity: async computed rejected with undefined') : e);
420
+ write(pending, false);
420
421
  }
421
422
  }, id = ++v, result = read(factory);
422
423
  if (isPromise(result)) {
424
+ if (id === v && !(factory.state & (STATE_IN_HEAP | STATE_NOTIFY_MASK))) {
425
+ write(pending, true);
426
+ }
423
427
  result.then((value) => {
424
428
  if (id === v && !(factory.state & (STATE_IN_HEAP | STATE_NOTIFY_MASK))) {
425
429
  write(error, undefined);
426
430
  write(node, value);
431
+ write(pending, false);
427
432
  }
428
433
  }, fail);
429
434
  }
@@ -439,14 +444,22 @@ function makeAsyncComputed(factory) {
439
444
  if (!r.done) {
440
445
  write(error, undefined);
441
446
  write(node, r.value);
447
+ write(pending, false);
442
448
  it.next().then(step, fail);
443
449
  }
450
+ else {
451
+ write(pending, false);
452
+ }
444
453
  };
454
+ if (id === v && !(factory.state & (STATE_IN_HEAP | STATE_NOTIFY_MASK))) {
455
+ write(pending, true);
456
+ }
445
457
  untrack(() => it.next()).then(step, fail);
446
458
  }
447
459
  else {
448
460
  write(error, undefined);
449
461
  write(node, result);
462
+ write(pending, false);
450
463
  }
451
464
  });
452
465
  let wrapper = makeComputed(() => {
@@ -456,6 +469,7 @@ function makeAsyncComputed(factory) {
456
469
  }
457
470
  return read(node);
458
471
  });
472
+ wrapper.pending = pending;
459
473
  asyncMeta.set(wrapper, { factory: factory });
460
474
  wrapper.disposal = stop;
461
475
  return wrapper;
@@ -574,15 +588,14 @@ const dispose = (computed) => {
574
588
  draining = false;
575
589
  }
576
590
  };
577
- const effect = (fn, onError) => {
578
- let c = makeComputed(onError
591
+ const effect = (fn, apply) => {
592
+ let prev;
593
+ let c = makeComputed(apply
579
594
  ? (o) => {
580
- try {
581
- return fn(o);
582
- }
583
- catch (e) {
584
- onError(e);
585
- }
595
+ let v = fn(o);
596
+ untrack(() => apply(v, prev));
597
+ prev = v;
598
+ return v;
586
599
  }
587
600
  : fn);
588
601
  c.state |= STATE_EFFECT;
@@ -681,9 +694,12 @@ root.disposables = 0;
681
694
  const signal = (value, equals = null) => {
682
695
  return {
683
696
  equals: equals,
697
+ key: undefined,
684
698
  keys: null,
685
699
  nextPending: null,
700
+ parent: undefined,
686
701
  rv: 0,
702
+ state: 0,
687
703
  subs: null,
688
704
  subsTail: null,
689
705
  type: SIGNAL,
@@ -703,6 +719,7 @@ signal.selector = (node, key) => {
703
719
  nextPending: null,
704
720
  parent: node,
705
721
  rv: 0,
722
+ state: 0,
706
723
  subs: null,
707
724
  subsTail: null,
708
725
  type: SIGNAL,
package/build/types.d.ts CHANGED
@@ -19,6 +19,9 @@ interface Computed<T> {
19
19
  subsTail: Link | null;
20
20
  value: T;
21
21
  }
22
+ type ComputedResult<T> = T extends Promise<any> | AsyncIterable<any> ? Computed<Settled<T>> & {
23
+ pending: Signal<boolean>;
24
+ } : Computed<Settled<T>>;
22
25
  interface Link {
23
26
  dep: Signal<unknown> | Computed<unknown>;
24
27
  nextDep: Link | null;
@@ -42,9 +45,12 @@ type SelectorSignal<T> = Signal<boolean> & {
42
45
  type Settled<T> = T extends Promise<infer U> ? Awaited<U> | undefined : T extends AsyncIterable<infer U> ? U | undefined : T;
43
46
  type Signal<T> = {
44
47
  equals: ((a: unknown, b: unknown) => boolean) | null;
48
+ key: unknown;
45
49
  keys: Map<T, SelectorSignal<T>> | null;
46
50
  nextPending: Signal<unknown> | null;
51
+ parent: Signal<unknown> | undefined;
47
52
  rv: number;
53
+ state: number;
48
54
  subs: Link | null;
49
55
  subsTail: Link | null;
50
56
  type: typeof SIGNAL;
@@ -55,4 +61,4 @@ interface TransformResult {
55
61
  code: string;
56
62
  sourceFile: ts.SourceFile;
57
63
  }
58
- export type { Computed, Link, Reactive, SelectorSignal, Settled, Signal, TransformResult };
64
+ export type { Computed, ComputedResult, Link, Reactive, SelectorSignal, Settled, Signal, TransformResult };
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "author": "ICJR",
3
3
  "dependencies": {
4
- "@esportsplus/utilities": "^0.27.3"
4
+ "@esportsplus/utilities": "^0.28.0"
5
5
  },
6
6
  "devDependencies": {
7
- "@esportsplus/typescript": "^0.29.1",
8
- "@types/node": "^25.6.0",
9
- "vite": "^8.0.8",
10
- "vitest": "^4.1.4"
7
+ "@esportsplus/typescript": "^0.31.0",
8
+ "@types/node": "^26.1.1",
9
+ "vite": "^8.1.5",
10
+ "vitest": "^4.1.10"
11
11
  },
12
12
  "exports": {
13
13
  ".": {
@@ -36,7 +36,7 @@
36
36
  },
37
37
  "type": "module",
38
38
  "types": "build/index.d.ts",
39
- "version": "0.32.0",
39
+ "version": "0.34.0",
40
40
  "scripts": {
41
41
  "agent:bench": "vitest bench --run",
42
42
  "agent:test": "tsc --noEmit && vitest run",
@@ -1,2 +1,4 @@
1
1
  allowBuilds:
2
2
  esbuild: true
3
+ minimumReleaseAgeExclude:
4
+ - '@esportsplus/typescript@0.31.0'
@@ -7,13 +7,13 @@ import type { Bindings } from './types';
7
7
 
8
8
  type VisitContext = {
9
9
  bindings: Bindings;
10
- checker: ts.TypeChecker | undefined;
10
+ checker: ts.Checker | undefined;
11
11
  replacements: ReplacementIntent[];
12
12
  sourceFile: ts.SourceFile;
13
13
  };
14
14
 
15
15
 
16
- function isReactiveCall(checker: ts.TypeChecker | undefined, node: ts.Node): node is ts.CallExpression {
16
+ function isReactiveCall(checker: ts.Checker | undefined, node: ts.Node): node is ts.CallExpression {
17
17
  if (!ts.isCallExpression(node) || !ts.isIdentifier(node.expression)) {
18
18
  return false;
19
19
  }
@@ -220,7 +220,7 @@ function visit(ctx: VisitContext, node: ts.Node): void {
220
220
  right = node.right;
221
221
 
222
222
  // Unwrap "as" expressions: arr = [] as Type[]
223
- while (ts.isAsExpression(right) || ts.isTypeAssertionExpression(right)) {
223
+ while (ts.isAsExpression(right) || ts.isTypeAssertion(right)) {
224
224
  right = right.expression;
225
225
  }
226
226
 
@@ -234,11 +234,11 @@ function visit(ctx: VisitContext, node: ts.Node): void {
234
234
  }
235
235
  }
236
236
 
237
- ts.forEachChild(node, n => visit(ctx, n));
237
+ node.forEachChild(n => visit(ctx, n));
238
238
  }
239
239
 
240
240
 
241
- export default (sourceFile: ts.SourceFile, bindings: Bindings, checker?: ts.TypeChecker): ReplacementIntent[] => {
241
+ export default (sourceFile: ts.SourceFile, bindings: Bindings, checker?: ts.Checker): ReplacementIntent[] => {
242
242
  let ctx: VisitContext = {
243
243
  bindings,
244
244
  checker,
@@ -10,7 +10,7 @@ import primitives from './primitives';
10
10
 
11
11
 
12
12
  type FindRemainingContext = {
13
- checker: ts.TypeChecker;
13
+ checker: ts.Checker;
14
14
  replacements: ReplacementIntent[];
15
15
  sourceFile: ts.SourceFile;
16
16
  transformedNodes: Set<ts.Node>;
@@ -18,7 +18,7 @@ type FindRemainingContext = {
18
18
 
19
19
 
20
20
  function findRemainingCalls(
21
- checker: ts.TypeChecker,
21
+ checker: ts.Checker,
22
22
  sourceFile: ts.SourceFile,
23
23
  transformedNodes: Set<ts.Node>
24
24
  ): ReplacementIntent[] {
@@ -29,7 +29,7 @@ function findRemainingCalls(
29
29
  return ctx.replacements;
30
30
  }
31
31
 
32
- function isReactiveCallExpression(checker: ts.TypeChecker, node: ts.Node): node is ts.CallExpression {
32
+ function isReactiveCallExpression(checker: ts.Checker, node: ts.Node): node is ts.CallExpression {
33
33
  if (!ts.isCallExpression(node)) {
34
34
  return false;
35
35
  }
@@ -49,14 +49,14 @@ function isReactiveCallExpression(checker: ts.TypeChecker, node: ts.Node): node
49
49
  return false;
50
50
  }
51
51
 
52
- function hasReactiveCalls(checker: ts.TypeChecker, node: ts.Node): boolean {
52
+ function hasReactiveCalls(checker: ts.Checker, node: ts.Node): boolean {
53
53
  if (isReactiveCallExpression(checker, node)) {
54
54
  return true;
55
55
  }
56
56
 
57
57
  let found = false;
58
58
 
59
- ts.forEachChild(node, child => {
59
+ node.forEachChild(child => {
60
60
  if (!found && hasReactiveCalls(checker, child)) {
61
61
  found = true;
62
62
  }
@@ -73,7 +73,7 @@ function visit(ctx: FindRemainingContext, node: ts.Node): void {
73
73
  });
74
74
  }
75
75
 
76
- ts.forEachChild(node, n => visit(ctx, n));
76
+ node.forEachChild(n => visit(ctx, n));
77
77
  }
78
78
 
79
79