type Increment<N extends number> = [
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,
21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,
38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54, // as far as you need
...number[] // bail out with number
][N]
type Zero = 0
type One = Increment<Zero> // 1
type Two = Increment<One> // 2
type WhoKnows = Increment<12345>; // number
type SomeNat = [...unknown[]];
type Zero = [];
type Succ<N extends SomeNat> = [...N, unknown];
type Nat2Number<N extends SomeNat> = N["length"];
type Dec<N extends SomeNat> = N extends [unknown, ...infer T] ? T : never;
type Add<N extends SomeNat, M extends SomeNat> = [...N, ...M];
type Sub<N extends SomeNat, M extends SomeNat> = M extends Zero ? N : Sub<Dec<N>, Dec<M>>;
type Number2Nat<I extends number, N extends SomeNat = Zero> = I extends Nat2Number<N> ? N : Number2Nat<I, Succ<N>>;
type Arr<N extends number, T extends any[] = []> = T['length'] extends N ? T : Arr<N, [...T, any]>
type Inc<N extends number> = [...Arr<N>, any]['length']
type I20 = Inc<19>
4条答案
按热度按时间gg58donl1#
我会像这样硬编码:
正如我在其他评论中所说,目前还没有对这种自然递归类型的支持。如果支持它,我会很高兴,但它并不存在。在实践中,我发现如果某个东西可以处理长度为20左右的元组,那就足够好了,但你的经验可能会有所不同。
无论如何,如果有人在这里提出了一个解决方案,它不是硬编码的,但对于任意数字(其中
Increment<123456789>
的计算结果为123456790
)也能很好地工作和执行,我很有兴趣看看它。也许将来有一天它会成为语言的一部分。希望有帮助;祝你好运!
5fjcxozz2#
这个解决方案不是硬编码的,但由于TypeScript的递归限制,它并没有什么用处。当我测试它时,它不能处理大于45的
Number2Nat
。nr7wwzry3#
一个稍有不同的解决方案。但是有同样的1000次递归调用的限制
bwitn5fc4#
下面的解决方案没有递归限制
n > 999
。唯一的限制是n.toString().length > 1000
;这似乎是javascript识别数字的能力的一个极限,一旦超过这个极限,typescript将把递增的类型显示为number
。给定解决方案的逻辑类似于将大数字求和为一个字符串。我们从最右边的字符开始,然后加1。
加法是用
IncrementMap
类型完成的,其中索引是我们试图递增的数字,值是我们想要获得的实际递增数字。链接到playground