type-fest 4.11.0 → 4.12.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/index.d.ts CHANGED
@@ -46,6 +46,7 @@ export type {ConditionalPick} from './source/conditional-pick';
46
46
  export type {ConditionalPickDeep, ConditionalPickDeepOptions} from './source/conditional-pick-deep';
47
47
  export type {UnionToIntersection} from './source/union-to-intersection';
48
48
  export type {Stringified} from './source/stringified';
49
+ export type {StringSlice} from './source/string-slice';
49
50
  export type {FixedLengthArray} from './source/fixed-length-array';
50
51
  export type {MultidimensionalArray} from './source/multidimensional-array';
51
52
  export type {MultidimensionalReadonlyArray} from './source/multidimensional-readonly-array';
@@ -72,7 +73,14 @@ export type {
72
73
  NonNegative,
73
74
  NegativeInteger,
74
75
  NonNegativeInteger,
76
+ IsNegative,
75
77
  } from './source/numeric';
78
+ export type {GreaterThan} from './source/greater-than';
79
+ export type {GreaterThanOrEqual} from './source/greater-than-or-equal';
80
+ export type {LessThan} from './source/less-than';
81
+ export type {LessThanOrEqual} from './source/less-than-or-equal';
82
+ export type {Sum} from './source/sum';
83
+ export type {Subtract} from './source/subtract';
76
84
  export type {StringKeyOf} from './source/string-key-of';
77
85
  export type {Exact} from './source/exact';
78
86
  export type {ReadonlyTuple} from './source/readonly-tuple';
@@ -104,6 +112,7 @@ export type {IsUnknown} from './source/is-unknown';
104
112
  export type {IfUnknown} from './source/if-unknown';
105
113
  export type {ArrayIndices} from './source/array-indices';
106
114
  export type {ArrayValues} from './source/array-values';
115
+ export type {ArraySlice} from './source/array-slice';
107
116
  export type {ArraySplice} from './source/array-splice';
108
117
  export type {SetFieldType} from './source/set-field-type';
109
118
  export type {Paths} from './source/paths';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "type-fest",
3
- "version": "4.11.0",
3
+ "version": "4.12.0",
4
4
  "description": "A collection of essential TypeScript types",
5
5
  "license": "(MIT OR CC0-1.0)",
6
6
  "repository": "sindresorhus/type-fest",
package/readme.md CHANGED
@@ -239,11 +239,13 @@ type ShouldBeNever = IfAny<'not any', 'not never', 'never'>;
239
239
  - [`Trim`](source/trim.d.ts) - Remove leading and trailing spaces from a string.
240
240
  - [`Split`](source/split.d.ts) - Represents an array of strings split using a given character or character set.
241
241
  - [`Replace`](source/replace.d.ts) - Represents a string with some or all matches replaced by a replacement.
242
+ - [`StringSlice`](source/string-slice.d.ts) - Returns a string slice of a given range, just like `String#slice()`.
242
243
 
243
244
  ### Array
244
245
 
245
246
  - [`Includes`](source/includes.d.ts) - Returns a boolean for whether the given array includes the given item.
246
247
  - [`Join`](source/join.d.ts) - Join an array of strings and/or numbers using the given string as a delimiter.
248
+ - [`ArraySlice`](source/array-slice.d.ts) - Returns an array slice of a given range, just like `Array#slice()`.
247
249
  - [`LastArrayElement`](source/last-array-element.d.ts) - Extracts the type of the last element of an array.
248
250
  - [`FixedLengthArray`](source/fixed-length-array.d.ts) - Create a type that represents an array of the given type and length.
249
251
  - [`MultidimensionalArray`](source/multidimensional-array.d.ts) - Create a type that represents a multidimensional array of the given type and dimensions.
@@ -263,6 +265,13 @@ type ShouldBeNever = IfAny<'not any', 'not never', 'never'>;
263
265
  - [`NonNegative`](source/numeric.d.ts) - A non-negative `number`/`bigint` (`0 <= x < ∞`).
264
266
  - [`NegativeInteger`](source/numeric.d.ts) - A negative (`-∞ < x < 0`) `number` that is an integer.
265
267
  - [`NonNegativeInteger`](source/numeric.d.ts) - A non-negative (`0 <= x < ∞`) `number` that is an integer.
