dart_common_extensions:一套 Dart 常用扩展方法集合

前言

写 Dart / Flutter 时,你一定遇到过这些场景:

字符串转 int 要写int.parse(s),还担心抛异常;日期格式化到处写DateFormat;列表想要个chunked还得自己写循环;Map 想取个不存在的 key 要加一大堆containsKey判断……

这些小操作本身不难,但每天写十几次,代码就变得啰嗦且容易出错。

这就是我开源dart_common_extensions的原因。

项目地址:github.com/ceeyang/dart_common_extensions
Pub 地址:pub.dev/packages/dart_common_extensions

150+ 扩展方法,覆盖 String / DateTime / List / Map / Num / Enum / Object 📦 零运行时依赖(仅 decimal + intl) 🧪100+ 单元测试 📄 完整 API 文档 + 示例代码

安装

dependencies: dart_common_extensions: ^0.0.9
# Flutter 项目flutter pub get# 纯 Dart 项目dart pub get

核心功能一览

📎 Object Extensions — 函数式编程小工具

Kotlin 开发者会非常熟悉letalso,Dart 里也能用了:

// let:对非空对象执行操作并返回结果 final length=userInput?.let((it)=>it.length)??0;//also:对对象执行副作用并返回对象本身 someObject.also((it)=>print('Processing:$it'));// 空安全判断 print(someObject.isNull);//true/falseprint(someObject.isNotNull);//true/false

🧵 String Extensions — 字符串处理的瑞士军刀

这是这个包里最常用的部分。类型转换、校验、格式化、大小写变换,一行搞定:

类型转换:

'12'.toInt;//12'12.34'.toDouble;//12.34'2023-01-01'.toDate;// DateTime(2023,1,1)'{"key":"value"}'.toJson;//{key: value}'1,2,3'.toIntList;//[1,2,3]

校验方法:

'13912345678'.isChineseMobile;//true'user@example.com'.isEmail;//true'192.168.1.1'.isIP;//true'{"a":1}'.isJson;//true'SGVsbG8='.isBase64;//true'https://example.com'.isValidUrl;// true(支持 localhost、IP、自定义端口)'AFFE'.isValidHex;//true

大小写转换:

'hello_world'.toCamelCase;// helloWorld'helloWorld'.toSnakeCase;// hello_world'hello-world'.toKebabCase;// hello-world'hello world'.toTitleCase;// Hello World

字符串操作:

'This is a long text'.truncate(10);//'This is a ...''user@example.com'.substringBefore('@');//'user''hello'.capitalize;//'Hello''Hello World'.removeAllSpaces;//'HelloWorld'

📅 DateTime Extensions — 日期时间不头疼

格式化:

final now=DateTime.now();now.ymd;//"2026-07-15"now.dmy;//"15-07-2026"now.iso8601;//"2026-07-15T12:00:00"now.fullDateTime;//"2026-07-15 12:00:00"now.monthYear;//"July 2026"now.shortDate;//"7/15/2026"(locale dependent) now.longDate;//"July 15, 2026"(locale dependent) now.time;//"12:00:00"

字符串也可以直接格式化:

'2023-01-01'.ymd;//"2023-01-01"'2023-01-01'.fullDateTime;//"2023-01-01 00:00:00"'1672531200000'.ymd;//"2023-01-01"(时间戳也支持)

日期计算:

now.startOfDay;// 当天 00:00:00.000 now.endOfDay;// 当天23:59:59.999 now.isToday;//true/falsenow.nextDay;// 明天 now.isLeapYear;// 是否闰年 now.daysInMonth;// 当月天数 // 工作日计算 DateTime friday=DateTime(2023,1,6);friday.addBusinessDays(1);// 下周一(跳过周末) friday.subtractBusinessDays(1);// 上周四 DateTime(2023,1,7).isWeekend;// true(周六)

📋 List & Iterable Extensions — 集合操作大补全

安全访问:

['a','b','c'].safeElementAt(5);// null(不抛异常)[1,2,3,4,5].firstWhereOrNull((e)=>e>10);// null

分组与变换:

[1,2,3,4,5].chunked(2);//[[1,2],[3,4],[5]][1,2,3,4].windowed(2);//[[1,2],[2,3],[3,4]][1,2].zip(['a','b']);//[[1,'a'],[2,'b']][1,2,3].mapIndexed((i, e)=>'$i: $e');//['0: 1','1: 2','2: 3']

统计聚合:

[1,2,3,4].sum;//10[1,2,3,4].average;//2.5[1,2,3,4].max;//4[1,2,3,4].min;//1[1,2,3,4].count((i)=>i>2);//2

实用方法:

[1,2,3].random;// 随机元素[1,2,3].shuffled;// 打乱后的新列表[1,2,3].groupBy((e)=>e.isEven ?'even':'odd');//{'odd':[1,3],'even':[2]}[null, null].isAllNull;//true

🗺️ Map Extensions — 安全又灵活

var map={'first':1,'second':2};map.getOrDefault('third',0);//0(不抛异常) map.getOrNull('third');// null map.toJsonString();//'{"first": 1, "second": 2}'// 过滤 map.pick(['first']);//{'first':1}map.omit(['first']);//{'second':2}map.filterKeys((k)=>k.startsWith('f'));//{'first':1}map.filterValues((v)=>v>1);//{'second':2}//合并 {'a':1}.merge({'a':2,'b':3});//{'a':2,'b':3} {'a':1}.merge({'a':2},(v1,v2)=>v1+v2);//{'a':3}//变换 {'a':1}.mapKeys((k,v)=>k.toUpperCase());//{'A':1}{'a':1}.mapValues((k,v)=>v+1);//{'a':2}

🔢 Num Extensions — 数字也可以有语法糖

时间 Duration:

5.seconds;// Duration(seconds:5)1.5.days;// Duration(hours:36)60.secondsDuration;//0:01:00.000000 await5.secondsDelay();// 延迟5

格式化:

1024.toFileSize();//"1.00 KB"123456.78.toCurrency(symbol:'€');//"€123,456.78"1234.567.toMoney(decimalDigits:1);//"1,234.6"255.toHexString;//"ff"10.toBinaryString;//"1010"0.1234.toPercentage();//"12.34%"

数学:

1.rangeTo(5);//[1,2,3,4,5]5.rangeTo(1);//[5,4,3,2,1]1.sumTo(5);//152.power(3);//85.isPrime;//true2.isEven;//true

🔁 Enum Extensions — 循环导航

enum Status{active, inactive}Status.active.next(Status.values);// Status.inactive Status.inactive.previous(Status.values);// Status.active

特别适合分页状态机、步骤导航等场景。


为什么自己造这个轮子?

Dart 生态中其实不缺扩展库,比如dartxbasicssupercharged等。选择自建一个,有几个原因:

  1. 按需定制:只收录日常真的会用到的扩展,不做大而全的"百宝箱"
  2. 中文友好:内置了isChineseisChineseMobile等中文场景校验
  3. 简单透明:代码量不大,每个扩展方法都清晰可查,遇到问题直接看源码比翻文档快
  4. 零学习成本:所有方法命名都是自解释的,看一眼就知道干嘛用的

项目状态与路线图

当前版本0.0.9,2026年5月底初次发布,已有 150+ 扩展方法和 100+ 单元测试。

后续计划:

  • Num扩展:货币格式化、范围生成、延迟
  • List扩展:windowedzipgroupBy
  • String扩展:百分比、Base64、URL 编码
  • Iterable扩展补充:更多懒加载操作
  • Duration扩展:人类可读格式
  • Null扩展:isNull/isNotNull顶层函数
  • 更多本地化日期格式

欢迎提 Issue 或 PR 贡献你常用的扩展方法。


结语

dart_common_extensions不是什么惊天动地的项目,它是一个工具箱——把每天写 Dart / Flutter 时那些"又来一遍"的操作封装起来,让代码更短、更清晰、更安全。

项目是完全开源的(MIT 协议),欢迎 Star、Issue 和 PR:

👉 github.com/ceeyang/dart_common_extensions

如果你也在写 Dart / Flutter,不妨试一试,加一行依赖就能省下不少样板代码。