@depup/type-fest 5.9.0-depup.0 → 5.10.0-depup.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -13,8 +13,8 @@ npm install @depup/type-fest
13
13
 
14
14
  | Field | Value |
15
15
  |-------|-------|
16
- | Original | [type-fest](https://www.npmjs.com/package/type-fest) @ 5.9.0 |
17
- | Processed | 2026-09-06 |
16
+ | Original | [type-fest](https://www.npmjs.com/package/type-fest) @ 5.10.0 |
17
+ | Processed | 2026-09-27 |
18
18
  | Smoke test | failed |
19
19
  | Deps updated | 0 |
20
20
 
package/changes.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "bumped": {},
3
- "timestamp": "2026-09-06T01:00:53.768Z",
3
+ "timestamp": "2026-09-27T01:04:10.017Z",
4
4
  "totalUpdated": 0
5
5
  }
package/index.d.ts CHANGED
@@ -99,6 +99,7 @@ export type {LessThan} from './source/less-than.d.ts';
99
99
  export type {LessThanOrEqual} from './source/less-than-or-equal.d.ts';
100
100
  export type {Sum} from './source/sum.d.ts';
101
101
  export type {Subtract} from './source/subtract.d.ts';
102
+ export type {UnionMax} from './source/union-max.d.ts';
102
103
  export type {KeyAsString} from './source/key-as-string.d.ts';
103
104
  export type {Exact} from './source/exact.d.ts';
104
105
  export type {ReadonlyTuple} from './source/readonly-tuple.d.ts';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@depup/type-fest",
3
- "version": "5.9.0-depup.0",
3
+ "version": "5.10.0-depup.0",
4
4
  "description": "A collection of essential TypeScript types (with updated dependencies)",
5
5
  "license": "(MIT OR CC0-1.0)",
6
6
  "repository": "sindresorhus/type-fest",
@@ -26,6 +26,7 @@
26
26
  },
27
27
  "scripts": {
28
28
  "test:tsc": "node --max-old-space-size=6144 ./node_modules/.bin/tsc",
29
+ "test:minimum-lib": "node --max-old-space-size=6144 ./node_modules/.bin/tsc -p tsconfig.minimum-lib.json",
29
30
  "test:tsd": "node --max-old-space-size=6144 ./node_modules/.bin/tsd",
30
31
  "test:xo": "node --max-old-space-size=6144 ./node_modules/.bin/xo --ignores=lint-processors/fixtures/**/*.d.ts '**/*.{js,ts,md}'",
31
32
  "test:linter": "node --test",
@@ -84,8 +85,8 @@
84
85
  "changes": {},
85
86
  "depsUpdated": 0,
86
87
  "originalPackage": "type-fest",
87
- "originalVersion": "5.9.0",
88
- "processedAt": "2026-09-06T01:00:57.924Z",
88
+ "originalVersion": "5.10.0",
89
+ "processedAt": "2026-09-27T01:04:16.083Z",
89
90
  "smokeTest": "failed"
90
91
  }
91
92
  }
package/readme.md CHANGED
@@ -29,17 +29,6 @@
29
29
  <sup>An open-source framework that supports any programming language, cloud provider, or deployment automation tool.</sup>
30
30
  </div>
31
31
  </a>
32
- <br>
33
- <br>
34
- <a href="https://circleback.ai?utm_source=sindresorhus&utm_medium=sponsorship&utm_campaign=awesome-list&utm_id=type-fest">
35
- <div>
36
- <img width="300" src="https://sindresorhus.com/assets/thanks/circleback-logo.png?x" alt="Circleback logo">
37
- </div>
38
- <b>Get the most out of every conversation.</b>
39
- <div>
40
- <sup>AI-powered meeting notes, automations, and search. Give AI agents the context they need to get things done.</sup>
41
- </div>
42
- </a>
43
32
  </p>
44
33
  </div>
45
34
  <br>
@@ -312,6 +301,7 @@ Click the type names for complete docs.
312
301
  - [`LessThanOrEqual`](source/less-than-or-equal.d.ts) - Returns a boolean for whether a given number is less than or equal to another number.
313
302
  - [`Sum`](source/sum.d.ts) - Returns the sum of two numbers.
314
303
  - [`Subtract`](source/subtract.d.ts) - Returns the difference between two numbers.
304
+ - [`UnionMax`](source/union-max.d.ts) - Returns the maximum number in a union of numbers.
315
305
  - [`Absolute`](source/absolute.d.ts) - Returns the absolute value of the specified number or bigint.
316
306
  - [`StringToNumber`](source/string-to-number.d.ts) - Converts a numeric string to a number.
317
307
 
@@ -101,10 +101,15 @@ type B = AllExtend<[1?, 2?, 3?], number | undefined>;
101
101
  @category Array
102
102
  */
103
103
  export type AllExtend<TArray extends UnknownArray, Type, Options extends AllExtendOptions = {}> =