268
+ - [`IsNegative`](source/numeric.d.ts) - Returns a boolean for whether the given number is a negative number.
269
+ - [`GreaterThan`](source/greater-than.d.ts) - Returns a boolean for whether a given number is greater than another number.
270
+ - [`GreaterThanOrEqual`](source/greater-than-or-equal.d.ts) - Returns a boolean for whether a given number is greater than or equal to another number.
271
+ - [`LessThan`](source/less-than.d.ts) - Returns a boolean for whether a given number is less than another number.
272
+ - [`LessThanOrEqual`](source/less-than-or-equal.d.ts) - Returns a boolean for whether a given number is less than or equal to another number.
273
+ - [`Sum`](source/sum.d.ts) - Returns the sum of two numbers.
274
+ - [`Subtract`](source/subtract.d.ts) - Returns the difference between two numbers.
266
275
 
267
276
  ### Change case
268
277
 
@@ -0,0 +1,93 @@
1
+ import type {Sum} from './sum';
2
+ import type {LessThan} from './less-than';
3
+ import type {LessThanOrEqual} from './less-than-or-equal';
4
+ import type {IsNegative} from './numeric';
5
+ import type {And} from './internal';
6
+ import type {IsEqual} from './is-equal';
7
+
8
+ /**
9
+ Returns an array slice of a given range, just like `Array#slice()`.
10
+
11
+ @example
12
+ ```
13
+ import type {ArraySlice} from 'type-fest';
14
+
15
+ type T0 = ArraySlice<[0, 1, 2, 3, 4]>;
16
+ //=> [0, 1, 2, 3, 4]
17
+
18
+ type T1 = ArraySlice<[0, 1, 2, 3, 4], 0, -1>;
19
+ //=> [0, 1, 2, 3]
20
+
21
+ type T2 = ArraySlice<[0, 1, 2, 3, 4], 1, -2>;
22
+ //=> [1, 2]
23
+
24
+ type T3 = ArraySlice<[0, 1, 2, 3, 4], -2, 4>;
25
+ //=> [3]
26
+
27
+ type T4 = ArraySlice<[0, 1, 2, 3, 4], -2, -1>;
28
+ //=> [3]
29
+
30
+ type T5 = ArraySlice<[0, 1, 2, 3, 4], 0, -999>;
31
+ //=> []
32
+
33
+ function arraySlice<
34
+ const Array_ extends readonly unknown[],
35
+ Start extends number = 0,
36
+ End extends number = Array_['length'],
37
+ >(array: Array_, start?: Start, end?: End) {
38
+ return array.slice(start, end) as ArraySlice<Array_, Start, End>;
39
+ }
40
+
41
+ const slice = arraySlice([1, '2', {a: 3}, [4, 5]], 0, -1);
42
+
43
+ typeof slice;
44
+ //=> [1, '2', { readonly a: 3; }]
45
+
46
+ slice[2].a;
47
+ //=> 3
48
+
49
+ // @ts-expect-error -- TS2493: Tuple type '[1, "2", {readonly a: 3}]' of length '3' has no element at index '3'.
50
+ slice[3];
51
+ ```
52
+
53
+ @category Array
54
+ */
55
+ export type ArraySlice<
56
+ Array_ extends readonly unknown[],
57
+ Start extends number = 0,
58
+ End extends number = Array_['length'],
59
+ > = ArraySliceHelper<Array_, Start, End>;
60
+
61
+ type ArraySliceHelper<
62
+ Array_ extends readonly unknown[],
63
+ Start extends number = 0,
64
+ End extends number = Array_['length'],
65
+ TraversedElement extends Array<Array_[number]> = [],
66
+ Result extends Array<Array_[number]> = [],
67
+ ArrayLength extends number = Array_['length'],
68
+ PositiveS extends number = IsNegative<Start> extends true
69
+ ? Sum<ArrayLength, Start> extends infer AddResult extends number
70
+ ? number extends AddResult // (ArrayLength + Start) < 0
71
+ ? 0
72
+ : AddResult
73
+ : never
74
+ : Start,
75
+ PositiveE extends number = IsNegative<End> extends true ? Sum<ArrayLength, End> : End,
76
+ > = true extends [IsNegative<PositiveS>, LessThanOrEqual<PositiveE, PositiveS>][number]
77
+ ? []
78
+ : ArraySliceByPositiveIndex<Array_, PositiveS, PositiveE>;
79
+
80
+ type ArraySliceByPositiveIndex<
81
+ Array_ extends readonly unknown[],
82
+ Start extends number,
83
+ End extends number,
84
+ TraversedElement extends Array<Array_[number]> = [],
85
+ Result extends Array<Array_[number]> = [],
86
+ > = Array_ extends readonly [infer H, ...infer Rest]
87
+ ? And<
88
+ IsEqual<LessThanOrEqual<Start, TraversedElement['length']>, true>,
89
+ IsEqual<LessThan<TraversedElement['length'], End>, true>
90
+ > extends true
91
+ ? ArraySliceByPositiveIndex<Rest, Start, End, [...TraversedElement, H], [...Result, H]>
92
+ : ArraySliceByPositiveIndex<Rest, Start, End, [...TraversedElement, H], Result>
93
+ : Result;
@@ -1,4 +1,6 @@
1
- import type {BuildTuple, Subtract, StaticPartOfArray, VariablePartOfArray, GTE} from './internal';
1
+ import type {BuildTuple, StaticPartOfArray, VariablePartOfArray} from './internal';
2
+ import type {GreaterThanOrEqual} from './greater-than-or-equal';
3
+ import type {Subtract} from './subtract';
2
4
  import type {UnknownArray} from './unknown-array';
