You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Dart如何像TypeScript一样动态创建自定义类型?

在Dart中实现类似TypeScript的字符串字面量联合类型

嘿,这个需求我太懂了!Dart里没法像TypeScript那样直接写type myType = 'HELLO' | 'WORLD' | '!'这种简洁的字面量联合类型,但有几种替代方案能达到甚至超越TS的类型安全效果,我给你逐一说明:

方案一:使用枚举(最推荐,简单直接)

这是最贴合你需求的方式,编译时就会严格限制取值,而且代码可读性拉满:

enum MyType {
  hello('HELLO'),
  world('WORLD'),
  exclamation('!');

  // 存储对应的字符串值
  final String value;
  const MyType(this.value);
}

使用的时候也很方便:

void main() {
  // 正确用法
  final validValue = MyType.hello.value; // 拿到 'HELLO'
  
  // 编译时就会报错,不能传其他值
  // final invalidValue = MyType.invalid;
}

枚举的优势在于:编译时检查+运行时安全,完全不用担心传入非法值,而且IDE会自动提示可选的取值。

方案二:密封类+工厂构造函数(适合需要额外行为的场景)

如果你需要给这些特定字符串值添加专属方法或逻辑,密封类(Sealed Class)是更好的选择:

// 密封类,限制只能在当前文件内继承
sealed class MyType {
  final String value;
  const MyType(this.value);

  // 工厂构造函数,根据字符串返回对应的子类实例
  factory MyType.fromString(String input) {
    switch (input) {
      case 'HELLO':
        return Hello();
      case 'WORLD':
        return World();
      case '!':
        return Exclamation();
      default:
        throw ArgumentError('无效的MyType值:$input');
    }
  }
}

// 每个取值对应一个子类,可以添加自定义方法
class Hello extends MyType {
  const Hello() : super('HELLO');

  void greet() {
    print('$value, 你好!');
  }
}

class World extends MyType {
  const World() : super('WORLD');
}

class Exclamation extends MyType {
  const Exclamation() : super('!');
}

使用示例:

void main() {
  final hello = MyType.fromString('HELLO');
  if (hello is Hello) {
    hello.greet(); // 输出: HELLO, 你好!
  }

  // 传入非法值会直接抛出错误
  // MyType.fromString('INVALID');
}

这种方式的灵活性更高,除了类型安全,还能给不同取值赋予独特的行为。

方案三:类型别名+运行时断言(临时简单场景)

如果只是想临时约束,不想创建枚举或类,可以用类型别名结合断言,但要注意:编译时不会检查,只能在运行时保证安全:

// 定义类型别名,本质还是String
typedef MyType = String;

// 通过工厂函数创建合法的MyType
MyType createMyType(String input) {
  const allowedValues = {'HELLO', 'WORLD', '!'};
  if (!allowedValues.contains(input)) {
    throw ArgumentError('必须传入以下值之一:$allowedValues');
  }
  return input;
}

使用时必须通过createMyType函数创建,否则没法保证类型安全:

void main() {
  final valid = createMyType('HELLO');
  
  // 编译时不会报错,但这是不安全的写法
  // MyType invalid = 'INVALID';
}

这种方式适合快速原型开发,不推荐在正式项目中使用,因为没法阻止直接赋值非法字符串。


内容的提问来源于stack exchange,提问作者Ale TheFe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 16:53:10