104
- _AllExtend<CollapseRestElement<TArray>, Type, ApplyDefaultOptions<AllExtendOptions, DefaultAllExtendOptions, Options>>;
105
-
106
- type _AllExtend<TArray extends UnknownArray, Type, Options extends Required<AllExtendOptions>> = IfNotAnyOrNever<TArray, {
107
- ifNot: TArray extends readonly [infer First, ...infer Rest]
104
+ IfNotAnyOrNever<CollapseRestElement<TArray>, {
105
+ ifNot: _AllExtend<CollapseRestElement<TArray>, Type, ApplyDefaultOptions<AllExtendOptions, DefaultAllExtendOptions, Options>>;
106
+ ifAny: false;
107
+ ifNever: false;
108
+ }>;
109
+
110
+ // Kept free of `IfNotAnyOrNever` so that it stays tail-recursive, which allows it to handle long arrays.
111
+ type _AllExtend<TArray extends UnknownArray, Type, Options extends Required<AllExtendOptions>> =
112
+ TArray extends readonly [infer First, ...infer Rest]
108
113
  ? IsNever<First> extends true
109
114
  ? Or<Or<IsNever<Type>, IsAny<Type>>, Not<Options['strictNever']>> extends true
110
115
  // If target `Type` is also `never`, or is `any`, or `strictNever` is disabled, recurse further.
@@ -114,8 +119,5 @@ type _AllExtend<TArray extends UnknownArray, Type, Options extends Required<AllE
114
119
  ? _AllExtend<Rest, Type, Options>
115
120
  : false
116
121
  : true;
117
- ifAny: false;
118
- ifNever: false;
119
- }>;
120
122
 
121
123
  export {};
@@ -1,7 +1,6 @@
1
1
  import type {If} from './if.d.ts';
2
2
  import type {IsArrayReadonly} from './internal/array.d.ts';
3
3
  import type {IfNotAnyOrNever, IsExactOptionalPropertyTypesEnabled} from './internal/type.d.ts';
4
- import type {IsOptionalKeyOf} from './is-optional-key-of.d.ts';
5
4
  import type {UnknownArray} from './unknown-array.d.ts';
6
5
 