3
5
 
4
6
  /**
@@ -23,7 +25,7 @@ type SplitVariableArrayByIndex<T extends UnknownArray,
23
25
  > =
24
26
  SplitIndex extends 0
25
27
  ? [[], T]
26
- : GTE<StaticPartOfArray<T>['length'], SplitIndex> extends true
28
+ : GreaterThanOrEqual<StaticPartOfArray<T>['length'], SplitIndex> extends true
27
29
  ? [
28
30
  SplitFixedArrayByIndex<StaticPartOfArray<T>, SplitIndex>[0],
29
31
  [
@@ -0,0 +1,22 @@
1
+ import type {GreaterThan} from './greater-than';
2
+
3
+ /**
4
+ Returns a boolean for whether a given number is greater than or equal to another number.
5
+
6
+ @example
7
+ ```
8
+ import type {GreaterThanOrEqual} from 'type-fest';
9
+
10
+ GreaterThanOrEqual<1, -5>;
11
+ //=> true
12
+
13
+ GreaterThanOrEqual<1, 1>;
14
+ //=> true
15
+
16
+ GreaterThanOrEqual<1, 5>;
17
+ //=> false
18
+ ```
19
+ */
20
+ export type GreaterThanOrEqual<A extends number, B extends number> = number extends A | B
21
+ ? never
22
+ : A extends B ? true : GreaterThan<A, B>;
@@ -0,0 +1,49 @@
1
+ import type {NumberAbsolute, And, Or, PositiveNumericStringGt} from './internal';
2
+ import type {IsEqual} from './is-equal';
3
+ import type {PositiveInfinity, NegativeInfinity, IsNegative} from './numeric';
4
+
5
+ /**
6
+ Returns a boolean for whether a given number is greater than another number.
7
+
8
+ @example
9
+ ```
10
+ import type {GreaterThan} from 'type-fest';
11
+
12
+ GreaterThan<1, -5>;
13
+ //=> true
14
+
15
+ GreaterThan<1, 1>;
16
+ //=> false
17
+
18
+ GreaterThan<1, 5>;
19
+ //=> false
20
+ ```
21
+ */
22
+ export type GreaterThan<A extends number, B extends number> = number extends A | B
23
+ ? never
24
+ : [
25
+ IsEqual<A, PositiveInfinity>, IsEqual<A, NegativeInfinity>,
26
+ IsEqual<B, PositiveInfinity>, IsEqual<B, NegativeInfinity>,
27
+ ] extends infer R extends [boolean, boolean, boolean, boolean]
28
+ ? Or<
29
+ And<IsEqual<R[0], true>, IsEqual<R[2], false>>,
30
+ And<IsEqual<R[3], true>, IsEqual<R[1], false>>
31
+ > extends true
32
+ ? true
33
+ : Or<
34
+ And<IsEqual<R[1], true>, IsEqual<R[3], false>>,
35
+ And<IsEqual<R[2], true>, IsEqual<R[0], false>>
36
+ > extends true
37
+ ? false
38
+ : true extends R[number]
39
+ ? false
40
+ : [IsNegative<A>, IsNegative<B>] extends infer R extends [boolean, boolean]
41
+ ? [true, false] extends R
42
+ ? false
43
+ : [false, true] extends R
44
+ ? true
45
+ : [false, false] extends R
46
+ ? PositiveNumericStringGt<`${A}`, `${B}`>
47
+ : PositiveNumericStringGt<`${NumberAbsolute<B>}`, `${NumberAbsolute<A>}`>
48
+ : never
49
+ : never;
@@ -1,4 +1,5 @@
1
- import type {BuildTuple, Subtract} from './internal';
1
+ import type {BuildTuple} from './internal';
2
+ import type {Subtract} from './subtract';
2
3
 
