Home > Back-end >  How to convert int to double and vice-versa when parsing using num.parse?
How to convert int to double and vice-versa when parsing using num.parse?

Time:01-19

Minimal reproducible code:

void main() {
  print(foo<int>('1'));
  print(foo<double>('1.0'));
  print(foo<double>('1'));
  print(foo<int>('1.0'));
}

T foo<T extends num>(String s) {
  final res = num.parse(s);
  return (T == double ? res.toDouble() : res.toInt()) as T;
}

As you can see I'm manually handling the types. Is there any better way to do it?

CodePudding user response:

I don't see a much better solution. You have a function which changes behavior entirely based on the type argument. Since all you can do with a type argument is subtype-checks, or comparing it to a constant type literal, you need to do something like that.

I'd prefer subtype-checks, because that also allows promotion, but for something limited like this, where there are only four possible types for T, checking Type object equality can also work. There'll just need to be at least one as T before returning.

Either approach also only works for type hierarchies which are finite, and you account for all the possible types. Even here, the current code is not covering <num> and <Never> which are also valid type arguments for the bound num. So, be vigilant.

Maybe, using subtype checks for promotion:

T parse<T extends num>(String source) {
  var value = num.parse(source);
  if (value is T) return value;
  // T is not `num`.
  num d = value.toDouble();
  if (d is T) return d; // T was double.
  try {
    num n = value.toInt(); // Can fail for Infinity/NaN
    if (n is T) return n; // T was int
  } catch (_) {
    // T was `int` after all, so throwing was correct.
    if (1 is T) rethrow; // T was int, but the input was not valid.
  }
  // T was neither num, double, nor int, so must be `Never`.
  throw ArgumentError.value(T, "T", "Must not be Never");
}

Or. using Type object equality:

T parse<T extends num>(String source) {
  var value = num.parse(source);
  switch (T) {
    case num: return value as T;
    case int: return value.toInt() as T;
    case double: return value.toDouble() as T;
    default: 
     throw ArgumentError.value(T, "T", "Must not be Never");
  }
}
  •  Tags:  
  • dart
  • Related