7
6
  /**
@@ -65,21 +64,23 @@ type _ArrayReverse<
65
64
  AfterRestAcc extends UnknownArray = [],
66
65
  Result extends UnknownArray = never,
67
66
  > =
68
- keyof TArray & `${number}` extends never
69
- // Enters this branch, if `TArray` is empty (e.g., `[]`),
70
- // or `TArray` contains no non-rest elements preceding the rest element (e.g., `[...string[]]` or `[...string[], string]`).
71
- ? TArray extends readonly [...infer Rest, infer Last]
72
- ? _ArrayReverse<Rest, BeforeRestAcc, [...AfterRestAcc, Last], Result> // Accumulate elements that are present after the rest element in reverse order.
73
- : Result | [...AfterRestAcc, ...TArray, ...BeforeRestAcc] // Add the rest element between the accumulated elements.
74
- : TArray extends readonly [(infer First)?, ...infer Rest]
75
- ? IsOptionalKeyOf<TArray, '0'> extends true
76
- ? _ArrayReverse<
67
+ '0' extends keyof TArray
68
+ // Enters this branch, if `TArray` starts with a non-rest element (e.g., `[string, number]` or `[string, ...number[]]`).
69
+ ? TArray extends readonly [(infer First)?, ...infer Rest]
70
+ // A tuple allows fewer than one element only when its first element is optional. Written in exactly this shape because equivalent ones, such as `[] extends TArray`, are several times slower.
71
+ ? TArray extends readonly [unknown, ...unknown[]]
72
+ ? _ArrayReverse<Rest, [First, ...BeforeRestAcc], AfterRestAcc, Result>
73
+ : _ArrayReverse<
77
74
  Rest,
78
75
  [First | (If<IsExactOptionalPropertyTypesEnabled, never, undefined>), ...BeforeRestAcc], // Add `| undefined` for optional elements, if `exactOptionalPropertyTypes` is disabled.
79
76
  AfterRestAcc,
80
77
  Result | BeforeRestAcc
81
78
  >
82
- : _ArrayReverse<Rest, [First, ...BeforeRestAcc], AfterRestAcc, Result>
83
- : never; // Should never happen, since `readonly [(infer First)?, ...infer Rest]` is a top-type for arrays.
79
+ : never // Should never happen, since `readonly [(infer First)?, ...infer Rest]` is a top-type for arrays.
80
+ // Enters this branch, if `TArray` is empty (e.g., `[]`),
81
+ // or `TArray` contains no non-rest elements preceding the rest element (e.g., `[...string[]]` or `[...string[], string]`).
82
+ : TArray extends readonly [...infer Rest, infer Last]
83
+ ? _ArrayReverse<Rest, BeforeRestAcc, [...AfterRestAcc, Last], Result> // Accumulate elements that are present after the rest element in reverse order.
84
+ : Result | [...AfterRestAcc, ...TArray, ...BeforeRestAcc]; // Add the rest element between the accumulated elements.
84
85
 
85
86
  export {};
@@ -60,11 +60,11 @@ export type ArrayTail<TArray extends UnknownArray> = IfNotAnyOrNever<TArray, {
60
60
  }>;
61
61
 
62
62
  type _ArrayTail<TArray extends UnknownArray> = TArray extends readonly [unknown?, ...infer Tail]
63
- ? keyof TArray & `${number}` extends never
64
- ? TArray extends readonly []
63
+ ? '0' extends keyof TArray
64
+ ? Tail
65
+ : TArray extends readonly []
65
66
  ? []
66
67
  : TArray // Happens when `TArray` is a non-tuple array (e.g., `string[]`) or has a leading rest element (e.g., `[...string[], number]`)
67
- : Tail
68
68
  : [];
69
69
 
70
70
  export {};
@@ -6,7 +6,7 @@ Generate a union of numbers between a specified start and end (both inclusive),
6
6
 
7
7
  You skip over numbers using the `Step` parameter (defaults to `1`). For example, `IntClosedRange<0, 10, 2>` will create a union of `0 | 2 | 4 | 6 | 8 | 10`.
8
8
 
9
- Note: `Start` or `End` must be non-negative and smaller than `999`.
9
+ Note: `Start` and `End` must each be between `-998` and `998`. The maximum is one less than for `IntRange` because the end is incremented internally to make it inclusive. If `Start` is greater than `End`, the result is `never`.
10
10
 
11
11
  Use-cases:
12
12
  1. This can be used to define a set of valid input/output values. for example:
@@ -23,6 +23,9 @@ type FontSize = IntClosedRange<10, 20>;
23
23
 
24
24
  type EvenNumber = IntClosedRange<0, 10, 2>;
25
25
  //=> 0 | 2 | 4 | 6 | 8 | 10
26
+
27
+ type Offset = IntClosedRange<-3, 3>;
28
+ //=> -3 | -2 | -1 | 0 | 1 | 2 | 3
26
29
  ```
27
30
 
28
31
  2. This can be used to define random numbers in a range. For example, `type RandomNumber = IntClosedRange<0, 100>;`
@@ -1,12 +1,16 @@
1
1
  import type {TupleOf} from './tuple-of.d.ts';
2
2
  import type {Subtract} from './subtract.d.ts';
3
+ import type {Absolute} from './absolute.d.ts';
4
+ import type {IsNegative} from './numeric.d.ts';
5
+ import type {UnknownArray} from './unknown-array.d.ts';
6
+ import type {ReverseSign} from './internal/index.d.ts';
3
7
 
4
8
  /**
5
9
  Generate a union of numbers between a specified start (inclusive) and end (exclusive), with an optional step.
6
10
 
7
11
  You skip over numbers using the `Step` parameter (defaults to `1`). For example, `IntRange<0, 10, 2>` will create a union of `0 | 2 | 4 | 6 | 8`.
8
12
 
9
- Note: `Start` or `End` must be non-negative and smaller than `1000`.
13
+ Note: `Start` and `End` must each be between `-998` and `999`. Negative ranges reach TypeScript's instantiation-depth limit one value earlier, so their supported minimum is one smaller in magnitude than the maximum. If `Start` is greater than `End`, the result is `never`.
10
14
 
11
15
  Use-cases:
12
16
  1. This can be used to define a set of valid input/output values. for example:
@@ -23,6 +27,9 @@ type FontSize = IntRange<10, 20>;
23
27
 
24
28
  type EvenNumber = IntRange<0, 11, 2>;
25
29
  //=> 0 | 2 | 4 | 6 | 8 | 10
30
+
31
+ type Offset = IntRange<-3, 3>;
32
+ //=> -3 | -2 | -1 | 0 | 1 | 2
26
33
  ```
27
34
 
28
35
  2. This can be used to define random numbers in a range. For example, `type RandomNumber = IntRange<0, 100>;`
@@ -40,7 +47,41 @@ type Hundreds = IntRange<100, 901, 100>;
40
47
 
41
48
  @see {@link IntClosedRange}
42
49
  */
43
- export type IntRange<Start extends number, End extends number, Step extends number = 1> = PrivateIntRange<Start, End, Step>;
50
+ export type IntRange<Start extends number, End extends number, Step extends number = 1> =
51
+ IsNegative<Start> extends true
52
+ ? PrivateNegativeIntRange<Start, End, Step>
53
+ : PrivateIntRange<Start, End, Step>;
54
+
55
+ /**
56
+ Removes `StepTuple['length']` elements from the front of `Tuple`, or empties it when it is too short.
57
+ */
58
+ type DropStep<Tuple extends UnknownArray, StepTuple extends UnknownArray> =
59
+ Tuple extends [...StepTuple, ...infer Rest extends UnknownArray] ? Rest : [];
60
+
61
+ /**
62
+ The implementation of `IntRange` for a negative `Start`.
63
+
64
+ A tuple length can never be negative, so instead of counting up to the value, `Magnitude` counts down from `-Start` and the value is `-Magnitude['length']`. Once `Magnitude` is too short to step again, the range has crossed zero and the rest is delegated to `PrivateIntRange`.
65
+ */
66
+ type PrivateNegativeIntRange<
67
+ Start extends number,
68
+ End extends number,
69
+ Step extends number,
70
+ // A `Step` below `1` cannot advance the range, so fall back to `1` like `PrivateIntRange` does
71
+ StepTuple extends UnknownArray = TupleOf<Step> extends [] ? [unknown] : TupleOf<Step>,
72
+ // How much of the range is left to generate, shortened by `Step` each time, so the range stops at `End`
73
+ Remaining extends UnknownArray = TupleOf<Subtract<End, Start>>,
74
+ // The magnitude of the current value, so the value itself is `-Magnitude['length']`
75
+ Magnitude extends UnknownArray = TupleOf<Absolute<Start>>,
76
+ Result = never,
77
+ > = Remaining extends []
78
+ ? Result
79
+ : Magnitude extends [...StepTuple, ...infer NextMagnitude extends UnknownArray]
80
+ ? PrivateNegativeIntRange<Start, End, Step, StepTuple, DropStep<Remaining, StepTuple>, NextMagnitude, Result | ReverseSign<Magnitude['length']>>
81
+ // Less than a step is left below zero, so `Crossover` is the amount the next step overshoots it by, and counting up can take over from there
82
+ : StepTuple extends [...Magnitude, ...infer Crossover extends UnknownArray]
83
+ ? Result | ReverseSign<Magnitude['length']> | PrivateIntRange<Crossover['length'], End, Step>
84
+ : never;
44
85
 
