Dart can't access property on a generic type function parameter despite providing the type

Viewed 314

I'm trying to specify a function parameter as a generic type T:

enum MyEnum {
  Foo,
  Bar
}

class DbColumn {
  final Function<T>(T value) serializer;
  const DbColumn({this.serializer});
}

class MyClass {

  static final DbColumn rating = DbColumn(
    serializer: <MyEnum>(v) {
      var i = v.index;
    }
  );
}

However when trying to access index on v I get this type error message:

The getter 'index' isn't defined for the type 'Object'. Try importing the library that defines 'index', correcting the name to the name of an existing getter, or defining a getter or field named 'index'.

When I hover over v in VSC it says that it's of type MyEnum.

If I instead remove the generic type and do a cast like this it works as expected:

class DbColumn {
  final Function(dynamic value) serializer;
  const DbColumn({this.serializer});
}

class MyClass {
  static final DbColumn rating = DbColumn(
    serializer: (v) {
      var casted = v as MyEnum;
      var i = casted.index;
    }
  );
}

Why is the generic type not working as expected?

EDIT:

What is even weirder is that this example works too if I put it inside MyClass:

  x<T>(Function(T) c) {}

  y() {
    x<MyEnum>((v) {
      print(v.index); // No error given and type of v is MyEnum
    });
  }

EDIT 2: The same problem happens when overriding methods:

abstract class MyInterface {
  int someFunction<T>(T value);
}

class MyClass implements MyInterface {
  @override
  someFunction<MyEnum>(v) {
    return v.index; // Gives same error and no intellisense happens in VSC
  }
}
1 Answers

Instead of making the function generic, declare the class as generic and it will work as expected. Like this :

enum MyEnum {
  Foo,
  Bar
}

class DbColumn<T> {
  final Function(T value) serializer;
  const DbColumn({this.serializer});
}

class MyClass {

  static final DbColumn<MyEnum> rating = DbColumn(
    serializer: (v) {
      var i = v.index;
      print('Index : $i');
    }
  );
}

void main() {
 MyClass.rating.serializer(MyEnum.Bar);
}

OUTPUT :

Index : 1
Related