|
| 1 | +// ! this library is mostly used with ramda |
| 2 | + |
| 3 | +import {I, T, Test} from "ts-toolbelt"; |
| 4 | + |
| 5 | +const {check, checks} = Test; |
| 6 | + |
| 7 | +// iterates over `T` and returns the `Iteration` position when finished |
| 8 | +type StdRecursiveIteration<T extends any[], I extends I.Iteration = I.IterationOf<'0'>> = { |
| 9 | + 0: StdRecursiveIteration<T, I.Next<I>>; |
| 10 | + 1: I.Pos<I>; |
| 11 | +}[ |
| 12 | + I.Pos<I> extends T.Length<T> // this form of recursion is preferred |
| 13 | + ? 1 // because it will let the user know if |
| 14 | + : 0 // the instantiation depth has been hit |
| 15 | +]; // (but error is sometimes swallowed (?)) |
| 16 | + |
| 17 | +checks([ |
| 18 | + check<StdRecursiveIteration<[ |
| 19 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 20 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 21 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 22 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 23 | + ]>, 40, Test.Pass>(), // max length is 40 |
| 24 | +]); |
| 25 | + |
| 26 | +// iterates over `T` and returns the `Iteration` position when finished |
| 27 | +type SafeRecursiveIteration<T extends any[], I extends I.Iteration = I.IterationOf<'0'>> = { |
| 28 | + 0: SafeRecursiveIteration<T, I.Next<I>>; |
| 29 | + 1: I.Pos<I>; |
| 30 | +}[ |
| 31 | + I.Key<I> extends T.Length<T, 's'> // this form of recursion is the safest |
| 32 | + ? 1 // because `T.Length<T, 's'>` will force |
| 33 | + : 0 // the length to comply with the limits |
| 34 | +]; // => won't compute if excessive length |
| 35 | + |
| 36 | +checks([ |
| 37 | + check<SafeRecursiveIteration<[ |
| 38 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 39 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 40 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 41 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 42 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 43 | + ]>, 0, Test.Pass>() // did not compute |
| 44 | +]); |
0 commit comments