letsar/binder

type 'String' is not a subtype of type 'Null' in type cast

Closed this issue · 2 comments

erf commented

If i try to write a String to a StateRef which was initialized with a null value and without type declared, i get the following exception:

Restarted application in 302ms.

�[38;5;248m════════ Exception caught by widgets library ═══════════════════════════════════�[39;49m
�[38;5;244mThe following _CastError was thrown building BinderScope(overrides: [], observers: [], state: BinderScopeState#a3935(LogicRef<StateTest>: Instance of 'StateTest', StateRef<Null>: HELLO)):�[39;49m
type 'String' is not a subtype of type 'Null' in type cast

�[38;5;244mThe relevant error-causing widget was�[39;49m
�[38;5;248mBinderScope�[39;49m
�[38;5;244mWhen the exception was thrown, this was the stack�[39;49m
�[38;5;244m#0      BinderContainerMixin.fetch�[39;49m
�[38;5;244m#1      StateRef.read�[39;49m
�[38;5;244m#2      Aspect.shouldRebuild�[39;49m
�[38;5;244m#3      InheritedBinderScope.updateShouldNotifyDependent.<anonymous closure>�[39;49m
�[38;5;244m#4      Iterable.any (dart:core/iterable.dart:356:15)�[39;49m
�[38;5;244m...�[39;49m
�[38;5;248m════════════════════════════════════════════════════════════════════════════════�[39;49m

Here is the failing example:

import 'package:flutter/material.dart';
import 'package:binder/binder.dart';

final stateRef = StateRef(null);

final stateTestRef = LogicRef((scope) => StateTest(scope));

class StateTest with Logic {
  const StateTest(this.scope);

  @override
  final Scope scope;

  void sayHello() {
    write(stateRef, 'HELLO');
  }
}

void main() {
  runApp(BinderScope(child: MyApp()));
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Binder test'),
      ),
      body: Center(
        child: Column(
          children: [
            Text(context.watch(stateRef) ?? ''),
            TextButton(
              child: Text('Say hello'),
              onPressed: () {
                context.use(stateTestRef).sayHello();
              },
            )
          ],
        ),
      ),
    );
  }
}

If i set the type of the StateRef like below, it works ok:

final stateRef = StateRef<String>(null);

Is this expected behavior?

Maybe related to:
#8

Yes this is the expected behavior, it behaves like any generic type in dart. If you don't set the type, dart will infer it from the value passed.
In the case you mentioned, null is of type Null and dart think that is what you want.

erf commented

Ah ok.