Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dart difficult on check Generic Type's type #1997

Closed
hndrbrm opened this issue Nov 30, 2021 · 2 comments
Closed

Dart difficult on check Generic Type's type #1997

hndrbrm opened this issue Nov 30, 2021 · 2 comments
Labels
request Requests to resolve a particular developer problem

Comments

@hndrbrm
Copy link

hndrbrm commented Nov 30, 2021

I need to find the type of the generic type. In which i will use it into some switch case or if else.
But i have difficulty on getting the specified type.

Using '==' and 'is' only return the value false.

The only method i could use is to instantiate some Class to guess the generic type.
And do the if else on that instantiation.

Are there any simplified method to checking the generic type's type?

I simplify the code like this:

void main() {
  List<int> probe = testing();
}

T testing<T>() {
  // The type T is List<int>
  print(T);

  // All this false
  print(T is List<int>);
  print(T is List);
  print(T == List);

  // This is the only method i known to identify correctly
  List<int> x = <int>[];
  print(x is T);

  final List<int> results = [0];
  return results as T;
}
@hndrbrm hndrbrm added the request Requests to resolve a particular developer problem label Nov 30, 2021
@Levi-Lesches
Copy link

Levi-Lesches commented Nov 30, 2021

As you pointed out, T is not a value, it's a type object that's pretty much useless because the type of a type object is Type, not List<int> or anything like that. There are a couple of ways to get around this:

  1. Check the type of the value, not its type. This isn't relevant to your example, because you don't actually take in a parameter, but still a good pattern to be aware of.
void main() => test<String>("Hello World");

void test<T>(T obj) {
  // Instead of this
  if (T is String) print(obj.toLowerCase());
  // do this
  if (obj is String) print(obj.toLowerCase());
}
  1. Do the casting outside the function. This one's more relevant to your example, as it seems you're trying to cast a list into specifically List<int>.
void main() {
  // instead of
  final List<int> value1 = getValue1<int>();
  // do this
  final value2 = List<int>.from(getValue2());
}

/// Tries to return a properly-typed list.
List<T> getValue1<T>() {
  if (T is int) return [0, 1, 2, 3];
  else if (T is String) return ["Hello", "World"];
}

/// Doesn't worry about the precise type of the elements.
List<num> getValue2() => [0.0, 1.0, 2.0, 3.0];
  1. Use a typeOf function:
Type typeOf<X>() => X;

void test<T>() => print(typeOf<T>() == int);
void main() => test<int>();

To be able to represent a complex type (ie, List<int> instead of just List or int), you would need to be able to write List<int> directly as an expression. See #123 -- this will be available when constructor tearoffs are released.

@hndrbrm
Copy link
Author

hndrbrm commented Nov 30, 2021

As you pointed out, T is not a value, it's a type object that's pretty much useless because the type of a type object is Type, not List<int> or anything like that. There are a couple of ways to get around this:

1. **Check the type of the value, not its type.** This isn't relevant to your example, because you don't actually take in a parameter, but still a good pattern to be aware of.
void main() => test<String>("Hello World");

void test<T>(T obj) {
  // Instead of this
  if (T is String) print(obj.toLowerCase());
  // do this
  if (obj is String) print(obj.toLowerCase());
}
2. **Do the casting outside the function.** This one's more relevant to your example, as it seems you're trying to cast a list into specifically `List<int>`.
void main() {
  // instead of
  final List<int> value1 = getValue1<int>();
  // do this
  final value2 = List<int>.from(getValue2());
}

/// Tries to return a properly-typed list.
List<T> getValue1<T>() {
  if (T is int) return [0, 1, 2, 3];
  else if (T is String) return ["Hello", "World"];
}

/// Doesn't worry about the precise type of the elements.
List<num> getValue2() => [0.0, 1.0, 2.0, 3.0];
3. **Use a `typeOf` function**:
Type typeOf<X>() => X;

void test<T>() => print(typeOf<T>() == int);
void main() => test<int>();

To be able to represent a complex type (ie, List<int> instead of just List or int), you would need to be able to write List<int> directly as an expression. See #123 -- this will be available when constructor tearoffs are released.

Thank you for the response sir.
The typeOf trick help me solve the problem.
I hope i can avoid constructor tearoffs 😃

The real scenario i face this problem is, i implement mtproto which is communication protocol used by Telegram app.
The input is bytes from the socket. And i make a function like parser which parse this bytes into the specified DataType class. So in here the T is arbitrary defined by the schema.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
request Requests to resolve a particular developer problem
Projects
None yet
Development

No branches or pull requests

2 participants