-
Notifications
You must be signed in to change notification settings - Fork 2
Description
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-nullableReplace with: Proper null handling with a sentinel or flag
bool hasResult = false;
R? lastResult;
// ...
if (hasResult) return lastResult as R; // or use a wrapper typeFiles: 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-nullableFiles: 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
mcp_server.dart(49 casts) — biggest offender, create extension types for the MCP SDK JS objectsselectors.dart(16 casts) — all identical pattern, one fix applies to alljs_helpers.dart(12 casts) — already a helpers file, perfect place to add type-safe accessorstesting.dart(11 casts) — React Native test utilitiesstatement.dart+database.dart(17 combined) — SQLite bindings, create extension types- Everything else
Acceptance Criteria
- Zero
ascasts in anypackages/*/lib/file - All replacements use pattern matching, extension types, or safe conversion helpers
- All existing tests still pass
- No new
dynamicintroduced as a side effect