iDecode
iDecode

Reputation: 29016

How to return two specific types from a generic method?

T getValue<T>(int i) {
  if (T == String) return '$i'; // Error
  return i; // Error
}


void main() {
  var s = getValue<String>(1);
  var i = getValue<int>(1);
}

I want getValue to return string if T is String and int otherwise. How to do that?

Upvotes: 0

Views: 118

Answers (2)

lrn
lrn

Reputation: 71873

You can't restrict the type parameter to just int or String, so it will have to accept more than that (at least their least common supertype, Object, so basically any type).

It's not a particularly helpful way to code. It's possible, but not recommended:

T getValue<T>(int i) {
  if (i is T) return i;
  return "$i" as T;
}

This will return the int if T allows it (so T being any of int, or a super type of int, which is num, Object, dynamic or void, or any number of Comparable<X> wrappings around any any of those supertypes), and otherwise try to return a string. That will fail with a type error unless T is String (since we've already ruled out all supertypes of String). You can still call it as getValue<bool>(42) and watch it fail, so the type argument doesn't help with correctness.

It's not particularly effective. I'd rather do:

dynamic getValue(int i, {bool toString = false}) {
  if (toString) return "$i";
  return i;
}

and call it as:

  String x = getValue(42, toString: true); // Add `as String` if you disable downcasts.
  int y = getValue(42); // And `as int` here.

The type parameter is really just making things harder. You are going to cast or type-check the result anyway, so might as well do it at the call point, rather than introduce type variables that aren't actually preventing misuse anyway.

(I'd probably just do two different functions, but I assume that there is a reason for wanting one function).

Upvotes: 1

Christopher Moore
Christopher Moore

Reputation: 17151

As I mentioned in the comments, I don't see any way that you could use your generic as the return type of your getValue function. Even assuming the return under the if statement worked, there is nothing that can be done about trying to return int i when List is passed as the type. You'll be trying to return an int as a List.

If you change it to dynamic, your code will work fine as it's just using the generic as another parameter.

dynamic getValue<T>(int i) {
  if (T == String) return '$i';
  return i;
}


void main() {
  var s = getValue<String>(1);
  var i = getValue<int>(1);
}

Upvotes: 0

Related Questions