Skip to content

Eliminate all 171 as type casts from lib/ code #41

@MelbourneDeveloper

Description

@MelbourneDeveloper

Problem

The project rules in CLAUDE.md explicitly state as is ILLEGAL. Yet there are 171 as type casts across 20 lib/ files in production code.

These unsafe casts can throw TypeError at runtime with no compile-time safety. Every single one needs to be replaced with pattern matching, extension types, or safe conversion helpers.

Full Inventory

By Package

Package File Cast Count
dart_node_mcp lib/src/mcp_server.dart 49
reflux lib/src/selectors.dart 16
dart_node_vsix lib/src/js_helpers.dart 12
dart_node_react_native lib/src/testing.dart 11
dart_node_better_sqlite3 lib/src/statement.dart 10
dart_node_react lib/src/reducer_hook.dart 10
dart_node_react lib/src/testing_library.dart 9
dart_node_better_sqlite3 lib/src/database.dart 7
dart_node_mcp lib/src/stdio_transport.dart 4
dart_node_react lib/src/state_hook.dart 4
dart_node_react_native lib/src/npm_component.dart 6
dart_node_coverage lib/src/runtime.dart 4
dart_node_react lib/src/ref.dart 3
dart_node_vsix lib/src/tree_view.dart 3
dart_node_vsix lib/src/extension_context.dart 3
dart_node_core lib/src/child_process.dart 2
dart_node_react lib/src/special_components.dart 2
dart_node_mcp lib/src/server.dart 2
dart_node_react lib/src/react.dart 1
dart_node_react lib/src/elements.dart 1
dart_node_react lib/src/test_utils.dart 1
reflux lib/src/enhancers.dart 1
dart_node_vsix lib/src/event_emitter.dart 1

Cast Patterns (what to replace with)

There are 5 distinct patterns. Each needs a different replacement strategy:


Pattern 1: JS property access → JSFunction (70+ occurrences)

Current:

final prepareFn = jsDb['prepare']! as JSFunction;

Replace with: Type-safe extension types with external getters

extension type BetterSqliteDb(JSObject _) {
  external JSFunction get prepare;
  external JSFunction get exec;
  external JSFunction get close;
}

Files: mcp_server.dart (30+), database.dart (5), statement.dart (4), js_helpers.dart (10+), testing_library.dart (9), extension_context.dart (3), stdio_transport.dart (4), server.dart (2)


Pattern 2: dartify() result casts (15+ occurrences)

Current:

final map = dartified as Map<Object?, Object?>;
final state = jsState.dartify() as TState;

Replace with: Pattern matching with proper error handling

final map = switch (dartified) {
  final Map<Object?, Object?> m => m,
  _ => throw StateError('Expected Map, got ${dartified.runtimeType}'),
};

Or better: return Result<T, E> per project conventions.

Files: statement.dart (1), mcp_server.dart (2), reducer_hook.dart (6), ref.dart (1)


Pattern 3: Memoization cache unwrapping (16 occurrences)

Current:

R? lastResult;
// ...later...
return lastResult as R;  // nullable → non-nullable

Replace with: Proper null handling with a sentinel or flag

bool hasResult = false;
R? lastResult;
// ...
if (hasResult) return lastResult as R; // or use a wrapper type

Files: selectors.dart (16 occurrences — all identical pattern)


Pattern 4: null as T (4 occurrences)

Current:

return null as T;

Replace with: Proper nullable generic bounds

T? useState<T>(...) // make return type nullable
// or
T useState<T extends Object>(...) // constrain T to non-nullable

Files: state_hook.dart (3), state_hook.dart (1)


Pattern 5: Result type unwrapping (4+ occurrences)

Current:

final success = moduleResult as Success<JSObject, String>;

Replace with: Pattern matching (which nadz supports)

switch (moduleResult) {
  case Success(value: final module): // use module
  case Failure(error: final err): // handle error
}

Files: npm_component.dart (4), enhancers.dart (1)


Priority Order

  1. mcp_server.dart (49 casts) — biggest offender, create extension types for the MCP SDK JS objects
  2. selectors.dart (16 casts) — all identical pattern, one fix applies to all
  3. js_helpers.dart (12 casts) — already a helpers file, perfect place to add type-safe accessors
  4. testing.dart (11 casts) — React Native test utilities
  5. statement.dart + database.dart (17 combined) — SQLite bindings, create extension types
  6. Everything else

Acceptance Criteria

  • Zero as casts in any packages/*/lib/ file
  • All replacements use pattern matching, extension types, or safe conversion helpers
  • All existing tests still pass
  • No new dynamic introduced as a side effect

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions