class Point {
int x;
int y;
Point(this.x, this.y);
Point.zero()
: x = 0,
y = 0;
Point.fromJson({required Map<String, int> json})
:x = json['x'], //Error : `The initializer type 'int?' can't be assigned to the field type 'int'`
y = json['y']; // Error :`The initializer type 'int?' can't be assigned to the field type 'int'`
}
As you can see the argument json here is Map<String , int> so why am getting this error here.When both are non-nullable here ?
Why compiler assuming json['x'] = int? ?
Because the [] operator on Map returns a nullable by spec:
V? operator [](Object? key)
The value for the given key, or null if key is not in the map.
https://api.dart.dev/stable/2.15.1/dart-core/Map/operator_get.html
So if you are asking for a key that is not in your Map you will get a null value back and not an exception.
If you are 100% sure json['x'] will always work and want the application to crash in case this is not the case, you can use json['x']!. Alternative, you need to provide default values or other type of handling in case these values is not in the map.
Related
A value of type 'String?' can't be assigned to a variable of type 'String'.
Try changing the type of the variable, or casting the right-hand type to 'String'.
This error message i got when i run this code.
This is a simple user input code on dart.
var person = ['abc', 'qwe', 'dfg'];
stdout.write('Enter Index : ');
String p = stdin.readLineSync(); //Error
int per = int.parse(p);
per > person.length
? stderr.write('Index does not exist')
: stdout.write('Person ${person[per]}');
}
Seems like readLineSync() returns nullable type. But you declare variable p as non-nullable. Either declare p as nullable: String? instead of String or make readLineSync() return default value if null:
String p = stdin.readLineSync() ?? "";// will return empty String if method readLineSync() returns null.
First of all check the null safety documentation, you'll learn everything you need to know
https://dart.dev/null-safety/understanding-null-safety
readLineSync returns a value of Type String? Meaning the return value must be a nullable String.
p is of type String and therefore expects a String (not a nullable String). the trick here is to cast stdin.readLineSync() to String:
String p = stdin.readLineSync() as String;
String p = stdin.readLineSync()!; #shorthand syntax
On top of that, your code needs some improvements. What if p can't be cast into an integer? One way to handle this is to add a try block and catch any FormatException.
This question already has answers here:
What is Null Safety in Dart?
(2 answers)
Closed 1 year ago.
After defining a map (with letters as keys and scrabble tile scores as values)
Map<String, int> letterScore //I'm omitting the rest of the declaration
when I experiment with this function (in DartPad)
int score(String aWord) {
int result = 0;
for (int i = 0; i < aWord.length; ++i) {
result += letterScore[aWord[i]];
}
return result;
}
I consistently get error messages, regardless of whether I experiment by declaring variables as num or int:
Error: A value of type 'int?' can't be assigned to a variable of type
'num' because 'int?' is nullable and 'num' isn't [I got this after declaring all the numerical variables as int]
Error: A value of type 'num' can't be returned from a function with
return type 'int'.
Error: A value of type 'num?' can't be assigned to a variable of type
'num' because 'num?' is nullable and 'num' isn't.
I understand the difference between an integer and a floating point (or double) number, it's the int vs int? and num vs num? I don't understand, as well as which form to use when declaring variables. How should I declare and use int or num variables to avoid these errors?
Take this for example:
int x; // x has value as null
int x = 0; // x is initialized as zero
Both the above code are fine and compilable code. But if you enable Dart's null-safety feature, which you should, it will make the above code work differently.
int x; // compilation error: "The non-nullable variable must be assigned before can be used"
int x = 0; // No Error.
This is an effort made from the compiler to warn you wherever your variable can be null, but during the compile time. Awesome.
But what happens, if you must declare a variable as null because you don't know the value at the compile time.
int? x; // Compiles fine because it's a nullable variable
The ? is a way for you tell the compiler that you want this variable to allow null. However, when you say a variable can be null, then every time you use the variable, the compiler will remind you to check whether the variable is null or not before you can use it.
Hence the other use of the ?:
int? x;
print(x?.toString() ?? "0");
Further readings:
Official Docs: https://dart.dev/null-safety/understanding-null-safety
Null-aware operators: https://dart.dev/codelabs/dart-cheatsheet
Now I am define a enum in dart like this:
enum LoginType {
PHONE,
WECHAT
}
extension ResponseStatusExtension on LoginType{
static const statusCodes = {
LoginType.PHONE: 1,
LoginType.WECHAT: 2,
};
int get statusCode => statusCodes[this];
}
I am upgrade to flutter 2.0.1 and support null safety and now it tell me :
A value of type 'int?' can't be returned from the function 'statusCode' because it has a return type of 'int'.
but I want to make it return a default not null value to make the code rubust and did not have to handle null when using this enum. what should I do to make it return a default value? is it possible?
The reason for your error is that the [] operator on Map is nullable since it has this behavior:
The value for the given key, or null if key is not in the map.
https://api.dart.dev/stable/2.12.2/dart-core/Map/operator_get.html
If you are sure your Map always contains the requested key you can add a ! after the use of [] operator like this:
int get statusCode => statusCodes[this]!;
This will make a null-check at runtime and fail if a null value is returned. But this should not be a problem if you are sure null is never returned from the Map.
Bonus tip
If you want to be able to have a default value returned from a Map in case the Map does not contain a given key you can add the following extension to Map:
extension MapDefaultValue<K, V> on Map<K, V> {
V get(K k, V defaultValue) => containsKey(k) ? this[k] as V : defaultValue;
}
Notice that defaultValue must be a compatible type for key in the Map so you cannot use null as defaultValue if null are not allowed as a value in the Map.
I am trying to assign to an int value, however, I get this error:
A value of type 'int?' can't be assigned to a variable of type 'int'
The line causing this compile-time error is the following:
int number = someFunction();
The problem here is that the value returned from someFunction is nullable and trying to assign that value to a non-nullable variable is a compile-time error (null-safety was introduced in Dart 2.7).
You need to check for null using a != null condition.
Example
void exampleFunction<T>(T? input) {
T result = input; // <- ERROR here
print(result);
}
In this example, input is nullable and thus cannot be assigned to the non-nullable variable result.
Solution
The given example problem can be solved like this:
void exampleFunction<T>(T? input) {
if (input != null) {
T result = input;
print(result);
}
}
I've recently came across this question How do I solve the 'Failed assertion: boolean expression must not be null' exception in Flutter
where the problem comes from a should be invalid code that gets treated as valid.
This code can be summarized as :
int stuff;
if (stuff = null) { // = instead of ==
}
But why does this code compiles ? As the following will not.
int stuff;
if (stuff = 42) {
}
With the following compile error :
Conditions must have a static type of 'bool'.
So I'd expect out of consistency that if (stuff = null) to gives the same error.
null is a valid value for a bool variable in Dart, at least until Dart supports non-nullable types.
bool foo = null;
or just
bool foo;
is valid.
Therefore in the first case there is nothing wrong from a statical analysis point of view.
In the 2nd case the type int is inferred because of the assignment, which is known to not be a valid boolean value.
bool foo = 42;
is invalid.
When you say var stuff; with no initial value it is giving stuff a static type of dynamic. Since dyamic might be a bool, it's legal to assign null to a variable of type dynamic, and it's legal to use a possibly null bool in a conditional, the compiler doesn't flag this. When you say int stuff; the compiler knows that stuff could not be a bool. The reported error in that case is cause by the static type of stuff, not the assignment to null.
Edit: Got the real answer from someone who knows how to read the spec.
The static type of an assignment expression is the right hand side of the assignment. So the expression stuff = null has the static type of Null which is assignable to bool.
The reasoning is that the value of an assignment is the right hand side, so it makes sense to also use it's type. This allows expressions like:
int foo;
num bar;
foo = bar = 1;
Commonly assignment operation returns the value that it assigns.
int a = 0;
print(a = 3);//Prints 3
So,
When stuff = null,
'stuff = null' returns null. if statement needs a boolean .null is a sub-Type of boolean.
if(null){}
is valid
When stuff = 42,
'stuff = 42' returns 42. if statement needs a boolean .42 is not a sub-Type of boolean.
if(42){}
is not valid