Are optional parameters in null-safe dart automatically nullable? If no, is there an easy way to make my code null-safe? - dart

I noticed a few more users on the Dart/Flutter tags trying out null safety in the newer Dart SDK versions and I started reading up about it, starting with this Medium article.
I noticed that in all of their examples they use positional, required arguments. But how will null-safety work with optional parameters, both positional and named?
Optional parameters are inherently null so does this mean that all optional parameters will have to be declared with the nullable variable declaration syntax with null-safety enabled? It seems like only a minor inconvenience to add ?, but it could break a lot of code that uses optional parameters liberally. Will dart be able to make an exception for optional parameters(knowing that they will always be nullable) so that such large changes can be avoided? or is there an easier alternative to making my code null-safe compatible that avoids these changes?

In null safe Dart, actual optional parameters must either have a default value, or they must be nullable (in which case they have the default default-value of null).
There is no exception. Because of default values, optional parameters are not inherently nullable.
You should not expect existing code to work with null safety as-is. You are expected to do a migration of the code to be null safe.
The easiest way to make your code null safe is to run dart migrate on your project. It will insert most of the necessary ?s for you.

Related

Confused about the benefit of null safety

As far as I know, the benefit of null safety is to prevent the accidental assignment of null to a variable and then later doing something like nullable_variable.foo() which would cause a runtime error.
But even when I am not using null safety, I do get a compilation error when calling a method on an object that have the null value, for example I get a compilation error when doing the following:
class Student
{
void foo()
{
}
}
void main()
{
Student? s1 = null; // not using null safety here
s1.foo(); // this causes a compilation error
}
So what I mean is that I am still getting the benefit of null safety without using null safety, so what is the point of null safety?!
You are using "Null Safety". The Null Safety feature is what allows you to write Student? to begin with, to distinguish between types which allow null and types which do not.
With that knowledge, the compiler can disallow calling methods on a nullable type that are not also allowed on null. And it does.
You get a compile-time error for something that, without Null Safety, you'd have written Student s1 = null;, had that accepted by the compiler, and gotten a runtime error.
The promise of Null Safety is that you get compile-time errors instead of runtime errors. The cost is that you need to check for null (or do unsafe casts to non-null types, but checking is better), and you have to explicitly include null in types where you do want to accept null.
To say in simple terms using your above example
Student s1 = null is valid without null safety which will lead to various other problems , Especially when you are dealing with the huge project.
So when you opt into null safety, types in your code are non-nullable by default, meaning that variables can’t contain null unless you say they can.
With null safety, your runtime null-dereference errors turn into edit-time analysis errors.
Where as in null safety , you can't have somethin like Student s1 = null,
Instead use Student? s1 = null. Meaning you are explicity saying the compiler that you are aware that this value can be null and take care of it in the entire program.
So flutter accepts that and helps you through by giving features like ! ?? ?.
To summarize , the null safety was introduced because,
Developers like statically-typed languages like Dart because they enable the type checker to find mistakes in code at compile time, usually right in the IDE. The sooner you find a bug, the sooner you can fix it. When language designers talk about “fixing null reference errors”, they mean enriching the static type checker so that the language can detect mistakes
And Dart is designed to run on an end-user’s device. If a server application fails, you can often restart it before anyone notices. But when a Flutter app crashes on a user’s phone, they are not happy. When your users aren’t happy, you aren’t happy.
Please follow the below links to dive deep into the null-safety concept.
https://dart.dev/null-safety
https://dart.dev/null-safety/understanding-null-safety

"The operand can't be null", even though the documentation of the employed method clearly specifies a possible null-return?

I'm using an IO Library which returns a Future<String>. While, yes, the returned type is String instead of String?, the documentation of that library method clearly states that null will be returned if the operation fails (Instead of throwing an exception). Therefore, I need to check for null myself and handle the exception throwing myself.
However, if I check the return value for null, Dart tells me that the operand can't be null and I therefore shouldn't be checking for it.
What should be done in such a case?
As is discussed in the comments, this issue can be seen when using legacy code that hasn't been updated for Dart 2.12 with null-safety.
In previous versions of Dart (pre-2.12), types did not have to have a trailing ? symbol to signify that a value may be null. A Future<String>, for example, could easily complete with a value of null.
To avoid this, make sure all your dependencies are null-safe.

Does dart have an equivalent to C# discards?

C# discards prevent allocation of values not needed. Is there something similar in dart? I saw a lot of people use the underscore as if it were a discard, but using two at the same time (like this (_, _) => method() will say the variable _ is already defined.
Dart does allow you to use the same discard operator as C#. You can define a variable or final with a name of _. This works well with the rule avoid-ignoring-return-values (Dart Code Metrics) Importantly, if you name the variable with this, you will not encounter the warning unused-local-variable. However, there is another code rule called no_leading_underscores_for_local_identifiers. You can safely turn this off as long as you don't have someone in your team that has a habit of prefixing variable names with an underscore.
Ignoring the return value
Discarding the return variable
Unfortunately, it doesn't work the same way as C# because it involves an assignment, and you cannot assign two different types to it. You need to declare it as an Object?

