typescriptdarttypescustom-type

Dart - How to create custom types on the fly like in Typescript?


I want to create a custom type in Dart like I would do in typescript. This type should be a subtype of String, accepting only some values.

For example, in Typescript I would do:

type myType = 'HELLO' | 'WORLD' | '!'

How can I do the same stuff in Dart?


Solution

  • Original Answer (see updates below): This isn't possible at the language level in Dart - There are a couple alternatives though.

    You could simply define an enum along with a method to derive a string from your enum:

    enum MyType {
      hello,
      world,
      exclamationPoint,
    }
    
    String myTypeToString(MyType value) {
      switch (value) {
        case MyType.hello: 
          return 'HELLO';
        case MyType.world: 
          return 'WORLD';
        case MyType.exclamationPoint: 
          return '!';
      }
    }
    

    Update 2: In Dart 3 we have yet another way, using sealed classes:

    sealed class MyType {
      @override
      String toString() {
        return switch (this) {
            Hello() => "Hello",
            World() => "world",
            Exclamation() => "!"
        };
      }
    }
    
    class Hello extends MyType {}
    class World extends MyType {}
    class Exclamation extends MyType {}
    

    https://dart.dev/language/class-modifiers#sealed


    Old Update: Now that Dart 2.17 supports declaring methods on enums, it's possible to do this a bit more cleanly than in my original answer:

    enum MyType {
      hello,
      world,
      exclamationPoint;
    
      @override
      String toString() {
        switch (this) {
          case MyType.hello: 
            return 'HELLO';
          case MyType.world: 
            return 'WORLD';
          case MyType.exclamationPoint: 
            return '!';
        }
      }
    }
    

    Or you could define a class with three named constructors, and override the toString method:

    class MyType {
      final String _value;
    
      MyType.hello(): _value = 'HELLO';
      MyType.world(): _value = 'WORLD';
      MyType.exclamationPoint(): _value = '!';
    
      @override
      String toString() {
        return _value;
      }
    }
    
    // Usage:
    void main() {
      final hello = MyType.hello();
      final world = MyType.world();
      final punctuation = MyType.exclamationPoint();
    
      // Prints "HELLO, WORLD!"
      print("$hello, $world$punctuation");
    }