3
4
  /**
4
5
  Generate a union of numbers.
@@ -2,6 +2,9 @@ import type {Primitive} from './primitive';
2
2
  import type {Simplify} from './simplify';
3
3
  import type {Trim} from './trim';
4
4
  import type {IsAny} from './is-any';
5
+ import type {NegativeInfinity, PositiveInfinity} from './numeric';
6
+ import type {GreaterThan} from './greater-than';
7
+ import type {LessThan} from './less-than';
5
8
  import type {IsLiteral} from './is-literal';
6
9
  import type {UnknownRecord} from './unknown-record';
7
10
  import type {IsNever} from './is-never';
@@ -52,7 +55,7 @@ If `<Fill>` is not provided, it will default to `unknown`.
52
55
 
53
56
  @link https://itnext.io/implementing-arithmetic-within-typescripts-type-system-a1ef140a6f6f
54
57
  */
55
- export type BuildTuple<L extends number, Fill = unknown, T extends readonly unknown[] = []> = T extends {readonly length: L}
58
+ export type BuildTuple<L extends number, Fill = unknown, T extends readonly unknown[] = []> = T['length'] extends L
56
59
  ? T
57
60
  : BuildTuple<L, Fill, [...T, Fill]>;
58
61
 
@@ -87,16 +90,6 @@ Note: This type is not the return type of the `.toString()` function.
87
90
  */
88
91
  export type ToString<T> = T extends string | number ? `${T}` : never;
89
92
 
90
- /**
91
- Create a tuple of length `A` and a tuple composed of two other tuples,
92
- the inferred tuple `U` and a tuple of length `B`, then extracts the length of tuple `U`.
93
-
94
- @link https://itnext.io/implementing-arithmetic-within-typescripts-type-system-a1ef140a6f6f
95
- */
96
- export type Subtract<A extends number, B extends number> = BuildTuple<A> extends [...(infer U), ...BuildTuple<B>]
97
- ? ArrayLength<U>
98
- : never;
99
-
100
93
  /**
101
94
  Matches any primitive, `void`, `Date`, or `RegExp` value.
102
95
  */
@@ -117,6 +110,108 @@ export type IsPlainObject<T> =
117
110
  ? true
118
111
  : false;
119
112
 
113
+ /**
114
+ Converts a numeric string to a number.
115
+
116
+ @example
117
+ ```
118
+ type PositiveInt = StringToNumber<'1234'>;
119
+ //=> 1234
120
+
121
+ type NegativeInt = StringToNumber<'-1234'>;
122
+ //=> -1234
123
+
124
+ type PositiveFloat = StringToNumber<'1234.56'>;
125
+ //=> 1234.56
126
+
127
+ type NegativeFloat = StringToNumber<'-1234.56'>;
128
+ //=> -1234.56
129
+
130
+ type PositiveInfinity = StringToNumber<'Infinity'>;
131
+ //=> Infinity
132
+
133
+ type NegativeInfinity = StringToNumber<'-Infinity'>;
134
+ //=> -Infinity
135
+ ```
136
+
137
+ @category String
138
+ @category Numeric
139
+ @category Template literal
140
+ */
141
+ export type StringToNumber<S extends string> = S extends `${infer N extends number}`
142
+ ? N
143
+ : S extends 'Infinity'
144
+ ? PositiveInfinity
145
+ : S extends '-Infinity'
146
+ ? NegativeInfinity
147
+ : never;
148
+
149
+ /**
150
+ Returns a boolean for whether the given string `S` starts with the given string `SearchString`.
151
+
152
+ @example
153
+ ```
154
+ StartsWith<'abcde', 'abc'>;
155
+ //=> true
156
+
157
+ StartsWith<'abcde', 'bc'>;
158
+ //=> false
159
+
160
+ StartsWith<string, 'bc'>;
161
+ //=> never
162
+
163
+ StartsWith<'abcde', string>;
164
+ //=> never
165
+ ```
166
+
167
+ @category String
168
+ @category Template literal
169
+ */
170
+ export type StartsWith<S extends string, SearchString extends string> = string extends S | SearchString
171
+ ? never
172
+ : S extends `${SearchString}${infer T}`
173
+ ? true
174
+ : false;
175
+
176
+ /**
177
+ Returns the length of the given string.
178
+
179
+ @example
180
+ ```
181
+ StringLength<'abcde'>;
182
+ //=> 5
183
+
184
+ StringLength<string>;
185
+ //=> never
186
+ ```
187
+
188
+ @category String
189
+ @category Template literal
190
+ */
191
+ export type StringLength<S extends string> = string extends S
192
+ ? never
193
+ : StringToArray<S>['length'];
194
+
195
+ /**
196
+ Returns an array of the characters of the string.
197
+
198
+ @example
199
+ ```
200
+ StringToArray<'abcde'>;
201
+ //=> ['a', 'b', 'c', 'd', 'e']
202
+
203
+ StringToArray<string>;
204
+ //=> never
205
+ ```
206
+
207
+ @category String
208
+ */
209
+ export type StringToArray<S extends string, Result extends string[] = []> = string extends S
210
+ ? never
211
+ : S extends `${infer F}${infer R}`
212
+ ? StringToArray<R, [...Result, F]>
213
+ : Result;
214
+
120
215
  export type UpperCaseCharacters = 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | 'J' | 'K' | 'L' | 'M' | 'N' | 'O' | 'P' | 'Q' | 'R' | 'S' | 'T' | 'U' | 'V' | 'W' | 'X' | 'Y' | 'Z';
