是否可以从数字类型T
得到值为T+1的数字类型Y
。
type one = 1
type Increment<T extends number> = ???
type two = Increment<one> // 2
P.S.目前,我已经硬编码了递增值的接口,但问题是硬编码的,因此受到限制:
export type IncrementMap = {
0: 1,
1: 2,
2: 3,
是否可以从数字类型T
得到值为T+1的数字类型Y
。
type one = 1
type Increment<T extends number> = ???
type two = Increment<one> // 2
P.S.目前,我已经硬编码了递增值的接口,但问题是硬编码的,因此受到限制:
export type IncrementMap = {
0: 1,
1: 2,
2: 3,
5条答案
按热度按时间piwo6bdm1#
这个答案已经过时了,因为TS4.1中引入了递归条件类型。
我会像这样硬编码:
正如我在其他评论中所说的,目前还没有对这种自然递归类型的强大支持。我希望它能得到支持,但它不在那里。在实践中,我发现如果某个东西可以处理长度达到20左右的元组,那就足够好了,但您的经验可能会有所不同。
无论如何,如果有人在这里提出了一个解决方案,它不是硬编码的,但对于任意数字(其中
Increment<123456789>
将计算为123456790
)也能很好地工作和执行,我很有兴趣看看它。也许将来有一天它会成为语言的一部分。kpbwa7wx2#
稍微不同的解决方案。但是有同样的1000次递归调用的限制
mzsu5hc03#
这个解决方案不是硬编码的,但由于TypeScript的递归限制,它没有用处。当我测试它时,它不能处理大于45的
Number2Nat
。qlzsbp2j4#
TypeScript仍然不支持数字文字类型的数学运算。在microsoft/TypeScript#26382上有一个长期的开放特性请求。
但是现在,如果必须的话,您可以使用模板文字类型通过将数字文字转换为字符串文字来增加数字文字类型;对该字符串文字执行逐字符decimal加法,并将所得字符串文字转换回数字文字。
坦率地说,对于任何合理的用例来说,这可能是矫枉过正的,但这是可能的,而且不会给编译器带来太多负担。
在下文中,我们将输入限制为表示小于
Number.MAX_SAFE_INTEGER
的非负整数的数字文字。对于任何其他输入(例如,number
本身,负数,分数,非常大的数字),输出将只是number
。如果有必要,可以通过仔细查看Number.toString(10)
和number
s的JavaScript编码规则(双精度64位二进制格式IEEE 754)来解决这些问题,但我不打算在这里打扰这些问题。这就是实现:
_IncDigit
类型是一个实用程序元组,它编码了如何递增一个数字而不用担心carry;所以_IncDigit[0]
是1
,_IncDigit[5]
是6
,一直到_IncDigit[9]
是0
。然后
_Inc<T>
是基本的递增操作,它假设T
是有效数字输入的字符串表示。如果T
至少有一个字符,则将其拆分为第一个字符F
和字符串R
的其余部分,并立即递归确定_Inc<R>
,即递增字符串其余部分的结果。这里我们将进位编码为"C"
的初始“数字”。如果_Inc<R>
的结果以进位标志位开始,则递增F
;否则我们就不管了如果F
递增并等于9
,则我们前置"C"
,否则不前置。最后,递增空字符串的结果就是进位标志。最后,
Increment<T>
负责将字符串转换为数字,将数字转换为字符串,以及验证输入。如果仍然有进位标志,它将被转换为1
。让我们测试一下:
看起来不错
不过,我还是不知道这种方法是否真的适用于任何正常的用例。如果你是为了好玩,那很好。但是,如果你发现自己想要在某个地方为一些生产代码库做这件事,请仔细考虑你实际上是否需要在类型系统中重新实现数学运算。很有可能,一种受限的方法(例如硬编码从
0
到100
的所有数字递增的结果等)也将满足您的需求。Playground链接到代码
ghhaqwfi5#
下面的解决方案没有
n > 999
的递归限制。唯一的限制是n.toString().length > 1000
;这似乎是javascript识别数字的能力的一个极限。一旦超过了这个限制,typescript将把递增的类型显示为number
。给定解决方案的逻辑类似于将大数求和为字符串。我们从最右边的字符开始并添加一个。
加法是用
IncrementMap
类型完成的,其中索引是我们试图递增的数字,值是我们想要获得的实际递增数字。链接到playground