DEV Community

Kilian Schulte
Kilian Schulte

Posted on

Useless Tips for Dart you probably never need. (Part 3)

There exist a lot of great articles highlighting the most useful tips and tricks for Flutter and Dart. They provide great value for both beginners and advanced developers. 

This article is not one of them.

This is about the useless tips, the weird quirks, the boring facts and not needed tricks. They are either so absurd you won't ever need them, or so abstruse you don't wish to need them. But they deserve some love, too.


NoSuchMethod

On our list of things we can use how they are definitely not intended, there is one more we haven't covered yet. In Dart there exists the special noSuchMethod(Invocation i) method that we can override in any custom class. As the name suggests, this method will be called when we try to access an instance member that does not exists.

For example take the class Person with only one method greet() and the overridden noSuchMethod(Invocation i). When we try to do person.hello() instead of throwing an error, our noSuchMethod(Invocation i) gets called with an Invocation object containing all information about the failed invocation, like name of the method or any parameters. It also supports getters and setters. Just note that the person variable has to have the type dynamic otherwise the compiler would complain.

JsObject

Here's my pitch: In Javascript you can access properties of any object either using object['myProp'] or directly via object.myProp. In Dart you can only do one at a time, either with a Map or a custom class that defines myProp as a field or getter/setter. You cannot however access an arbitrary property dynamically and extend an object at runtime. 

Except with noSuchMethod we can. We would have a class that internally just wraps a Map, but externally uses noSuchMethod to catch any property access using getters and setters.

You probably know that there are several reasons why this is a very bad idea to do. For instance it is a poor way to completely disregard any type safety that comes with Dart. So let's do it anyways!

First we define our JsObject class. It just wraps a Map<String, dynamic> and overrides both noSuchMethod and toString.

class JsObject {
  final Map<String, dynamic> map = {};

  @override
  dynamic noSuchMethod(Invocation i) { 
    // TODO
  }  

  @override
  String toString() {
    return map.toString();
  }
}
Enter fullscreen mode Exit fullscreen mode

We then fill in the implementation for noSuchMethod() which is actually pretty straight forward:

@override
dynamic noSuchMethod(Invocation i) { 
  if (i.isGetter) {
    return map[i.memberName.name];
  } else if (i.isSetter) {
    map[i.memberName.name] = i.positionalArguments.first;
  }
}
Enter fullscreen mode Exit fullscreen mode

The .name is just an extension on Symbol to get the actual name. It also strips the tailing = that each setter invocation has. Lastly we need a helper function that creates a new instance of JsObject but returns dynamic to trick the compiler:

dynamic jsObject() => JsObject();
Enter fullscreen mode Exit fullscreen mode

With that here is how to use it:

void main() {
  var o = jsObject();
  o.myProp = "Hello World";
  o.year = 2022;

  print(o.myProp); // prints "Hello World"
  print(o); // prints "{myProp: Hello World, year: 2022}"
}
Enter fullscreen mode Exit fullscreen mode

See the full working code on dartpad.dev

Void Variables

Now on to the finale. All the above tips and tricks were language features designed with a specific purpose which we have crudely disregarded and defaced. But did you know there is actually a feature that is designed to be useless?

The following quote was taken directly from the depths of the Dart Language Specification:

It could be said that the type void is used to help developers maintain a certain self-imposed discipline about the fact that certain objects are not intended to be used.

What a nice way of saying something is useless, isn't it? 

So what does that mean? You most certainly know void as the return type of functions that do not return anything. But you can also use void as a variable type. You can get such a variable by assigning any other variable to a new void variable and thereby making it completely unusable.

 

void main() {
  var myString = "Hello World";
  void myVoidVr = myString;
  // what to do with myVoidVar?
}
Enter fullscreen mode Exit fullscreen mode

Here is what you cannot do with a void variable: You cannot print it. You cannot pass it as a dynamic parameter. You cannot do .toString() or .runtimeType on it. You cannot compare it with == or !=
Here is what you can do: You can cast it back to its original type. That's effectively it. You can also return it from a void function or pass it as a void parameter, but that still leaves you with an unusable void variable. 

So the only thing you can use a void variable for is to throw it away. As per the Language Specification: 

The special type void is used to indicate that the value of an expression is meaningless and intended to be discarded.

So how can we this time completely ignore any good practices or misuse a certain language feature? A feature that is particularly designed to be meaningless and not be used? Well, we use it of course:

First let's define a normal void Function(). However instead of returning nothing, we return some value which we assign to void :

void getText() {
  String str = "Hello World";
  void result = str;
  return result;
}
Enter fullscreen mode Exit fullscreen mode

We also define a function that accepts a value of type void and casts it back to String. This will of course throw if the value is not actually a String.

void printText(void text) {
 var str = text as String;
 print(str);
}
Enter fullscreen mode Exit fullscreen mode

Finally we combine these two methods:

void main() {
 var text = getText();
 // text is void and cannot be used for anything
 printText(text);
}
Enter fullscreen mode Exit fullscreen mode

Why would you do it? Maybe you want to torture your coworkers. Maybe you want to torture yourself. For everybody else:

Please never use it!


Do you know any more useless or abstruse tricks? Please leave a comment.

Also I wanted to experiment with something you won't read everyday in contrast to the thousands of 'Tips & Tricks' articles out there. So please show some love in case you liked it or give some feedback.

Top comments (1)

Collapse
 
mvolpato profile image
Michele Volpato

When you are code reviewing some bullshit function from your coworker you could edit the code and assign the result from that function to a void variable. Just to make it clear how wrong your coworker is.