121
216
 
122
217
  export type StringDigit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9';
@@ -359,6 +454,190 @@ IsPrimitive<Object>
359
454
  */
360
455
  export type IsPrimitive<T> = [T] extends [Primitive] ? true : false;
361
456
 
457
+ /**
458
+ Returns a boolean for whether A and B are both true.
459
+
460
+ @example
461
+ ```
462
+ And<true, true>;
463
+ //=> true
464
+
465
+ And<true, false>;
466
+ //=> false
467
+ ```
468
+ */
469
+ export type And<A extends boolean, B extends boolean> = [A, B][number] extends true
470
+ ? true
471
+ : true extends [IsEqual<A, false>, IsEqual<B, false>][number]
472
+ ? false
473
+ : never;
474
+
475
+ /**
476
+ Returns a boolean for either A or B is true.
477
+
478
+ @example
479
+ ```
480
+ Or<true, false>;
481
+ //=> true
482
+
483
+ Or<false, false>;
484
+ //=> false
485
+ ```
486
+ */
487
+ export type Or<A extends boolean, B extends boolean> = [A, B][number] extends false
488
+ ? false
489
+ : true extends [IsEqual<A, true>, IsEqual<B, true>][number]
490
+ ? true
491
+ : never;
492
+
493
+ /**
494
+ Returns a boolean for whether A is false.
495
+
496
+ @example
497
+ ```
498
+ Not<true>;
499
+ //=> false
500
+
501
+ Not<false>;
502
+ //=> true
503
+ ```
504
+ */
505
+ export type Not<A extends boolean> = A extends true
506
+ ? false
507
+ : A extends false
508
+ ? true
509
+ : never;
510
+
511
+ /**
512
+ Returns the maximum value from a tuple of integers.
513
+
514
+ Note:
515
+ - Float numbers are not supported.
516
+
517
+ @example
518
+ ```
519
+ ArrayMax<[1, 2, 5, 3]>;
520
+ //=> 5
521
+
522
+ ArrayMax<[1, 2, 5, 3, 99, -1]>;
523
+ //=> 99
524
+ ```
525
+ */
526
+ export type ArrayMax<A extends number[], Result extends number = NegativeInfinity> = number extends A[number]
527
+ ? never :
528
+ A extends [infer F extends number, ...infer R extends number[]]
529
+ ? GreaterThan<F, Result> extends true
530
+ ? ArrayMax<R, F>
531
+ : ArrayMax<R, Result>
532
+ : Result;
533
+
534
+ /**
535
+ Returns the minimum value from a tuple of integers.
536
+
537
+ Note:
538
+ - Float numbers are not supported.
539
+
540
+ @example
541
+ ```
542
+ ArrayMin<[1, 2, 5, 3]>;
543
+ //=> 1
544
+
545
+ ArrayMin<[1, 2, 5, 3, -5]>;
546
+ //=> -5
547
+ ```
548
+ */
549
+ export type ArrayMin<A extends number[], Result extends number = PositiveInfinity> = number extends A[number]
550
+ ? never
551
+ : A extends [infer F extends number, ...infer R extends number[]]
552
+ ? LessThan<F, Result> extends true
553
+ ? ArrayMin<R, F>
554
+ : ArrayMin<R, Result>
555
+ : Result;
556
+
557
+ /**
558
+ Returns the absolute value of a given value.
559
+
560
+ @example
561
+ ```
562
+ NumberAbsolute<-1>;
563
+ //=> 1
564
+
565
+ NumberAbsolute<1>;
566
+ //=> 1
567
+
568
+ NumberAbsolute<NegativeInfinity>
569
+ //=> PositiveInfinity
570
+ ```
571
+ */
572
+ export type NumberAbsolute<N extends number> = `${N}` extends `-${infer StringPositiveN}` ? StringToNumber<StringPositiveN> : N;
573
+
574
+ /**
575
+ Returns a boolean for whether `A` represents a number greater than `B`, where `A` and `B` are both numeric strings and have the same length.
576
+
577
+ @example
578
+ ```
579
+ SameLengthPositiveNumericStringGt<'50', '10'>;
580
+ //=> true
581
+
582
+ SameLengthPositiveNumericStringGt<'10', '10'>;
583
+ //=> false
584
+ ```
585
+ */
586
+ type SameLengthPositiveNumericStringGt<A extends string, B extends string> = A extends `${infer FirstA}${infer RestA}`
587
+ ? B extends `${infer FirstB}${infer RestB}`
588
+ ? FirstA extends FirstB
589
+ ? SameLengthPositiveNumericStringGt<RestA, RestB>
590
+ : PositiveNumericCharacterGt<FirstA, FirstB>
591
+ : never
592
+ : false;
593
+
594
+ type NumericString = '0123456789';
595
+
596
+ /**
597
+ Returns a boolean for whether `A` is greater than `B`, where `A` and `B` are both positive numeric strings.
598
+
599
+ @example
600
+ ```
601
+ PositiveNumericStringGt<'500', '1'>;
602
+ //=> true
603
+
604
+ PositiveNumericStringGt<'1', '1'>;
605
+ //=> false
606
+
607
+ PositiveNumericStringGt<'1', '500'>;
608
+ //=> false
609
+ ```
610
+ */
611
+ export type PositiveNumericStringGt<A extends string, B extends string> = A extends B
612
+ ? false
613
+ : [BuildTuple<StringLength<A>, 0>, BuildTuple<StringLength<B>, 0>] extends infer R extends [readonly unknown[], readonly unknown[]]
614
+ ? R[0] extends [...R[1], ...infer Remain extends readonly unknown[]]
615
+ ? 0 extends Remain['length']
616
+ ? SameLengthPositiveNumericStringGt<A, B>
617
+ : true
618
+ : false
619
+ : never;
620
+
621
+ /**
622
+ Returns a boolean for whether `A` represents a number greater than `B`, where `A` and `B` are both positive numeric characters.
623
+
624
+ @example
625
+ ```
626
+ PositiveNumericCharacterGt<'5', '1'>;
627
+ //=> true
628
+
629
+ PositiveNumericCharacterGt<'1', '1'>;
630
+ //=> false
631
+ ```
632
+ */
633
+ type PositiveNumericCharacterGt<A extends string, B extends string> = NumericString extends `${infer HeadA}${A}${infer TailA}`
634
+ ? NumericString extends `${infer HeadB}${B}${infer TailB}`
635
+ ? HeadA extends `${HeadB}${infer _}${infer __}`
636
+ ? true
637
+ : false
638
+ : never
639
+ : never;
640
+
362
641
  /**
363
642
  Utility type to retrieve only literal keys from type.
364
643
  */
