explore associating a unit with a number ?
中文标题:探索将单位与数字关联
- 阶段: 未分阶段
- 状态: 进行中
- ECMAScript 版本: —
- 同步时间: 2026年9月19日
- English original · 官方仓库
该提案旨在解决将数字与其所度量的单位关联起来的需求,这是 MessageFormat 2.0 所需的一种数据类型,但在 JavaScript 中没有对应物。它为 Intl.NumberFormat.prototype.format 增加了一种协议,同时也应由 Intl.PluralRules.prototype.select 接受,该协议接受与单位配对的数值。该协议允许在格式化时提供单位,而不是通过 Intl.NumberFormat 构造函数提供,包括货币单位,并规定了缺失字段、单位冲突以及不允许单位样式时的行为。
以下 README 来自上游仓库,其中的阶段或状态标注可能滞后;当前信息以提案概览为准。
TC39 Intl 单位协议
状态:Stage 2
提案人:Shane F Carr (Google i18n)
历史:
草案规范:https://tc39.es/proposal-intl-unit-protocol/
背景
i18n 社区已经达成共识:数字应当标注它所度量的量。与本地化的小数分隔符、数字的记数系统以及分组策略不同,单位是待格式化数据模型的核心组成部分,而不是由格式化器应用的样式。
例如,在格式化消息时,这允许根据区域设置的单位偏好对度量进行本地化。
带单位标注的数字是 MessageFormat 2.0 所需的唯一一种在 JavaScript 中没有对应物的数据类型。参见:MessageFormat 2.0 中的函数列表。
添加一个新的原始对象(primordial),例如 Amount,可以解决这个问题以及影响 i18n 的多个其他问题。一个关键问题是 Amount 如何与 Intl 对接,以及第三方库如何实现类似 Amount 的对象。提案负责人认为,这是一个足够不同的问题领域,因此他们正在将 Intl Unit Protocol 作为独立提案推进。
提议的解决方案
为 Intl.NumberFormat.prototype.format 增加一种协议,该协议接受与单位配对的数值类型。该协议也应被 Intl.PluralRules.prototype.select 接受。
给定这些输入:
用户目前可以这样写:
使用协议后,用户可以改为这样写:
构造与格式化
Intl 长期以来允许构造函数和格式化函数相互分离。这实现了两个目的:
- 格式化器可以封装区域设置和选项,以指定待格式化值的样式和上下文,例如在初始化模板引擎时。
- 区域设置数据可以提前初始化,从而在循环中格式化多个项目时提高效率。
通过将 unit 从构造函数一侧移到格式化一侧,我们推进了目标 1。
该提案对目标 2 有一定代价,因为加载单位显示名称存在一些实现成本,而现在必须延迟这一成本。我们将与 ICU[4X] 合作以尽量减少这一成本。
货币
该协议将允许以类似方式指定货币单位。
协议要求同时提供 value 和 unit 字段
该协议要求对象同时具有 value 和 unit 字段:
如果其中任一字段缺失或为 undefined,我们会回退到当前调用 Symbol.toPrimitive 的行为:
单位冲突
如果构造函数中有一个单位,而该单位与协议中的单位不同,则会抛出异常,因为这是程序员的错误。
当 Amount 提案推进时,可以将其改为自动把输入单位转换为格式化器单位。
如果 style 不是 "unit" 或 "currency",则不允许使用单位
如果在协议中设置了 unit,但格式化器 未 配置为 style "unit" 或 "currency",则会发生错误。
这有助于实现方知道它们需要在构造函数中加载单位或货币数据,从而部分缓解上文讨论的“构造与格式化”影响。
范围格式化
目前,格式化范围要求单位相等。这一限制将来可能会放宽。
与未来提案的集成
Amount 提案旨在添加一个封装数值类型与单位的原始对象(primordial)。它将实现此处指定的 Intl 协议。
Decimal 提案旨在添加一个原始对象(primordial),以一种为正确且高效的算术运算而设计的形式表示十进制数。它很可能作为协议中 value 字段的另一种数值类型得到支持。
将来还可以向该协议添加其他字段,例如表达精度的替代方式,或对构造函数中指定的有效数字位数进行覆盖。