45
86
  /**
46
87
  The actual implementation of `IntRange`. It's private because it has some arguments that don't need to be exposed.
@@ -54,14 +95,20 @@ type PrivateIntRange<
54
95
  // The final `List` is `[...StartLengthTuple, ...[number, ...GapLengthTuple], ...[number, ...GapLengthTuple], ... ...]`, so can initialize the `List` with `[...StartLengthTuple]`
55
96
  List extends unknown[] = TupleOf<Start, never>,
56
97
  EndLengthTuple extends unknown[] = TupleOf<End>,
57
- > = Gap extends 0
98
+ // Avoid `GreaterThan<Start, End>` here because the extra type instantiations would make `IntRange<0, 999>` exceed TypeScript's instantiation-depth limit
99
+ // `TupleOf` represents a negative length as an empty tuple, so a negative `End` must be detected before comparing the tuple lengths
100
+ // Recursive calls pass `false` because reversal only depends on the initial bounds; the termination checks below still handle reaching or overshooting `End` without repeating this tuple comparison
101
+ IsReversed extends boolean = IsNegative<End> extends true ? true : List extends [...EndLengthTuple, unknown, ...unknown[]] ? true : false,
102
+ > = IsReversed extends true
103
+ ? never
104
+ : Gap extends 0
58
105
  // Handle the case that without `Step`
59
- ? List['length'] extends End // The result of "List[length] === End"
60
- ? Exclude<List[number], never> // All unused elements are `never`, so exclude them
61
- : PrivateIntRange<Start, End, Step, Gap, [...List, List['length'] ]>
106
+ ? List['length'] extends End // The result of "List[length] === End"
107
+ ? Exclude<List[number], never> // All unused elements are `never`, so exclude them
108
+ : PrivateIntRange<Start, End, Step, Gap, [...List, List['length'] ], EndLengthTuple, false>
62
109
  // Handle the case that with `Step`
63
- : List extends [...(infer U), ...EndLengthTuple] // The result of "List[length] >= End", because the `...TupleOf<Gap, never>` maybe make `List` too long.
64
- ? Exclude<List[number], never>
65
- : PrivateIntRange<Start, End, Step, Gap, [...List, List['length'], ...TupleOf<Gap, never>]>;
110
+ : List extends [...(infer U), ...EndLengthTuple] // The result of "List[length] >= End", because the `...TupleOf<Gap, never>` maybe make `List` too long.
111
+ ? Exclude<List[number], never>
112
+ : PrivateIntRange<Start, End, Step, Gap, [...List, List['length'], ...TupleOf<Gap, never>], EndLengthTuple, false>;
66
113
 
67
114
  export {};
@@ -1,6 +1,5 @@
1
1
  import type {If} from '../if.d.ts';
2
2
  import type {IsNever} from '../is-never.d.ts';
3
- import type {OptionalKeysOf} from '../optional-keys-of.d.ts';
4
3
  import type {UnknownArray} from '../unknown-array.d.ts';
5
4
  import type {IsExactOptionalPropertyTypesEnabled, IfNotAnyOrNever} from './type.d.ts';
6
5
 
@@ -119,26 +118,28 @@ type _CollapseRestElement<
119
118
  BackwardAccumulator extends UnknownArray = [],
120
119
  > =
121
120
  TArray extends UnknownArray // For distributing `TArray`
122
- ? keyof TArray & `${number}` extends never
123
- // Enters this branch, if `TArray` is empty (e.g., []),
124
- // or `TArray` contains no non-rest elements preceding the rest element (e.g., `[...string[]]` or `[...string[], string]`).
125
- ? TArray extends readonly [...infer Rest, infer Last]
126
- ? _CollapseRestElement<Rest, ForwardAccumulator, [Last, ...BackwardAccumulator]> // Accumulate elements that are present after the rest element.
127
- : TArray extends readonly []
128
- ? [...ForwardAccumulator, ...BackwardAccumulator]
129
- : [...ForwardAccumulator, TArray[number], ...BackwardAccumulator] // Add the rest element between the accumulated elements.
130
- : TArray extends readonly [(infer First)?, ...infer Rest]
121
+ ? '0' extends keyof TArray
122
+ // Enters this branch, if `TArray` starts with a non-rest element (e.g., `[string, number]` or `[string, ...number[]]`).
123
+ ? TArray extends readonly [(infer First)?, ...infer Rest]
131
124
  ? _CollapseRestElement<
132
125
  Rest,
133
126
  [
134
127
  ...ForwardAccumulator,
135
- '0' extends OptionalKeysOf<TArray>
136
- ? If<IsExactOptionalPropertyTypesEnabled, First, First | undefined> // Add `| undefined` for optional elements, if `exactOptionalPropertyTypes` is disabled.
137
- : First,
128
+ // A tuple allows fewer than one element only when its first element is optional. Written in exactly this shape because equivalent ones, such as `[] extends TArray`, are several times slower.
129
+ TArray extends readonly [unknown, ...unknown[]]
130
+ ? First
131
+ : If<IsExactOptionalPropertyTypesEnabled, First, First | undefined>, // Add `| undefined` for optional elements, if `exactOptionalPropertyTypes` is disabled.
138
132
  ],
139
133
  BackwardAccumulator
140
134
  >
141
135
  : never // Should never happen, since `[(infer First)?, ...infer Rest]` is a top-type for arrays.
136
+ // Enters this branch, if `TArray` is empty (e.g., []),
137
+ // or `TArray` contains no non-rest elements preceding the rest element (e.g., `[...string[]]` or `[...string[], string]`).
138
+ : TArray extends readonly [...infer Rest, infer Last]
139
+ ? _CollapseRestElement<Rest, ForwardAccumulator, [Last, ...BackwardAccumulator]> // Accumulate elements that are present after the rest element.
140
+ : TArray extends readonly []
141
+ ? [...ForwardAccumulator, ...BackwardAccumulator]
142
+ : [...ForwardAccumulator, TArray[number], ...BackwardAccumulator] // Add the rest element between the accumulated elements.
142
143
  : never; // Should never happen
143
144
 
144
145
  export {};
@@ -1,4 +1,3 @@
1
- import type {IsNever} from '../is-never.d.ts';
2
1
  import type {Finite, NegativeInfinity, PositiveInfinity} from '../numeric.d.ts';
3
2
  import type {UnknownArray} from '../unknown-array.d.ts';
4
3
  import type {IfNotAnyOrNever, IsAnyOrNever} from './type.d.ts';
@@ -69,43 +68,6 @@ type InternalUnionMin<N extends number, T extends UnknownArray = []> =
69
68
  ? T['length']
70
69
  : InternalUnionMin<N, [...T, unknown]>;
71
70
 
72
- /**
73
- Returns the maximum number in the given union of numbers.
74
-
75
- Note: Just supports numbers from 0 to 999.
76
-
77
- @example
78
- ```
79
- type A = UnionMax<1 | 3 | 2>;
80
- //=> 3
81
-
82
- type B = UnionMax<number>;
83
- //=> number
84
-
85
- type C = UnionMax<any>;
86
- //=> any
87
-
88
- type D = UnionMax<never>;
89
- //=> never
90
- ```
91
- */
92
- export type UnionMax<N extends number> =
93
- IsAnyOrNever<N> extends true ? N
94
- : number extends N ? number
95
- : PositiveInfinity extends N ? PositiveInfinity
96
- : [N] extends [NegativeInfinity] ? NegativeInfinity
97
- : InternalUnionMax<Finite<N>>;
98
-
99
- /**
100
- The actual implementation of `UnionMax`. It's private because it has some arguments that don't need to be exposed.
101
- */
102
- type InternalUnionMax<N extends number, T extends UnknownArray = []> =
103
- IsNever<N> extends true
104
- ? T['length']
105
- : T['length'] extends N
106
- ? InternalUnionMax<Exclude<N, T['length']>, T>
107
- : InternalUnionMax<N, [...T, unknown]>;
108
-
109
71
  /**
110
72
  Returns the number with reversed sign.
111
73
 
@@ -81,9 +81,9 @@ type _IsTuple<
81
81
  TArray extends unknown // For distributing `TArray`
82
82
  ? number extends TArray['length']
83
83
  ? Options['fixedLengthOnly'] extends false
84
- ? If<IsNever<keyof TArray & `${number}`>,
85
- TArray extends readonly [...any, any] ? true : false, // To handle cases where a non-rest element follows a rest element, e.g., `[...number[], number]`
86
- true>
84
+ ? '0' extends keyof TArray
85
+ ? true
86
+ : TArray extends readonly [...any, any] ? true : false // To handle cases where a non-rest element follows a rest element, e.g., `[...number[], number]`
87
87
  : false
88
88
  : true
89
89
  : false
@@ -18,9 +18,9 @@ type Writable<TArray extends UnknownArray> = {-readonly [Key in keyof TArray]: T
18
18
 
19
19
  // Using the default `ArrayTail` type causes issues, refer https://github.com/sindresorhus/type-fest/pull/1175/files#r2134694728.
20
20
  type ArrayTail<TArray extends UnknownArray> = TArray extends unknown // For distributing `TArray`
21
- ? keyof TArray & `${number}` extends never
22
- ? []
23
- : Writable<_ArrayTail<TArray>>
21
+ ? '0' extends keyof TArray
22
+ ? Writable<_ArrayTail<TArray>>
23
+ : []
24
24
  : never; // Should never happen
25
25
 
26
26
  type SimplifyDeepExcludeArray<T> = SimplifyDeep<T, UnknownArray>;
@@ -1,7 +1,6 @@
1
1
  import type {Except} from './except.d.ts';
2
2
  import type {If} from './if.d.ts';
3
3
  import type {HomomorphicPick, IsArrayReadonly} from './internal/index.d.ts';
4
- import type {OptionalKeysOf} from './optional-keys-of.d.ts';
5
4
  import type {Simplify} from './simplify.d.ts';
6
5
  import type {UnknownArray} from './unknown-array.d.ts';
7
6
 
@@ -57,19 +56,21 @@ type SetArrayRequired<
57
56
  Counter extends any[] = [],
58
57
  Accumulator extends UnknownArray = [],
59
58
  > = TArray extends unknown // For distributing `TArray` when it's a union
60
- ? keyof TArray & `${number}` extends never
61
- // Exit if `TArray` is empty (e.g., []), or
62
- // `TArray` contains no non-rest elements preceding the rest element (e.g., `[...string[]]` or `[...string[], string]`).
63
- ? [...Accumulator, ...TArray]
64
- : TArray extends readonly [(infer First)?, ...infer Rest]
65
- ? '0' extends OptionalKeysOf<TArray> // If the first element of `TArray` is optional
66
- ? `${Counter['length']}` extends `${Keys & (string | number)}` // If the current index needs to be required
59
+ ? '0' extends keyof TArray
60
+ ? TArray extends readonly [(infer First)?, ...infer Rest]
61
+ // A tuple allows fewer than one element only when its first element is optional. Written in exactly this shape because equivalent ones, such as `[] extends TArray`, are several times slower.
62
+ // Unlike the other array loops, this one has no `any` guard above it, so the check is wrapped in tuples to stop `any` from matching both branches.
63
+ ? [TArray] extends [readonly [unknown, ...unknown[]]]
64
+ ? SetArrayRequired<Rest, Keys, [...Counter, any], [...Accumulator, First]>
65
+ : `${Counter['length']}` extends `${Keys & (string | number)}` // If the current index needs to be required
67
66
  ? SetArrayRequired<Rest, Keys, [...Counter, any], [...Accumulator, First]>
68
67
  // If the current element is optional, but it doesn't need to be required,
69
68
  // then we can exit early, since no further elements can now be made required.
70
69
  : [...Accumulator, ...TArray]
71
- : SetArrayRequired<Rest, Keys, [...Counter, any], [...Accumulator, TArray[0]]>
72
70
  : never // Should never happen, since `[(infer F)?, ...infer R]` is a top-type for arrays.
71
+ // Exit if `TArray` is empty (e.g., []), or
72
+ // `TArray` contains no non-rest elements preceding the rest element (e.g., `[...string[]]` or `[...string[], string]`).
73
+ : [...Accumulator, ...TArray]
73
74
  : never; // Should never happen
74
75
 
75
76
  export {};
@@ -1,4 +1,5 @@
1
- import type {NonRecursiveType, UnionMin, UnionMax, TupleLength, StaticPartOfArray, VariablePartOfArray, IsArrayReadonly, SetArrayAccess, ApplyDefaultOptions} from './internal/index.d.ts';
1
+ import type {NonRecursiveType, UnionMin, TupleLength, StaticPartOfArray, VariablePartOfArray, IsArrayReadonly, SetArrayAccess, ApplyDefaultOptions} from './internal/index.d.ts';
2
+ import type {UnionMax} from './union-max.d.ts';
2
3
  import type {IsNever} from './is-never.d.ts';
3
4
  import type {UnknownArray} from './unknown-array.d.ts';
4
5
 
@@ -95,10 +95,15 @@ type B = SomeExtend<[1?, 2?, '3'?], string | undefined>;
95
95
  @category Array
96
96
  */