should I give type?

Should I give type when creating variable?
Any downside for just declaring the keyword "var"?
Any difference between these two?
var a = 0;
int a = 0;
Pros/Cons
ONGOING WORK
Best Practices
It's recommended to use var or final keyword, without specifying type annotation, and implicitly infer type for known local variables. Otherwise it's recommended to specify type annotations. As for dynamic keyword, it should be used very sparingly in specific use-cases, when you're doing manual type checking. For example print(myVariable is SomeType).
omit_local_variable_types Dart linter rule encourages omitting type annotation for known local variables. always_specify_types encourages specifying type annotations for cases that don't fall into the scope of the former linter rule.
1. Style guide for Flutter repo
1.1 avoid using var
All variables and arguments are typed; avoid "dynamic" or "Object" in
any case where you could figure out the actual type. Always specialize
generic types where possible. Explicitly type all list and map
literals.
This achieves two purposes: it verifies that the type that the
compiler would infer matches the type you expect, and it makes the
code self-documenting in the case where the type is not obvious (e.g.
when calling anything other than a constructor).
Always avoid "var". Use "dynamic" if you are being explicit that the
type is unknown, but prefer "Object" and casting, as using dynamic
disables all static checking.
2. Dart Lint Rules
2.1 omit_local_variable_types
CONSIDER omitting type annotations for local variables.
Usually, the types of local variables can be easily inferred, so it
isn't necessary to annotate them.
2.2 always_specify_types
DO specify type annotations.
Avoid var when specifying that a type is unknown and short-hands that
elide type annotations. Use dynamic if you are being explicit that the
type is unknown. Use Object if you are being explicit that you want an
object that implements == and hashCode.
References
You can refer to Style guide for Flutter repo, full list of Dart's Linter Supported Lint Rules, and Effective Dart's Style Guide.
Note, Style guide for Flutter repo is used among flutter community and takes precedence over LinterRules and Effective Dart's Style Guide especially within repo contributions. From what I've seen, Style guide for Flutter repo is more of a superset Style Guide that should honor Dart Linter rules.
There isn't any difference between the two statements you gave.
And I don't see any downside to only declare the keyword "var", unless that your code might become a bit more difficult to read. On the other side, specifying the type might become a bit redundant sometimes.
But this is really just a question of taste 😄
I advise you to pick between those two, and be consistent in your code.
If you choose to always specify the type, you can use always_specify_types in your file analysis_options.yaml :
https://dart-lang.github.io/linter/lints/always_specify_types.html

Kotlin- Extension functions and platform types?

I want to add two extension functions to ResultSet that gets a value as a LocalDate.
fun ResultSet.getLocalDate(colName: String) = getDate(colName)?.toLocalDate()
fun ResultSet.getLocalDate(colIndex: Int) = getDate(colIndex)?.toLocalDate()
The problem is getDate() returns a Date!, and obviously I could get a null error without the ?. call before toLocalDate(). But then anyone using this extension must use the result as a LocalDate? rather than a LocalDate!.
Is there any way I can maintain the platform type for consistency's sake? And let the user of the extension function decide if it is allowed to be nullable or not? Or am I looking at this wrongly as an inconvenience rather than a feature?
Look at it from a different angle: if you could make your functions return a value of platform type LocalDate!, Java unsafe nullability would spread to the functions usages in your Kotlin code: they would return null at any time, possibly unexpected to the caller using the return value as non-null.
Kotlin, in turn, is null-safe and it won't allow passing null silently to somewhere where it will cause an NPE. Instead, every value is either passed around as nullable or passes non-null check or assertion.
Platform types are non-denotable in the language, this is just a way of dealing with unsafe Java nullability (simply treating all Java values as nullable wouldn't work). They provide you a way to state that you believe that this call to Java code won't return null: when you treat T! as T, an assertion is generated to check it. Otherwise you work with platform type T! as with nullable T?.
Null safety is one of the key points in Kotlin language design, and it makes you decide for each value in your Kotlin code whether it is nullable or not.
You have two options for API design:
Return a non-null value, checking the nullability inside your function
Return nullable value and thus warn the caller about possible null
However, if a function has semantics allowing the caller to assume that it won't return null in some conditions, you can make a wrapper function that makes the assertion. This is feasible if coupled with additional logic or fallback, otherwise it will hardly be more concise than the assertion (!!) at call site.

Resources