Quantcast
Channel: Dart - How to create custom types on the fly like in Typescript? - Stack Overflow
Viewing all articles
Browse latest Browse all 4

Answer by Rick Gladwin for Dart - How to create custom types on the fly like in Typescript?

$
0
0

Another way to enforce custom types in Dart is to use assertions in a constructor (when your custom type is being used).

class SomeClass {  final String someVariable  SomeClass(this.someVariable) : <initializer goes here>;}

The initializer (the part after the colon at the end of the constructor) executes before the constructor itself, so custom requirements for your constructor variables can go there.

We use an assertion rather than an exception, since assertions throw errors that we want to catch in our code before production, rather than exceptions that we want to handle at runtime.

Let's say we have a class called Student that has a required field called id. The data type of id is String, but we want to enforce a rule that says a student id must be a 24 character hexadecimal string.

Like you say, the natural choice in TypeScript would be to create a custom type using a string literal or template literal and use that as the argument type when using a student id in a function and when instantiating a Student. Dart doesn't let us create custom data types in the same way (though there is the typedef type alias), but it does let us make assertions about the values of data types when we're trying to use them.

void main() {  const validId = 'a52f5a6d7b46bffe9f5ec08f';  const invalidId = 'thisisnotavalidid';  // student1 throws no errors at development time, compile time, or runtime  final student1 = Student(id: validId, fullName: 'Jimmy Beans');  // student2 throws no errors at development time, but throws an  // AssertionError (in debug mode) at runtime when trying to   // instantiate Student() with an invalid id.  final student2 = Student(id: invalidId, fullName: 'Bimmy Jeans');  print(student1.toString());}// 24 hexadecimal charactersconst String studentIdPattern = r'^[a-f\d]{24}$';class Student {  final String id;  final String fullName;  Student({    required this.id,    required this.fullName,  }) : assert(RegExp(studentIdPattern, caseSensitive: false).hasMatch(id));  @override  toString() {    return "Instance of 'Student': {id: $id, fullName: $fullName}";  }}

Run this code on DartPad

Basically, we declare a regular expression pattern r'^[a-f\d]{24}$' for our 24 character hex string (it can be in the student.dart library/file or in some config file) and add an initializer to the default Student() constructor in the form of an assert() function call.

When the Student() constructor is called, the initializer runs first and checks that the id argument that has been passed in is valid.

Some additional notes regarding your specific example:

  • the regex pattern to use would be r'^(HELLO)|(WORLD)$'
  • that assert() call can be made in other places in the code where it matters what the value of the String type is; it doesn't have to be in an initializer.
  • this method does not throw errors in a linter by default (this is intentional on the part of the Dart devs). Make sure you run your code in a debugger, emulator, or test suite in order to trigger the assertions.
  • for more complicated custom types, there's a way to use Map<KeyClass, ValueClass> as a "custom type" and enums or classes for KeyClass and ValueClass in a way that's comparable to TypeScript types, but it's overkill for simple patterns.

Viewing all articles
Browse latest Browse all 4

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>