@@ -506,42 +785,6 @@ Returns whether the given array `T` is readonly.
506
785
  */
507
786
  export type IsArrayReadonly<T extends UnknownArray> = T extends unknown[] ? false : true;
508
787
 
509
- /**
510
- Returns the result of `A >= B`.
511
-
512
- @example
513
- ```
514
- type A = GTE<15, 10>;
515
- //=> true
516
-
517
- type B = GTE<10, 15>;
518
- //=> false
519
-
520
- type C = GTE<10, 10>;
521
- //=> true
522
- ```
523
- */
524
- export type GTE<A extends number, B extends number> =
525
- BuildTuple<A> extends [...infer _, ...BuildTuple<B>]
526
- ? true
527
- : false;
528
-
529
- /**
530
- Returns the result of `A > B`
531
-
532
- @example
533
- ```
534
- type A = GT<15, 10>;
535
- //=> true
536
-
537
- type B = GT<10, 15>;
538
- //=> false
539
- */
540
- export type GT<A extends number, B extends number> =
541
- IsEqual<A, B> extends true
542
- ? false
543
- : GTE<A, B>;
544
-
545
788
  /**
546
789
  Get the exact version of the given `Key` in the given object `T`.
547
790
 
@@ -0,0 +1,22 @@
1
+ import type {GreaterThan} from './greater-than';
2
+
3
+ /**
4
+ Returns a boolean for whether a given number is less than or equal to another number.
5
+
6
+ @example
7
+ ```
8
+ import type {LessThanOrEqual} from 'type-fest';
9
+
10
+ LessThanOrEqual<1, -5>;
11
+ //=> false
12
+
13
+ LessThanOrEqual<1, 1>;
14
+ //=> true
15
+
16
+ LessThanOrEqual<1, 5>;
17
+ //=> true
18
+ ```
19
+ */
20
+ export type LessThanOrEqual<A extends number, B extends number> = number extends A | B
21
+ ? never
22
+ : GreaterThan<A, B> extends true ? false : true;
@@ -0,0 +1,22 @@
1
+ import type {GreaterThanOrEqual} from './greater-than-or-equal';
2
+
3
+ /**
4
+ Returns a boolean for whether a given number is less than another number.
5
+
6
+ @example
7
+ ```
8
+ import type {LessThan} from 'type-fest';
9
+
10
+ LessThan<1, -5>;
11
+ //=> false
12
+
13
+ LessThan<1, 1>;
14
+ //=> false
15
+
16
+ LessThan<1, 5>;
17
+ //=> true
18
+ ```
19
+ */
20
+ export type LessThan<A extends number, B extends number> = number extends A | B
21
+ ? never
22
+ : GreaterThanOrEqual<A, B> extends true ? false : true;
@@ -15,7 +15,7 @@ import type {EnforceOptional} from './enforce-optional';
15
15
  /**
16
16
  Deeply simplifies an object excluding iterables and functions. Used internally to improve the UX and accept both interfaces and type aliases as inputs.
17
17
  */
