I'm using a linter package to practice strict coding, however, I can't figure out how to solve this warning. The code is working but I just want to understand this warning and how to solve this. I'm new to flutter by the way. Hope someone can answer my question. TIA!
Actual Code
PS: sorry, unable to display image because of restriction
The lint you're getting is from pedantic's always_specify_types property. It means that you have to specify the type of the variable. In your case, you need to specify the type of your MapEntry. By default, MapEntry's key and value's type will be dynamic. You'd have to specify it as MapEntry<int,Tab>.
In simple terms, instead of:
var number = 12; // dynamic means that the type can be anything (Eg: String, int, etc.)
do:
int number = 12;
Related
For example, I have Map<int, int> m;. Then I can write down m['hello'] without any compile-time error, but of course, cannot find any element at runtime. I hope it will produce an error (or warning) at compile-time or lint time.
This is a big problem in many cases. For example, when I refactor Map<A, int> m into Map<B, int> m, I want to have compile-time errors for all accesses like m[some_var_of_type_A], instead of no compile-time errors and suddenly it explodes at runtime. As another example, the de-serialized JSON is of type Map<String, ...> but the key is actually a int. So it is tempting to do var userId=42; deserializedJson[userId] but only to find errors. Actually need to do deserializedJson[userId.toString()].
You know, dart's type system is so strong (even null safe!), and I really enjoy it since it catchs a LOT of bugs at compile-time. So I hope this problem can also be addressed at compile-time.
Thanks for any suggestions!
There currently is no lint to warn about doing lookups on a Map with arguments of the wrong type. This has been requested in https://github.com/dart-lang/linter/issues/1307.
Also see https://github.com/dart-lang/sdk/issues/37392, which requests a type-checked alternative to Map.operator []. In the meantime, Dart's extension mechanism allows anyone to easily add such an alternative themselves. For example, package:basics provides a type-checked Map.get extension.
NOTE:
The original answer was wrong and has been edited to:
point out the right/better answer
explain why the original answer was wrong
Thank you #jamesdlin for pointing this out.
Better answer
As pointed by #jamesdlin in his answer, the lint rule mentioned in the question has been requested in the flutter Github issues, and not in production yet.
Original Answer (wrong but kind of related to the question)
Why it is wrong:
The question was asking about the lint rule when using an index of Map. The answer however gave the lint rule about initializing a map using the wrong index (By the wrong index, I mean different data type).
Below is the answer:
There is a lint rule for this.
For example, if you define a Map like this ->
final Map<String, String> m = {
1: 'some random value',
};
It shows an error right away and this won't compile. This is the error ->
Error: A value of type 'int' can't be assigned to a variable of type 'String'.
1: 'error because index is of type String but assigned value is of type int',
^
Error: Compilation failed.
See the official docs where this lint rule, map_key_type_not_assignable is defined.
I have tested this in dartpad and vs code. Both IDEs show this error.
There could be some issues in your IDE configuration if you're not seeing this lint error.
As for your question, there is already a lint rule for this as explained above.
there is one thing I can't quite wrap my head around concerning null-safety in Dart, and that concerns how to safely retrieve values from Map<String,dynamic> (I've read the FAQ from the Dart docs).
Basically, the following code in the DartPad with null-safty enabled is valid:
void main() {
int i;
Map<String, dynamic> map = {"key": 1};
i = map["key"];
print(i);
}
Which I do not understand. Why can I assign map["key"] to i without the compiler shouting at me? From the docs:
Code should be safe by default. If you write new Dart code and don’t
use any explicitly unsafe features, it never throws a null reference
error at runtime.
But exactly this is happening. If, in the code above, the key is not in the map, or contains some random type, the program will crash on runtime, which I though is what should never happen with null safety.
I'm particular interested in this since I'm writing a Flutter app and don't understand how to properly deserialize the JSON data I fetch from the DB (try..catch? Special syntax like ??= ?). Even though I don't have the 'non-nullable' language feature enabled (I can't even write int? val without getting a warning), the compiler does not seem to mind that I assign nullable values to non-nullable variables, and will happily crash on runtime if they are null.
Basically, my question does not only concern null-safety, but the type system in general, since from my understanding it shouldn't be possible to assign a dynamic value to an int variable, but obviously this works with Map. Any explanation is greatly appreciated!
A dynamic variable can contain any data type, "dynamic" keyword is used when you don't know the specific data type that might be returned.
and what you're actually doing here:
i = map["key"];
is assigning a "dynamic" variable to an "int" variable and since dynamic in this case the value in the key/value pair of your Map is an integer which matches the data type "int" of variable "i" it won't crash because of type inference done at runtime and not compile time. if the "dynamic" variable was a String it would crash at runtime because of a type mismatch. Hope this is explanatory.
I don't know if this was happening before my switch to the beta channel in Flutter but I don't understand why this is an error. A List is an Iterable right? I took the example from the official docs.
Iterable<int> example() {
Iterable<int> iterable = [1, 2, 3];
return iterable;
}
VSCode marks the list with a red underline telling me:
A value of type 'List<int>' can't be assigned to a variable of type 'Iterable<int>'.
Try changing the type of the variable, or casting the right-hand type to 'Iterable<int>'. dart(invalid_assignment)
I think the problem is the as is more of an assertion and not a cast. To perform the cast you need to use the .cast function:
https://api.flutter.dev/flutter/dart-core/List/cast.html
E.g.
# ...
.toList().cast<Iteratable<File>>()
You can read more from this answer covering when/why to cast: https://stackoverflow.com/a/49542401/931209
Alternatively, you can probably call the iterator property on the list (but the above is likely the more correct solution):
https://api.dart.dev/stable/2.10.4/dart-core/Iterable/iterator.html
I don't know what was the problem but I tried removing the Flutter and Dart extensions from VSCode, restarting the whole computer and installing them again (in that order) and now the same code works!
As BeefPapa said in a comment, the code was absolutely correct.
Who knows what happened.
You need convert again the results to List adding .toList() in the end because Dart changes the type of the variable.
I have used xCode 6.3's convertor to convert my project to swift 1.2,
After that i was still left with many errors, but i fixed them all manually.
Now when i compile i get:
<unknown>:0: error: '[Set<T>]' is not convertible to 'Hashable'.
The only place i use Set is:
var productID:Set<NSObject> = [subscriptionId]
var productsRequest:SKProductsRequest = SKProductsRequest(productIdentifiers: productID )
I have tried cleaning the project and also tried deleting the DerivedData folder, but that didn't help.
I have searched but i couldn't find anyone with the same problem.
Anyone know how to solve this?
This won’t be a problem with derived data. It looks like where previously you had an NSArray (probably of NSSet), you now have an Array of Set. Presumably you’re then trying to do something like use that value to key a dictionary type. In 6.3, several API calls that previously returned NSSomething now return native Swift types.
Swift Arrays aren’t hashable (because they might contain something that isn’t hashable). NSArrays are (though not always in a helpful way, depending on what they contain, so be wary).
Bear in mind, with type inference, that your explicit use of Set or Array won’t be the only places you might have a set. If you call a function that returns an array of sets, and you assign that value like so: let thing = funcThatReturnsArrayOfSets() then you will have a [Set<whatever>] even without explicitly writing that type in your code.
To fix this, you need to find the line where you’re getting the error, look at the types involved, then trace back to where those variables were declared. Option-click all the things to see what types they are.
Let's say I get two instances in my code and I don't know their types. How to check it?
If in Java, I can use this code:
a.getClass() == b.getClass()
But in Dart, I can't find similar methods. Although there is the dart:mirrors providing reflect(instance) function, which may let me do it, but I'm not sure if that's a correct solution since it looks complicated.
a.runtimeType == b.runtimeType
I think dart:mirrors (reflection) API helps you. Look at this page :
http://blog.dartwatch.com/2012/06/dartmirrors-reflection-api-is-on-way.html
Also you can look this question(with runtime solution)
How do I get the qualified name from a Type instance, in Dart?
if you want to compare a and b you can use
if(a.runtimeType == b.runtimeType);
but if you want to confirm that a is the type you want you need to do this
if(a.runtimeType.toString()=="DivElement");//a is a div for instance
because runtimeType's value is not a string