You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: source/internal/type.d.ts
+26Lines changed: 26 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -96,6 +96,32 @@ type B = IfNotAnyOrNever<any, 'VALID', 'IS_ANY', 'IS_NEVER'>;
96
96
type C = IfNotAnyOrNever<never, 'VALID', 'IS_ANY', 'IS_NEVER'>;
97
97
//=> 'IS_NEVER'
98
98
```
99
+
100
+
Note: Wrapping a tail-recursive type with `IfNotAnyOrNever` makes the implementation non-tail-recursive. To fix this, move the recursion into a helper type. Refer to the following example:
101
+
102
+
@example
103
+
```ts
104
+
import type {StringRepeat} from 'type-fest';
105
+
106
+
type NineHundredNinetyNineSpaces = StringRepeat<' ', 999>;
107
+
108
+
// The following implementation is not tail recursive
109
+
type TrimLeft<S extends string> = IfNotAnyOrNever<S, S extends ` ${infer R}` ? TrimLeft<R> : S>;
110
+
111
+
// Hence, instantiations with long strings will fail
112
+
// @ts-expect-error
113
+
type T1 = TrimLeft<NineHundredNinetyNineSpaces>;
114
+
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
115
+
// Error: Type instantiation is excessively deep and possibly infinite.
116
+
117
+
// To fix this, move the recursion into a helper type
118
+
type TrimLeftOptimised<S extends string> = IfNotAnyOrNever<S, _TrimLeftOptimised<S>>;
119
+
120
+
type _TrimLeftOptimised<S extends string> = S extends ` ${infer R}` ? _TrimLeftOptimised<R> : S;
121
+
122
+
type T2 = TrimLeftOptimised<NineHundredNinetyNineSpaces>;
0 commit comments