97
97
  export type SomeExtend<TArray extends UnknownArray, Type, Options extends SomeExtendOptions = {}> =
98
- _SomeExtend<CollapseRestElement<TArray>, Type, ApplyDefaultOptions<SomeExtendOptions, DefaultSomeExtendOptions, Options>>;
99
-
100
- type _SomeExtend<TArray extends UnknownArray, Type, Options extends Required<SomeExtendOptions>> = IfNotAnyOrNever<TArray, {
101
- ifNot: TArray extends readonly [infer First, ...infer Rest]
98
+ IfNotAnyOrNever<CollapseRestElement<TArray>, {
99
+ ifNot: _SomeExtend<CollapseRestElement<TArray>, Type, ApplyDefaultOptions<SomeExtendOptions, DefaultSomeExtendOptions, Options>>;
100
+ ifAny: false;
101
+ ifNever: false;
102
+ }>;
103
+
104
+ // Kept free of `IfNotAnyOrNever` so that it stays tail-recursive, which allows it to handle long arrays.
105
+ type _SomeExtend<TArray extends UnknownArray, Type, Options extends Required<SomeExtendOptions>> =
106
+ TArray extends readonly [infer First, ...infer Rest]
102
107
  ? IsNever<First> extends true
103
108
  ? Or<Or<IsNever<Type>, IsAny<Type>>, Not<Options['strictNever']>> extends true
104
109
  // If target `Type` is also `never`, or is `any`, or `strictNever` is disabled, return `true`.
@@ -108,8 +113,5 @@ type _SomeExtend<TArray extends UnknownArray, Type, Options extends Required<Som
108
113
  ? true
109
114
  : _SomeExtend<Rest, Type, Options>
110
115
  : false;
111
- ifAny: false;
112
- ifNever: false;
113
- }>;
114
116
 
