痛点:现有方案的局限
在 JavaScript 项目中处理单位转换时,你是否遇到过这样的困扰?
方案一:专用库
bytes只能处理文件大小filesize同样局限- 需要格式化时间、长度、货币?再装一个库
方案二:通用转换库
- 每个转换都要手动定义
- 代码臃肿,配置繁琐
// 老方式:繁琐且不灵活
const bytes = require('bytes')
const filesize = require('filesize')
// 时间、长度、货币还需要别的库...
如果只需要定义一次单位链,就能获得智能格式化、链式展示、国际化支持和简洁的 API,会怎样?
解决方案:smart-unit 2.1.2
smart-unit 是一个轻量级的 TypeScript 优先库,提供自动单位选择的单位转换功能。专为追求优雅而不牺牲功能的开发者设计。
npm install smart-unit
核心概念:简洁而强大
smart-unit 的精髓在于声明式单位链定义。只需定义一次单位和转换比例,剩下的交给库来处理。
文件大小格式化
import SmartUnit from 'smart-unit'
const fileSize = new SmartUnit(['B', 'KB', 'MB', 'GB', 'TB'], {
baseDigit: 1024,
})
console.log(fileSize.format(1024)) // "1KB"
console.log(fileSize.format(1536)) // "1.5KB"
console.log(fileSize.format(1024 * 1024 * 100)) // "100MB"
console.log(fileSize.format(1024 * 1024 * 1024 * 5)) // "5GB"
注意 format(1536) 自动选择了 "1.5KB" 而不是 "1536B" 或 "0.0015MB"。库会智能选择最易读的单位。
长度单位(可变比例)
并非所有单位系统都使用一致的基数。公制长度单位的比例各不相同:
const length = new SmartUnit(['mm', 10, 'cm', 100, 'm', 1000, 'km'])
console.log(length.format(1500)) // "1.5m"
console.log(length.format(1500000)) // "1.5km"
console.log(length.format(25)) // "2.5cm"
通过指定单独的比例(10、100、1000),可以准确建模任何单位层级。
双向转换:解析与格式化
smart-unit 不仅用于展示,还能将格式化字符串解析回基础值:
const time = new SmartUnit(['ms', 1000, 's', 60, 'm', 60, 'h'])
console.log(time.parse('90s')) // 90000 (ms)
console.log(time.parse('2.5h')) // 9000000 (ms)
console.log(time.parse('30m')) // 1800000 (ms)
这种双向能力使其非常适合配置文件、用户输入和数据序列化。
小数位数控制
支持固定小数位或范围格式,灵活控制输出精度:
const size = new SmartUnit(['B', 'KB', 'MB', 'GB'], {
baseDigit: 1024,
fractionDigits: '0-2' // 最少0位,最多2位
})
size.format(1536) // "1.5KB" (自动省略末尾0)
size.format(1000) // "1000B" (不需要小数)
size.format(1536.789) // "1.50KB" (最多2位小数,补0到最少位数)
链式格式化:2.0 新特性
将时间、角度等复合单位格式化为人类友好的链式表达:
const time = new SmartUnit(['ms', 1000, 's', 60, 'm', 60, 'h'])
time.formatChain(63000) // "1m3s"
time.formatChain(3663000) // "1h1m3s"
time.formatChain(90061000) // "25h1m1s" (超过24小时不转换为天)
// 反向解析
time.parseChain('1h30m') // 5400000 (ms)
time.parseChain('2h30m30s') // 9030000 (ms)
支持自定义分隔符:
const timeWithSpace = new SmartUnit(['ms', 1000, 's', 60, 'm', 60, 'h'], {
separator: ' '
})
timeWithSpace.formatChain(3663000) // "1h 1m 3s"
国际化 (i18n):2.0 新特性
通过 withConvert() 方法轻松实现单位名称的本地化:
const i18nMap = {
ms: '毫秒',
s: '秒',
m: '分钟',
h: '小时',
}
const t = (unit) => i18nMap[unit]
const timeI18n = new SmartUnit(['ms', 1000, 's', 60, 'm', 60, 'h'], {
separator: ' '
}).withConvert(t)
timeI18n.format(90000) // "1.5分钟"
timeI18n.formatChain(90000) // "1分钟 30秒"
配合 separator 选项,可以生成完全本地化的输出。
高精度模式:突破 JavaScript 极限
JavaScript 的 number 类型安全整数上限是 2^53 - 1(约 9 千万亿)。对于金融计算或科学应用,这是致命缺陷。
smart-unit 2.0 将高精度功能拆分为独立模块,通过 SmartUnitPrecision 类实现任意精度运算:
import { SmartUnitPrecision } from 'smart-unit/precision'
const bigLength = new SmartUnitPrecision(
['mm', 10, 'cm', 100, 'm', 1000, 'km', 1000, 'Mm', 1000, 'Gm', 1000, 'Tm']
)
// 支持 BigInt 和超出 JS 安全整数范围的数值
bigLength.format(10n ** 18n) // "1000Tm"
bigLength.format('1000000000000000000') // "1Tm"
金融计算
货币和金融数据经常超出安全整数限制,同时需要精确的十进制处理:
const currency = new SmartUnitPrecision(['', 'K', 'M', 'B', 'T'], {
baseDigit: 1000,
fractionDigits: 2,
})
currency.format('12345678901234567890') // "12345678.90T"
fractionDigits: 2 确保货币值保持一致的十进制位数。
自定义 Decimal.js 配置
2.0 支持为每个实例配置独立的 Decimal.js 参数:
const precise = new SmartUnitPrecision(['m', 1000, 'km'], {
decimalOptions: {
precision: 50, // 50位精度
rounding: 4, // 四舍五入模式
}
})
对比优势
| 特性 | bytes | filesize | smart-unit |
|---|---|---|---|
| 文件大小 | ✅ | ✅ | ✅ |
| 自定义单位 | ❌ | ❌ | ✅ |
| 双向转换 | ❌ | ❌ | ✅ |
| 链式格式化 | ❌ | ❌ | ✅ |
| 国际化 | ❌ | ❌ | ✅ |
| 高精度 | ❌ | ❌ | ✅ |
| BigInt 支持 | ❌ | ❌ | ✅ |
| 小数范围控制 | ❌ | ❌ | ✅ |
| TypeScript | 部分 | 部分 | ✅ 原生支持 |
| 包体积 | ~1KB | ~2KB | ~2KB(核心) |
smart-unit 用专用库的体积,提供通用库的灵活性。
测试覆盖
项目包含 100+ 条单元测试,覆盖各种边界情况:
- BigInt 输入处理
- Decimal.js 高精度计算
- 链式格式化与解析
- 国际化转换
- 边界值和异常处理
- 多种单位链配置
确保在生产环境中的稳定性和可靠性。
实际应用场景
数据传输速率
const bitrate = new SmartUnit(['bps', 'Kbps', 'Mbps', 'Gbps'], {
baseDigit: 1000,
fractionDigits: 1,
})
bitrate.format(1500000) // "1.5Mbps"
频率
const freq = new SmartUnit(['Hz', 'kHz', 'MHz', 'GHz'], {
baseDigit: 1000,
fractionDigits: 2,
})
freq.format(2400000000) // "2.40GHz"
存储容量(自定义阈值)
const storage = new SmartUnit(['B', 'KB', 'MB', 'GB', 'TB'], {
baseDigit: 1024,
threshold: 0.9, // 在下一单位的 90% 时切换
})
视频时长显示
const duration = new SmartUnit(['s', 60, 'm', 60, 'h'], {
separator: ':'
})
duration.formatChain(3661) // "1h:1m:1s"
TypeScript 原生设计
smart-unit 使用 TypeScript 编写,提供完整的类型安全:
import SmartUnit, { type GetUnitNames } from 'smart-unit'
import type { Decimal } from 'decimal.js'
// 普通模式 - 返回 number
const regular = new SmartUnit(['B', 'KB', 'MB', 'GB'], { baseDigit: 1024 })
const num: number = regular.parse('1KB')
// 高精度模式 - 返回 Decimal
const precise = new SmartUnitPrecision(['B', 'KB', 'MB', 'GB'], { baseDigit: 1024 })
const dec: Decimal = precise.parse('1KB')
// 类型推导
const time = new SmartUnit(['ms', 1000, 's', 60, 'm', 60, 'h'])
type TimeUnits = GetUnitNames<typeof time> // "ms" | "s" | "m" | "h"
// 国际化函数类型安全
const timeI18n = time.withConvert((unit: TimeUnits) => {
const map = { ms: '毫秒', s: '秒', m: '分钟', h: '小时' }
return map[unit]
})
类型推断无缝工作,API 设计有意保持简洁,降低认知负担。
快速开始
npm install smart-unit
import SmartUnit from 'smart-unit'
// 定义一次,随处使用
const size = new SmartUnit(['B', 'KB', 'MB', 'GB'], { baseDigit: 1024 })
size.format(1024 * 1024 * 100) // "100MB"
size.parse('2.5GB') // 2684354560
在线体验
直接在浏览器中体验 smart-unit:
总结
smart-unit 2.1.2 用优雅的方案解决了普遍存在的问题。无论是格式化文件上传、解析用户输入、处理金融数据,还是构建科学应用,它都在简洁性和功能性之间取得了完美平衡。
核心要点:
- 用极简语法定义任意单位链
- 自动选择最优单位
- 双向转换(格式化和解析)
- 链式格式化(2.0 新增)
- 国际化支持(2.0 新增)
- 高精度模式支持 BigInt,模块化按需加载
- 小数位数范围控制
- TypeScript 原生,包体积最小
- 100+ 条单元测试全覆盖,稳定性有保障
在下一个项目中试试看,你的单位转换代码会感谢你的。
相关链接:
- GitHub: github.com/flycran/sma…
- npm: www.npmjs.com/package/sma…
- 文档: flycran.github.io/smart-unit/
- 协议: MIT