'Generic callback with generic class as parameter in Dart

I wrote a custom switch class in Flutter to implement generic parameters, I used the flutter_switch package. When I toggle the switch I faced the following error:

type '(String) => void' is not a subtype of type '(dynamic) => void'

or

type '(int) => void' is not a subtype of type '(dynamic) => void'

This error comes from dealing with the onChange callback.

It looks like Dart defines the parameters generic functions as dynamic.

This is my code...

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

class CustomSwitch<T> extends StatefulWidget {
  final T choice1;
  final T choice2;
  final T? value;
  final Function(T)? onChange;

  const CustomSwitch({
    required this.choice1,
    required this.choice2,
    this.value,
    this.onChange,
  });

  @override
  _CustomSwitchState createState() => _CustomSwitchState();
}

class _CustomSwitchState extends State<CustomSwitch> {
  bool value = true;

  @override
  void initState() {
    super.initState();
    value = widget.value == widget.choice1 || widget.value == null;
  }

  @override
  Widget build(BuildContext context) {
    return FlutterSwitch(
      value: value,
      activeText: widget.choice1.toString(),
      inactiveText: widget.choice2.toString(),
      onToggle: (bool value) {
        setState(() {
          this.value = value;

          // here the error happened 
          // type '(String) => void' is not a subtype of type '(dynamic) => void'
          if (widget.onChange != null) { // <--
            widget.onChange!.call(value ? widget.choice1 : widget.choice2);
          }
        });
      },
    );
  }
}

And I use CustomSwitch like this...

CustomSwitch<String>(
    choise1: 'Active',
    choise1: 'Inactive',
    value: 'Active',
    onChange: (value) {
      print('value: $value');
    }
  );

This code throws an error saying:

type '(String) => void' is not a subtype of type '(dynamic) => void'

What's wrong I did?

How to fix it?



Solution 1:[1]

You should also use generics in your _CustomSwitchState, as @jamesdlin said.

class CustomSwitch<T> extends StatefulWidget {
  final T choice1;
  final T choice2;
  final T? value;
  final Function(T)? onChange;

  const CustomSwitch({
    required this.choice1,
    required this.choice2,
    this.value,
    this.onChange,
  });

  @override
  _CustomSwitchState<T> createState() => _CustomSwitchState<T>();
}

class _CustomSwitchState<T> extends State<CustomSwitch<T>> {

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Ibrahim Karahan