115
117
  export {};
@@ -1,6 +1,5 @@
1
1
  import type {IfNotAnyOrNever, IsExactOptionalPropertyTypesEnabled} from './internal/type.d.ts';
2
2
  import type {ApplyDefaultOptions} from './internal/object.d.ts';
3
- import type {IsOptionalKeyOf} from './is-optional-key-of.d.ts';
4
3
  import type {IsArrayReadonly} from './internal/array.d.ts';
5
4
  import type {UnknownArray} from './unknown-array.d.ts';
6
5
  import type {If} from './if.d.ts';
@@ -84,25 +83,27 @@ export type _SplitOnRestElement<
84
83
  HeadAcc extends UnknownArray = [],
85
84
  TailAcc extends UnknownArray = [],
86
85
  > =
87
- keyof Array_ & `${number}` extends never
88
- // Enters this branch, if `Array_` is empty (e.g., []),
89
- // or `Array_` contains no non-rest elements preceding the rest element (e.g., `[...string[]]` or `[...string[], string]`).
90
- ? Array_ extends readonly [...infer Rest, infer Last]
91
- ? _SplitOnRestElement<Rest, Options, HeadAcc, [Last, ...TailAcc]> // Accumulate elements that are present after the rest element.
92
- : [HeadAcc, Array_ extends readonly [] ? [] : Array_, TailAcc] // Add the rest element between the accumulated elements.
93
- : Array_ extends readonly [(infer First)?, ...infer Rest]
86
+ '0' extends keyof Array_
87
+ // Enters this branch, if `Array_` starts with a non-rest element (e.g., `[string, number]` or `[string, ...number[]]`).
88
+ ? Array_ extends readonly [(infer First)?, ...infer Rest]
94
89
  ? _SplitOnRestElement<