18
- type SimplifyDeep<Type> = ConditionalSimplifyDeep<Type, Function | Iterable<unknown>, object>;
18
+ export type SimplifyDeep<Type> = ConditionalSimplifyDeep<Type, Function | Iterable<unknown>, object>;
19
19
 
20
20
  /**
21
21
  Try to merge two record properties or return the source property value, preserving `undefined` properties values in both cases.
@@ -1,4 +1,4 @@
1
- import type {Subtract} from './internal';
1
+ import type {Subtract} from './subtract';
2
2
  import type {IsEqual} from './is-equal';
3
3
 
4
4
  type Recursive<T> = Array<Recursive<T>>;
@@ -1,4 +1,4 @@
1
- import type {Subtract} from './internal';
1
+ import type {Subtract} from './subtract';
2
2
  import type {IsEqual} from './is-equal';
3
3
 
4
4
  type Recursive<T> = ReadonlyArray<Recursive<T>>;
@@ -168,3 +168,20 @@ declare function setLength<T extends number>(length: NonNegativeInteger<T>): voi
168
168
  @category Numeric
169
169
  */
170
170
  export type NonNegativeInteger<T extends number> = NonNegative<Integer<T>>;
171
+
172
+ /**
173
+ Returns a boolean for whether the given number is a negative number.
174
+
175
+ @see Negative
176
+
177
+ @example
178
+ ```
179
+ import type {IsNegative} from 'type-fest';
180
+
181
+ type ShouldBeFalse = IsNegative<1>;
182
+ type ShouldBeTrue = IsNegative<-1>;
183
+ ```
184
+
185
+ @category Numeric
186
+ */
187
+ export type IsNegative<T extends Numeric> = T extends Negative<T> ? true : false;
@@ -0,0 +1,37 @@
1
+ import type {Join} from './join';
2
+ import type {ArraySlice} from './array-slice';
3
+ import type {StringToArray} from './internal';
4
+
5
+ /**
6
+ Returns a string slice of a given range, just like `String#slice()`.
7
+
8
+ @see {ArraySlice}
9
+
10
+ @example
11
+ ```
12
+ import type {StringSlice} from 'type-fest';
13
+
14
+ StringSlice<'abcde', 0, 2>;
15
+ //=> 'ab'
16
+
17
+ StringSlice<'abcde', 1>;
18
+ //=> 'bcde'
19
+
20
+ StringSlice<'abcde', 0, -1>;
21
+ //=> 'abcd'
22
+
23
+ StringSlice<'abcde', -2, -1>;
24
+ //=> 'd'
25
+ ```
26
+
27
+ @category String
28
+ */
29
+ export type StringSlice<
30
+ S extends string,
31
+ Start extends number = 0,
32
+ End extends number = StringToArray<S>['length'],
33
+ > = string extends S
34
+ ? string[]
35
+ : ArraySlice<StringToArray<S>, Start, End> extends infer R extends readonly string[]
36
+ ? Join<R, ''>
37
+ : never;
@@ -0,0 +1,66 @@
1
+ import type {NumberAbsolute, BuildTuple, And, Or} from './internal';
2
+ import type {IsEqual} from './is-equal';
3
+ import type {PositiveInfinity, NegativeInfinity, IsNegative} from './numeric';
4
+ import type {LessThan} from './less-than';
5
+ import type {Sum} from './sum';
6
+
7
+ /**
8
+ Returns the difference between two numbers.
9
+
10
+ Note:
11
+ - A or B can only support `-999` ~ `999`.
12
+ - If the result is negative, you can only get `number`.
13
+
14
+ @example
15
+ ```
16
+ import type {Subtract} from 'type-fest';
17
+
18
+ Subtract<333, 222>;
19
+ //=> 111
20
+
21
+ Subtract<111, -222>;
22
+ //=> 333
23
+
24
+ Subtract<-111, 222>;
25
+ //=> number
26
+
27
+ Subtract<PositiveInfinity, 9999>;
28
+ //=> PositiveInfinity
29
+
30
+ Subtract<PositiveInfinity, PositiveInfinity>;
31
+ //=> number
32
+ ```
33
+
34
+ @category Numeric
35
+ */
36
+ // TODO: Support big integer and negative number.
37
+ export type Subtract<A extends number, B extends number> = [
38
+ IsEqual<A, PositiveInfinity>, IsEqual<A, NegativeInfinity>,
39
+ IsEqual<B, PositiveInfinity>, IsEqual<B, NegativeInfinity>,
40
+ ] extends infer R extends [boolean, boolean, boolean, boolean]
41
+ ? Or<
42
+ And<IsEqual<R[0], true>, IsEqual<R[2], false>>,
43
+ And<IsEqual<R[3], true>, IsEqual<R[1], false>>
44
+ > extends true
45
+ ? PositiveInfinity
46
+ : Or<
47
+ And<IsEqual<R[1], true>, IsEqual<R[3], false>>,
48
+ And<IsEqual<R[2], true>, IsEqual<R[0], false>>
49
+ > extends true
50
+ ? NegativeInfinity
51
+ : true extends R[number]
52
+ ? number
53
+ : [IsNegative<A>, IsNegative<B>] extends infer R
54
+ ? [false, false] extends R
55
+ ? BuildTuple<A> extends infer R
56
+ ? R extends [...BuildTuple<B>, ...infer R]
57
+ ? R['length']
58
+ : number
59
+ : never
60
+ : LessThan<A, B> extends true
61
+ ? number
62
+ : [false, true] extends R
63
+ ? Sum<A, NumberAbsolute<B>>
64
+ : Subtract<NumberAbsolute<B>, NumberAbsolute<A>>
65
+ : never
66
+ : never;
@@ -0,0 +1,66 @@
1
+ import type {NumberAbsolute, BuildTuple, And, Or, ArrayMax, ArrayMin} from './internal';
2
+ import type {IsEqual} from './is-equal';
3
+ import type {PositiveInfinity, NegativeInfinity, IsNegative} from './numeric';
4
+ import type {Subtract} from './subtract';
5
+
6
+ /**
7
+ Returns the sum of two numbers.
8
+
9
+ Note:
10
+ - A or B can only support `-999` ~ `999`.
11
+ - A and B can only be small integers, less than 1000.
12
+ - If the result is negative, you can only get `number`.
13
+
14
+ @example
15
+ ```
16
+ import type {Sum} from 'type-fest';
17
+
18
+ Sum<111, 222>;
19
+ //=> 333
20
+
21
+ Sum<-111, 222>;
22
+ //=> 111
23
+
24
+ Sum<111, -222>;
25
+ //=> number
26
+
27
+ Sum<PositiveInfinity, -9999>;
28
+ //=> PositiveInfinity
29
+
30
+ Sum<PositiveInfinity, NegativeInfinity>;
31
+ //=> number
32
+ ```
33
+
34
+ @category Numeric
35
+ */
36
+ // TODO: Support big integer and negative number.
37
+ export type Sum<A extends number, B extends number> = [
38
+ IsEqual<A, PositiveInfinity>, IsEqual<A, NegativeInfinity>,
39
+ IsEqual<B, PositiveInfinity>, IsEqual<B, NegativeInfinity>,
40
+ ] extends infer R extends [boolean, boolean, boolean, boolean]
41
+ ? Or<
42
+ And<IsEqual<R[0], true>, IsEqual<R[3], false>>,
43
+ And<IsEqual<R[2], true>, IsEqual<R[1], false>>
44
+ > extends true
45
+ ? PositiveInfinity
46
+ : Or<
47
+ And<IsEqual<R[1], true>, IsEqual<R[2], false>>,
48
+ And<IsEqual<R[3], true>, IsEqual<R[0], false>>
49
+ > extends true
50
+ ? NegativeInfinity
51
+ : true extends R[number]
52
+ ? number
53
+ : ([IsNegative<A>, IsNegative<B>] extends infer R
54
+ ? [false, false] extends R
55
+ ? [...BuildTuple<A>, ...BuildTuple<B>]['length']
56
+ : [true, true] extends R
57
+ ? number
58
+ : ArrayMax<[NumberAbsolute<A>, NumberAbsolute<B>]> extends infer Max_
59
+ ? ArrayMin<[NumberAbsolute<A>, NumberAbsolute<B>]> extends infer Min_ extends number
60
+ ? Max_ extends A | B
61
+ ? Subtract<Max_, Min_>
62
+ : number
63
+ : never
64
+ : never
65
+ : never) & number
66
+ : never;