这对我来说是谷歌上的最高结果,所以我认为我应该提供我找到的解决方案。
使用bigint
现在是 2020 年并且bigint
已被接受,值得一提。您可以简单地执行以下操作。请注意,bigint
与 a 相比, s 对性能的影响更大number
。
const myNumber: bigint = 10n
使用标称类型/标记类型/不透明类型
另一种方法是使用标称类型,但可以说它不太符合人体工程学,我不确定它是否比 快bigint
,但该模式确实可以推广到任何类型,而不仅仅是number
. TypeScript 对此没有“一流”的支持,所以你必须做一个厚颜无耻的 hack。有一个用于此调用的库newtype-ts
,其中包括常见类型,Integer
因此您可能只想使用它,但我将在下面解释其工作原理。
首先,我们定义integer
类型。
const TAG = Symbol()
type integer = number & { readonly [TAG]: unique symbol }
确保我们有一个唯一的TAG
值,这样我们就不会意外地使用相同的键创建一个对象,并且出于同样的原因,我们也使该字段成为唯一的符号。现在,您的整数实际上不会有这个对象字段,但这很好。
有了这个,你仍然可以添加integer
到number
using +
. 不好。因此,您可以通过使用函数按摩类型系统来对此处的参数强制执行类型安全。我只是将其称为警卫,而且您可以再次看到它不是特定于integer
s 的 - 您可以制作更多不透明的类型并再次使用它。
type guard = <A>(f: (...ns: Array<A>) => A, ...ns: Array<A>) => A
const guard: guard = (f, ...ns) => f(...ns)
如果您尝试使用number
const bad: integer = guard((a, b) => a + b as integer, myCoolInteger, 10)
您会收到如下错误
Argument of type '10' is not assignable to parameter of type 'integer'.
Type '10' is not assignable to type '{ readonly [TAG]: unique symbol; }'.(2345)
请注意,您没有在此处强制执行返回类型(因为您必须使用as integer
),并且某些运算符(例如)/
将返回浮点数,因此您可能仍希望进行运行时检查或将 a 添加Math.round
到的专用版本中guard
,但这至少会确保您没有尝试同时使用两种单独的数字类型 - 假设您有GBP
并USD
尝试添加它们,这可能不是您想要的。