95
90
  Rest, Options,
96
91
  [
97
92
  ...HeadAcc,
98
- ...IsOptionalKeyOf<Array_, '0'> extends true
99
- ? Options['preserveOptionalModifier'] extends false
93
+ // A tuple allows fewer than one element only when its first element is optional. Written in exactly this shape because equivalent ones, such as `[] extends Array_`, are several times slower.
94
+ ...Array_ extends readonly [unknown, ...unknown[]]
95
+ ? [First]
96
+ : Options['preserveOptionalModifier'] extends false
100
97
  ? [If<IsExactOptionalPropertyTypesEnabled, First, First | undefined>] // Add `| undefined` for optional elements, if `exactOptionalPropertyTypes` is disabled.
101
- : [First?]
102
- : [First],
98
+ : [First?],
103
99
  ],
104
100
  TailAcc
105
101
  > // Accumulate elements that are present before the rest element.
106
- : never; // Should never happen, since `[(infer First)?, ...infer Rest]` is a top-type for arrays.
102
+ : never // Should never happen, since `[(infer First)?, ...infer Rest]` is a top-type for arrays.
103
+ // Enters this branch, if `Array_` is empty (e.g., []),
104
+ // or `Array_` contains no non-rest elements preceding the rest element (e.g., `[...string[]]` or `[...string[], string]`).
105
+ : Array_ extends readonly [...infer Rest, infer Last]
106
+ ? _SplitOnRestElement<Rest, Options, HeadAcc, [Last, ...TailAcc]> // Accumulate elements that are present after the rest element.
107
+ : [HeadAcc, Array_ extends readonly [] ? [] : Array_, TailAcc]; // Add the rest element between the accumulated elements.
107
108
 
108
109
  export {};
package/source/split.d.ts CHANGED
@@ -64,27 +64,38 @@ export type Split<
64
64
  Delimiter extends string,
65
65
  Options extends SplitOptions = {},
66
66
  > =
67
- SplitHelper<S, Delimiter, ApplyDefaultOptions<SplitOptions, DefaultSplitOptions, Options>>;
67
+ _Split<S, Delimiter, ApplyDefaultOptions<SplitOptions, DefaultSplitOptions, Options>>;
68
68
 
69
- type SplitHelper<
69
+ type _Split<
70
70
  S extends string,
71
71
  Delimiter extends string,
72
72
  Options extends Required<SplitOptions>,
73
- Accumulator extends string[] = [],
74
73
  > = S extends string // For distributing `S`
75
74
  ? Delimiter extends string // For distributing `Delimiter`
76
75
  // If `strictLiteralChecks` is `false` OR `S` and `Delimiter` both are string literals, then perform the split
77
76
  ? Or<Not<Options['strictLiteralChecks']>, And<IsStringLiteral<S>, IsStringLiteral<Delimiter>>> extends true
78
- ? S extends `${infer Head}${Delimiter}${infer Tail}`
79
- ? SplitHelper<Tail, Delimiter, Options, [...Accumulator, Head]>
80
- : Delimiter extends ''
81
- ? S extends ''
82
- ? Accumulator
83
- : [...Accumulator, S]
84
- : [...Accumulator, S]
77
+ // The `extends infer` step keeps `SplitOnDelimiter` out of this conditional's tail-recursion chain, so the loop gets the full recursion budget to itself.
78
+ ? SplitOnDelimiter<S, Delimiter> extends infer Result ? Result : never
85
79
  // Otherwise, return `string[]`
86
80
  : string[]
87
81
  : never // Should never happen
88
82
  : never; // Should never happen
89
83
 
84
+ /**
85
+ Splits `S` on `Delimiter`.
86
+
87
+ `S` and `Delimiter` must already be distributed, so that the checks performed by `_Split` do not have to be repeated on every recursion step.
88
+ */
89
+ type SplitOnDelimiter<
90
+ S extends string,
91
+ Delimiter extends string,
92
+ Accumulator extends string[] = [],
93
+ > = S extends `${infer Head}${Delimiter}${infer Tail}`
94
+ ? SplitOnDelimiter<Tail, Delimiter, [...Accumulator, Head]>
95
+ : Delimiter extends ''
96
+ ? S extends ''
97
+ ? Accumulator
98
+ : [...Accumulator, S]
99
+ : [...Accumulator, S];
100
+
90
101
  export {};
@@ -1,6 +1,10 @@
1
+ import type {FindGlobalType} from './find-global-type.d.ts';
2
+
1
3
  /**
2
4
  Matches any [typed array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray), like `Uint8Array` or `Float64Array`.
3
5
 
6
+ `Float16Array` is included only when it exists in your TypeScript `lib` (`ESNext` or `ES2025` and later).
7
+
4
8
  @category Array
5
9
  */
6
10
  export type TypedArray =
@@ -11,7 +15,8 @@ export type TypedArray =
11
15
  | Uint16Array
12
16
  | Int32Array
13
17
  | Uint32Array
14
- | Float16Array
18
+ // Looked up through `globalThis` so that a `lib` without `Float16Array` gets `never` here instead of a compile error. The `prototype` type is `Float16Array<ArrayBufferLike>`, matching the other members.
19
+ | FindGlobalType<'Float16Array'>['prototype']
15
20
  | Float32Array
16
21
  | Float64Array
17
22
  | BigInt64Array
@@ -0,0 +1,56 @@
1
+ import type {IsNever} from './is-never.d.ts';
2
+ import type {Finite, NegativeInfinity, PositiveInfinity} from './numeric.d.ts';
3
+ import type {UnknownArray} from './unknown-array.d.ts';
4
+ import type {IsAnyOrNever} from './internal/type.d.ts';
5
+
6
+ /**
7
+ Returns the maximum number in a union of numbers.
8
+
9
+ Use this to derive a maximum retry count or concurrency limit from a fixed set of supported values.
10
+
11
+ Supports small non-negative integer literals, plus `PositiveInfinity` and `NegativeInfinity`. Negative finite numbers and fractional numbers are not supported. Large integers or unions can exceed TypeScript’s recursion limit.
12
+
13
+ Returns `number`, `any`, or `never` when given those types.
14
+
15
+ @example
16
+ ```
17
+ import type {UnionMax} from 'type-fest';
18
+
19
+ const retryCounts = [0, 2, 5] as const;
20
+ type MaximumRetries = UnionMax<typeof retryCounts[number]>;
21
+ //=> 5
22
+
23
+ const maximumRetries: MaximumRetries = 5;
24
+ ```
25
+
26
+ @example
27
+ ```
28
+ import type {PositiveInfinity, UnionMax} from 'type-fest';
29
+
30
+ type Unlimited = UnionMax<1 | 5 | PositiveInfinity>;
31
+ //=> Infinity
32
+ ```
33
+
34
+ The implementation counts upward using a tuple, removing each matching union member until none remain. Infinity and non-literal inputs are handled before counting.
35
+
36
+ @see https://github.com/sindresorhus/type-fest/issues/676
37
+ @category Numeric
38
+ */
39
+ export type UnionMax<NumberUnion extends number> =
40
+ IsAnyOrNever<NumberUnion> extends true ? NumberUnion
41
+ : number extends NumberUnion ? number
42
+ : PositiveInfinity extends NumberUnion ? PositiveInfinity
43
+ : [NumberUnion] extends [NegativeInfinity] ? NegativeInfinity
44
+ : InternalUnionMax<Finite<NumberUnion>>;
45
+
46
+ /**
47
+ The actual implementation of `UnionMax`. It's private because it has some arguments that don't need to be exposed.
48
+ */
49
+ type InternalUnionMax<NumberUnion extends number, Counter extends UnknownArray = []> =
50
+ IsNever<NumberUnion> extends true
51
+ ? Counter['length']
52
+ : Counter['length'] extends NumberUnion
53
+ ? InternalUnionMax<Exclude<NumberUnion, Counter['length']>, Counter>
54
+ : InternalUnionMax<NumberUnion, [...Counter, unknown]>;
55
+
56
+ export {};