🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

type-fest

Package Overview
Dependencies
Maintainers
1
Versions
192
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

type-fest - npm Package Compare versions

Comparing version
5.7.0
to
5.8.0
+56
source/extract-exactly.d.ts
import type {IsAny} from './is-any.d.ts';
import type {If} from './if.d.ts';
import type {IsEqual} from './is-equal.d.ts';
import type {IfNotAnyOrNever} from './internal/type.d.ts';
/**
A stricter version of `Extract<T, U>` that extracts types only when they are exactly identical.
@example
```
import type {ExtractExactly} from 'type-fest';
type TestExtract1 = Extract<'a' | 'b' | 'c' | 1 | 2 | 3, string>;
//=> 'a' | 'b' | 'c'
type TestExtractExactly1 = ExtractExactly<'a' | 'b' | 'c' | 1 | 2 | 3, string>;
//=> never
type TestExtract2 = Extract<'a' | 'b' | 'c' | 1 | 2 | 3, any>;
//=> 'a' | 'b' | 'c' | 1 | 2 | 3
type TestExtractExactly2 = ExtractExactly<'a' | 'b' | 'c' | 1 | 2 | 3, any>;
//=> never
type TestExtract3 = Extract<{a: string} | {a: string; b: string}, {a: string}>;
//=> {a: string} | {a: string; b: string}
type TestExtractExactly3 = ExtractExactly<{a: string} | {a: string; b: string}, {a: string}>;
//=> {a: string}
```
@category Improved Built-in
*/
export type ExtractExactly<Union, Match> =
IfNotAnyOrNever<Union, {
ifNot: _ExtractExactly<Union, Match>;
// If `Union` is `any`, then if `Match` is `any`, return `any`, else return `never`.
ifAny: If<IsAny<Match>, Union, never>;
// If `Union` is `never`, return `never`, doesn't matter what `Match` is.
ifNever: never;
}>;
type _ExtractExactly<Union, Match> =
IfNotAnyOrNever<Match, {
ifNot: Union extends unknown // For distributing `Union`
? [Match extends unknown // For distributing `Match`
? If<IsEqual<Union, Match>, true, never>
: never] extends [never] ? never : Union
: never;
// If `Match` is `any` or `never`, then return `never`,
// because `Union` cannot be `any` or `never` here.
ifAny: never;
ifNever: never;
}>;
export {};
import type {StringToArray} from './string-to-array.d.ts';
/**
Returns the length of the given string.
@example
```
import type {StringLength} from 'type-fest';
type A = StringLength<'abcde'>;
//=> 5
type B = StringLength<'abcde' | 'fgh'>;
//=> 3 | 5
```
For non-literal strings, the result is `number` because the length of a non-literal string can be any number.
@example
```
import type {StringLength} from 'type-fest';
type A = StringLength<string>;
//=> number
type B = StringLength<Uppercase<string>>;
//=> number
type C = StringLength<`${string}abc`>;
//=> number
```
@category String
@category Template literal
*/
export type StringLength<S extends string> = StringToArray<S>['length'];
export {};
import type {ApplyDefaultOptions} from './internal/object.d.ts';
import type {IfNotAnyOrNever} from './internal/type.d.ts';
import type {IsStringLiteral} from './is-literal.d.ts';
import type {Or} from './or.d.ts';
/**
@see {@link StringToArray}
*/
export type StringToArrayOptions = {
/**
When enabled, non-literal parts of the string (e.g., `string`, `Uppercase<string>`) are mapped as single elements instead of being mapped as a rest element.
Note: Enabling this option can produce misleading results that might not reflect the actual runtime behavior.
For example, `StringToArray<string, {mapNonLiteralsDirectly: true}>` returns `[string]`, but at runtime, the string could be `'abc'` (which satisfies `string`), and converting it to an array would result in `['a', 'b', 'c']`, which doesn't satisfy `[string]`.
So, it is recommended to not enable this option unless you are aware of the implications.
@default false
@example
```
import type {StringToArray} from 'type-fest';
type A = StringToArray<string, {mapNonLiteralsDirectly: false}>;
//=> string[]
type B = StringToArray<string, {mapNonLiteralsDirectly: true}>;
//=> [string]
type C = StringToArray<`on${string}`, {mapNonLiteralsDirectly: false}>;
//=> ['o', 'n', ...string[]]
type D = StringToArray<`on${string}`, {mapNonLiteralsDirectly: true}>;
//=> ['o', 'n', string]
type E = StringToArray<`${string}xyz`, {mapNonLiteralsDirectly: false}>;
//=> [...string[], 'x', 'y', 'z']
type F = StringToArray<`${string}xyz`, {mapNonLiteralsDirectly: true}>;
//=> [string, 'x', 'y', 'z']
```
*/
mapNonLiteralsDirectly?: boolean;
};
type DefaultStringToArrayOptions = {
mapNonLiteralsDirectly: false;
};
/**
Returns an array of the characters of the specified string.
@example
```
import type {StringToArray} from 'type-fest';
type A = StringToArray<'abcde'>;
//=> ['a', 'b', 'c', 'd', 'e']
type B = StringToArray<''>;
//=> []
type C = StringToArray<string>;
//=> string[]
type D = StringToArray<`foo${string}bar`>;
//=> ['f', 'o', 'o', ...string[], 'b', 'a', 'r']
type E = StringToArray<`foo${string}bar`, {mapNonLiteralsDirectly: true}>;
//=> ['f', 'o', 'o', string, 'b', 'a', 'r']
```
@see {@link StringToArrayOptions}
@category String
*/
export type StringToArray<S extends string, Options extends StringToArrayOptions = {}> =
IfNotAnyOrNever<
S,
{
ifNot: _StringToArray<S, ApplyDefaultOptions<StringToArrayOptions, DefaultStringToArrayOptions, Options>>;
ifAny: unknown[];
}
>;
type _StringToArray<S extends string, Options extends Required<StringToArrayOptions>, Accumulator extends string[] = []> =
S extends `${infer First}${infer Rest}`
? Or<IsStringLiteral<First>, Options['mapNonLiteralsDirectly']> extends true
? _StringToArray<Rest, Options, [...Accumulator, First]>
: _StringToArray<Rest, Options, [...Accumulator, ...First[]]>
: S extends ''
? Accumulator
: Options['mapNonLiteralsDirectly'] extends true
? [...Accumulator, S]
: [...Accumulator, ...S[]];
export {};
import type {IfNotAnyOrNever} from './internal/type.d.ts';
import type {NegativeInfinity, PositiveInfinity} from './numeric.d.ts';
/**
Converts a numeric string to a number.
@example
```
import type {StringToNumber} from 'type-fest';
type PositiveInteger = StringToNumber<'1234'>;
//=> 1234
type NegativeInteger = StringToNumber<'-1234'>;
//=> -1234
type PositiveFloat = StringToNumber<'1234.56'>;
//=> 1234.56
type NegativeFloat = StringToNumber<'-1234.56'>;
//=> -1234.56
type PositiveInfinity = StringToNumber<'Infinity'>;
//=> Infinity
type NegativeInfinity = StringToNumber<'-Infinity'>;
//=> -Infinity
```
Note: Some strings, such as `'1.50'`, `'0b10'`, or `'12_345'`, may look like they can be converted to numbers, but they don't actually have corresponding numeric literals. So, in such cases, this type produces `never`. See [type-fest#1446](https://github.com/sindresorhus/type-fest/pull/1446) for more details.
@example
```
import type {StringToNumber} from 'type-fest';
type FractionalsEndingInZero = StringToNumber<'1.50'>;
//=> never
type NonDecimalBases = StringToNumber<'0b10' | '0o10' | '0x10'>;
//=> never
type NumericSeparators = StringToNumber<'12_345'>;
//=> never
```
@category String
@category Numeric
@category Template literal
*/
export type StringToNumber<S extends string> = IfNotAnyOrNever<S, {ifNot: _StringToNumber<S>; ifAny: number}>;
type _StringToNumber<S extends string> =
S extends `${infer N extends number}`
? number extends N
? `${number}` extends S
? N
: never
: N
: string extends S
? number
: S extends 'Infinity'
? PositiveInfinity
: S extends '-Infinity'
? NegativeInfinity
: never;
export {};
+4
-0

@@ -180,2 +180,3 @@ // Basic

export type {UnionLength} from './source/union-length.d.ts';
export type {StringToNumber} from './source/string-to-number.d.ts';

@@ -212,2 +213,4 @@ // Template literal types

export type {RemoveSuffix, RemoveSuffixOptions} from './source/remove-suffix.d.ts';
export type {StringToArray, StringToArrayOptions} from './source/string-to-array.d.ts';
export type {StringLength} from './source/string-length.d.ts';

@@ -224,3 +227,4 @@ // Miscellaneous

export type {ExcludeExactly} from './source/exclude-exactly.d.ts';
export type {ExtractExactly} from './source/extract-exactly.d.ts';
export {};
+1
-1
{
"name": "type-fest",
"version": "5.7.0",
"version": "5.8.0",
"description": "A collection of essential TypeScript types",

@@ -5,0 +5,0 @@ "license": "(MIT OR CC0-1.0)",

@@ -268,2 +268,4 @@ <div align="center">

- [`RemoveSuffix`](source/remove-suffix.d.ts) - Remove the specified suffix from the end of a string.
- [`StringToArray`](source/string-to-array.d.ts) - Returns an array of the characters of the specified string.
- [`StringLength`](source/string-length.d.ts) - Returns the length of the given string.

@@ -314,2 +316,3 @@ ### Array

- [`Absolute`](source/absolute.d.ts) - Returns the absolute value of the specified number or bigint.
- [`StringToNumber`](source/string-to-number.d.ts) - Converts a numeric string to a number.

@@ -347,2 +350,3 @@ ### Change case

- [`ExcludeExactly`](source/exclude-exactly.d.ts) - A stricter version of `Exclude<T, U>` that excludes types only when they are exactly identical.
- [`ExtractExactly`](source/extract-exactly.d.ts) - A stricter version of `Extract<T, U>` that extracts types only when they are exactly identical.

@@ -349,0 +353,0 @@ ## Declined types

@@ -1,2 +0,2 @@

import type {StringToNumber} from './internal/string.d.ts';
import type {StringToNumber} from './string-to-number.d.ts';

@@ -3,0 +3,0 @@ /**

@@ -106,4 +106,4 @@ import type {CollapseRestElement} from './internal/array.d.ts';

type _AllExtend<TArray extends UnknownArray, Type, Options extends Required<AllExtendOptions>> = IfNotAnyOrNever<TArray,
TArray extends readonly [infer First, ...infer Rest]
type _AllExtend<TArray extends UnknownArray, Type, Options extends Required<AllExtendOptions>> = IfNotAnyOrNever<TArray, {
ifNot: TArray extends readonly [infer First, ...infer Rest]
? IsNever<First> extends true

@@ -117,5 +117,7 @@ ? Or<Or<IsNever<Type>, IsAny<Type>>, Not<Options['strictNever']>> extends true

: false
: true,
false, false>;
: true;
ifAny: false;
ifNever: false;
}>;
export {};

@@ -54,8 +54,9 @@ import type {If} from './if.d.ts';

*/
export type ArrayReverse<TArray extends UnknownArray> = IfNotAnyOrNever<TArray,
TArray extends unknown // For distributing `TArray`
export type ArrayReverse<TArray extends UnknownArray> = IfNotAnyOrNever<TArray, {
ifNot: TArray extends unknown // For distributing `TArray`
? _ArrayReverse<TArray> extends infer Result
? If<IsArrayReadonly<TArray>, Readonly<Result>, Result>
: never // Should never happen
: never>; // Should never happen
: never; // Should never happen
}>;

@@ -62,0 +63,0 @@ type _ArrayReverse<

@@ -54,9 +54,9 @@ import type {If} from './if.d.ts';

*/
export type ArrayTail<TArray extends UnknownArray> = IfNotAnyOrNever<TArray,
TArray extends UnknownArray // For distributing `TArray`
export type ArrayTail<TArray extends UnknownArray> = IfNotAnyOrNever<TArray, {
ifNot: TArray extends UnknownArray // For distributing `TArray`
? _ArrayTail<TArray> extends infer Result
? If<IsArrayReadonly<TArray>, Readonly<Result>, Result>
: never // Should never happen
: never
>;
: never;
}>;

@@ -63,0 +63,0 @@ type _ArrayTail<TArray extends UnknownArray> = TArray extends readonly [unknown?, ...infer Tail]

@@ -53,3 +53,3 @@ import type {ExtendsStrict} from './extends-strict.d.ts';

export type ConditionalKeys<Base, Condition> = (Base extends UnknownArray ? TupleToObject<Base> : Base) extends infer _Base // Remove non-numeric keys from arrays
? IfNotAnyOrNever<_Base, _ConditionalKeys<_Base, Condition>, keyof _Base>
? IfNotAnyOrNever<_Base, {ifNot: _ConditionalKeys<_Base, Condition>; ifAny: keyof _Base}>
: never;

@@ -56,0 +56,0 @@

@@ -36,23 +36,23 @@ import type {IsNever} from './is-never.d.ts';

export type ExcludeExactly<Union, Delete> =
IfNotAnyOrNever<
Union,
_ExcludeExactly<Union, Delete>,
IfNotAnyOrNever<Union, {
ifNot: _ExcludeExactly<Union, Delete>;
// If `Union` is `any`, then if `Delete` is `any`, return `never`, else return `Union`.
If<IsAny<Delete>, never, Union>,
ifAny: If<IsAny<Delete>, never, Union>;
// If `Union` is `never`, then if `Delete` is `never`, return `never`, else return `Union`.
If<IsNever<Delete>, never, Union>
>;
ifNever: If<IsNever<Delete>, never, Union>;
}>;
type _ExcludeExactly<Union, Delete> =
IfNotAnyOrNever<Delete,
Union extends unknown // For distributing `Union`
IfNotAnyOrNever<Delete, {
ifNot: Union extends unknown // For distributing `Union`
? [Delete extends unknown // For distributing `Delete`
? If<IsEqual<Union, Delete>, true, never>
: never] extends [never] ? Union : never
: never,
: never;
// If `Delete` is `any` or `never`, then return `Union`,
// because `Union` cannot be `any` or `never` here.
Union, Union
>;
ifAny: Union;
ifNever: Union;
}>;
export {};

@@ -30,4 +30,4 @@ import type {SplitOnRestElement} from './split-on-rest-element.d.ts';

*/
export type ExcludeRestElement<Array_ extends UnknownArray> = IfNotAnyOrNever<Array_,
SplitOnRestElement<Array_> extends infer Result
export type ExcludeRestElement<Array_ extends UnknownArray> = IfNotAnyOrNever<Array_, {
ifNot: SplitOnRestElement<Array_> extends infer Result
? Result extends readonly UnknownArray[]

@@ -38,5 +38,5 @@ ? IsArrayReadonly<Array_> extends true

: never
: never
>;
: never;
}>;
export {};

@@ -128,9 +128,9 @@ import type {If} from './if.d.ts';

*/
export type ExclusifyUnion<Union> = IfNotAnyOrNever<Union,
If<IsUnknown<Union>, Union,
export type ExclusifyUnion<Union> = IfNotAnyOrNever<Union, {
ifNot: If<IsUnknown<Union>, Union,
Extract<Union, NonRecursiveType | MapsSetsOrArrays> extends infer SkippedMembers
? SkippedMembers | _ExclusifyUnion<Exclude<Union, SkippedMembers>>
: never
>
>;
>;
}>;

@@ -137,0 +137,0 @@ type _ExclusifyUnion<Union, UnionCopy = Union> = Union extends unknown // For distributing `Union`

@@ -114,3 +114,3 @@ import type {If} from '../if.d.ts';

*/
export type CollapseRestElement<TArray extends UnknownArray> = IfNotAnyOrNever<TArray, _CollapseRestElement<TArray>>;
export type CollapseRestElement<TArray extends UnknownArray> = IfNotAnyOrNever<TArray, {ifNot: _CollapseRestElement<TArray>}>;

@@ -117,0 +117,0 @@ type _CollapseRestElement<

@@ -29,7 +29,9 @@ import type {IsNever} from '../is-never.d.ts';

export type IsNumberLike<N> =
IfNotAnyOrNever<N,
N extends number | `${number}`
IfNotAnyOrNever<N, {
ifNot: N extends number | `${number}`
? true
: false,
boolean, false>;
: false;
ifAny: boolean;
ifNever: false;
}>;

@@ -36,0 +38,0 @@ /**

@@ -9,5 +9,6 @@ import type {Simplify} from '../simplify.d.ts';

import type {IsNever} from '../is-never.d.ts';
import type {StringToNumber} from '../string-to-number.d.ts';
import type {FilterDefinedKeys, FilterOptionalKeys} from './keys.d.ts';
import type {MapsSetsOrArrays, NonRecursiveType} from './type.d.ts';
import type {StringToNumber, ToString} from './string.d.ts';
import type {ToString} from './string.d.ts';

@@ -14,0 +15,0 @@ /**

import type {TupleOf} from '../tuple-of.d.ts';
import type {NegativeInfinity, PositiveInfinity} from '../numeric.d.ts';
import type {Trim} from '../trim.d.ts';
import type {StringLength} from '../string-length.d.ts';
import type {Whitespace} from './characters.d.ts';

@@ -14,38 +14,2 @@

/**
Converts a numeric string to a number.
@example
```
type PositiveInt = StringToNumber<'1234'>;
//=> 1234
type NegativeInt = StringToNumber<'-1234'>;
//=> -1234
type PositiveFloat = StringToNumber<'1234.56'>;
//=> 1234.56
type NegativeFloat = StringToNumber<'-1234.56'>;
//=> -1234.56
type PositiveInfinity = StringToNumber<'Infinity'>;
//=> Infinity
type NegativeInfinity = StringToNumber<'-Infinity'>;
//=> -Infinity
```
@category String
@category Numeric
@category Template literal
*/
export type StringToNumber<S extends string> = S extends `${infer N extends number}`
? N
: S extends 'Infinity'
? PositiveInfinity
: S extends '-Infinity'
? NegativeInfinity
: never;
/**
Returns a boolean for whether the given string `S` starts with the given string `SearchString`.

@@ -78,41 +42,2 @@

/**
Returns an array of the characters of the string.
@example
```
type A = StringToArray<'abcde'>;
//=> ['a', 'b', 'c', 'd', 'e']
type B = StringToArray<string>;
//=> never
```
@category String
*/
export type StringToArray<S extends string, Result extends string[] = []> = string extends S
? never
: S extends `${infer F}${infer R}`
? StringToArray<R, [...Result, F]>
: Result;
/**
Returns the length of the given string.
@example
```
type A = StringLength<'abcde'>;
//=> 5
type B = StringLength<string>;
//=> never
```
@category String
@category Template literal
*/
export type StringLength<S extends string> = string extends S
? never
: StringToArray<S>['length'];
/**
Returns a boolean for whether a string is whitespace.

@@ -119,0 +44,0 @@ */

@@ -1,2 +0,1 @@

import type {If} from '../if.d.ts';
import type {IsAny} from '../is-any.d.ts';

@@ -6,3 +5,2 @@ import type {IsNever} from '../is-never.d.ts';

import type {UnknownArray} from '../unknown-array.d.ts';
import type {UnionToIntersection} from '../union-to-intersection.d.ts';

@@ -95,12 +93,12 @@ /**

```
// When `T` is a NOT `any` or `never` (like `string`) => Returns `IfNotAnyOrNever` branch
type A = IfNotAnyOrNever<string, 'VALID', 'IS_ANY', 'IS_NEVER'>;
// When `T` is neither `any` nor `never` (like `string`) => Returns `IfNot` branch
type A = IfNotAnyOrNever<string, {ifNot: 'VALID'; ifAny: 'IS_ANY'; ifNever: 'IS_NEVER'}>;
//=> 'VALID'
// When `T` is `any` => Returns `IfAny` branch
type B = IfNotAnyOrNever<any, 'VALID', 'IS_ANY', 'IS_NEVER'>;
type B = IfNotAnyOrNever<any, {ifNot: 'VALID'; ifAny: 'IS_ANY'; ifNever: 'IS_NEVER'}>;
//=> 'IS_ANY'
// When `T` is `never` => Returns `IfNever` branch
type C = IfNotAnyOrNever<never, 'VALID', 'IS_ANY', 'IS_NEVER'>;
type C = IfNotAnyOrNever<never, {ifNot: 'VALID'; ifAny: 'IS_ANY'; ifNever: 'IS_NEVER'}>;
//=> 'IS_NEVER'

@@ -118,3 +116,3 @@ ```

// The following implementation is not tail recursive
type TrimLeft<S extends string> = IfNotAnyOrNever<S, S extends ` ${infer R}` ? TrimLeft<R> : S>;
type TrimLeft<S extends string> = IfNotAnyOrNever<S, {ifNot: S extends ` ${infer R}` ? TrimLeft<R> : S}>;

@@ -128,3 +126,3 @@ // Hence, instantiations with long strings will fail

// To fix this, move the recursion into a helper type
type TrimLeftOptimised<S extends string> = IfNotAnyOrNever<S, _TrimLeftOptimised<S>>;
type TrimLeftOptimised<S extends string> = IfNotAnyOrNever<S, {ifNot: _TrimLeftOptimised<S>}>;

@@ -137,4 +135,12 @@ type _TrimLeftOptimised<S extends string> = S extends ` ${infer R}` ? _TrimLeftOptimised<R> : S;

*/
export type IfNotAnyOrNever<T, IfNotAnyOrNever, IfAny = any, IfNever = never> =
If<IsAny<T>, IfAny, If<IsNever<T>, IfNever, IfNotAnyOrNever>>;
export type IfNotAnyOrNever<T, Cases extends {ifNot: unknown; ifAny?: unknown; ifNever?: unknown}> =
IsAny<T> extends true
? 'ifAny' extends keyof Cases
? Cases['ifAny']
: any
: IsNever<T> extends true
? 'ifNever' extends keyof Cases
? Cases['ifNever']
: never
: Cases['ifNot'];

@@ -141,0 +147,0 @@ /**

@@ -117,5 +117,7 @@ import type {Primitive} from './primitive.d.ts';

*/
export type IsStringLiteral<S> = IfNotAnyOrNever<S,
_IsStringLiteral<CollapseLiterals<S extends TagContainer<any> ? UnwrapTagged<S> : S>>,
false, false>;
export type IsStringLiteral<S> = IfNotAnyOrNever<S, {
ifNot: _IsStringLiteral<CollapseLiterals<S extends TagContainer<any> ? UnwrapTagged<S> : S>>;
ifAny: false;
ifNever: false;
}>;

@@ -122,0 +124,0 @@ export type _IsStringLiteral<S> =

@@ -0,1 +1,6 @@

import type {If} from './if.d.ts';
import type {IfNotAnyOrNever, IsExactOptionalPropertyTypesEnabled} from './internal/type.d.ts';
import type {SplitOnRestElement} from './split-on-rest-element.d.ts';
import type {UnknownArray} from './unknown-array.d.ts';
/**

@@ -19,19 +24,67 @@ Extract the type of the last element of an array.

Note: When the array ends with an optional or rest element, the last element's position becomes ambiguous. In such cases, the result is a union of the types of all elements that could potentially be the last element of the array.
@example
```
import type {LastArrayElement} from 'type-fest';
type A = LastArrayElement<[string, number?, bigint?]>;
//=> bigint | number | string
type B = LastArrayElement<[string, number, bigint?, ...boolean[]]>;
//=> boolean | bigint | number
```
Note: If empty array is a valid value for the array type, the result includes an `undefined`. This aligns with the runtime behavior of `[].at(-1)`.
@example
```
import type {LastArrayElement} from 'type-fest';
type A = LastArrayElement<[]>;
//=> undefined
// `[]` is assignable to `string[]`
type B = LastArrayElement<string[]>;
//=> string | undefined
// `[]` is assignable to `[string?, number?]`
type C = LastArrayElement<[string?, number?]>;
//=> number | string | undefined
// `[]` is assignable to [string?, number?, ...bigint[]]`
type D = LastArrayElement<[string?, number?, ...bigint[]]>;
//=> bigint | number | string | undefined
```
@category Array
@category Template literal
*/
export type LastArrayElement<Elements extends readonly unknown[], ElementBeforeTailingSpreadElement = never> =
// If the last element of an array is a spread element, the `LastArrayElement` result should be `'the type of the element before the spread element' | 'the type of the spread element'`.
Elements extends readonly []
? ElementBeforeTailingSpreadElement
: Elements extends readonly [...infer U, infer V]
? V
: Elements extends readonly [infer U, ...infer V]
// If we return `V[number] | U` directly, it would be wrong for `[[string, boolean, object, ...number[]]`.
// So we need to recurse type `V` and carry over the type of the element before the spread element.
? LastArrayElement<V, U>
: Elements extends ReadonlyArray<infer U>
? U | ElementBeforeTailingSpreadElement
: never;
export type LastArrayElement<TArray extends UnknownArray> =
IfNotAnyOrNever<TArray, {
ifNot: TArray extends UnknownArray // For distributing `TArray`
? SplitOnRestElement<TArray> extends readonly [infer BeforeRest extends UnknownArray, infer Rest extends UnknownArray, infer AfterRest extends UnknownArray]
? _LastArrayElement<BeforeRest, Rest, AfterRest>
: never
: never;
}>;
type _LastArrayElement<BeforeRest extends UnknownArray, Rest extends UnknownArray, AfterRest extends UnknownArray> =
AfterRest extends readonly [...any, infer Last] // Note there are no optional elements in `AfterRest`.
? Last // If there's a `Last` in `AfterRest`, then that's the result.
: Rest[number] | BeforeRestLastElement<BeforeRest>; // Otherwise, the result is union of the `Rest` element and the last element in `BeforeRest`.
type BeforeRestLastElement<BeforeRest extends UnknownArray, Accumulator = never> =
BeforeRest extends readonly []
? Accumulator | undefined
: BeforeRest extends readonly [...any, infer Last]
? Last | Accumulator
: BeforeRest extends readonly [...infer Rest, (infer Last)?]
? BeforeRestLastElement<
Rest,
// Add `undefined` for optional elements, if `exactOptionalPropertyTypes` is disabled.
Last | Accumulator | If<IsExactOptionalPropertyTypesEnabled, never, undefined>
>
: never;
export {};

@@ -93,18 +93,23 @@ import type {If} from './if.d.ts';

export type ObjectMerge<First extends object, Second extends object> =
IfNotAnyOrNever<First, IfNotAnyOrNever<Second, First extends unknown // For distributing `First`
? Second extends unknown // For distributing `Second`
? First extends MapsSetsOrArrays
? unknown
: Second extends MapsSetsOrArrays
? unknown
: _ObjectMerge<
First,
Second,
NormalizedLiteralKeys<First>,
NormalizedLiteralKeys<Second>,
IsExactOptionalPropertyTypesEnabled extends true ? Required<First> : First,
IsExactOptionalPropertyTypesEnabled extends true ? Required<Second> : Second
>
: never // Should never happen
: never>, First & Second>; // Should never happen
IfNotAnyOrNever<First, {
ifNot: IfNotAnyOrNever<Second, {
ifNot: First extends unknown // For distributing `First`
? Second extends unknown // For distributing `Second`
? First extends MapsSetsOrArrays
? unknown
: Second extends MapsSetsOrArrays
? unknown
: _ObjectMerge<
First,
Second,
NormalizedLiteralKeys<First>,
NormalizedLiteralKeys<Second>,
IsExactOptionalPropertyTypesEnabled extends true ? Required<First> : First,
IsExactOptionalPropertyTypesEnabled extends true ? Required<Second> : Second
>
: never // Should never happen
: never; // Should never happen
}>;
ifAny: First & Second;
}>;

@@ -111,0 +116,0 @@ type _ObjectMerge<

@@ -97,10 +97,9 @@ import type {ApplyDefaultOptions} from './internal/object.d.ts';

export type RemovePrefix<S extends string, Prefix extends string, Options extends RemovePrefixOptions = {}> =
IfNotAnyOrNever<
S,
If<
IfNotAnyOrNever<S, {
ifNot: If<
IsNever<Prefix>,
S,
_RemovePrefix<S, Prefix, ApplyDefaultOptions<RemovePrefixOptions, DefaultRemovePrefixOptions, Options>>
>
>;
>;
}>;

@@ -107,0 +106,0 @@ type _RemovePrefix<S extends string, Prefix extends string, Options extends Required<RemovePrefixOptions>> =

@@ -97,10 +97,9 @@ import type {ApplyDefaultOptions} from './internal/object.d.ts';

export type RemoveSuffix<S extends string, Suffix extends string, Options extends RemoveSuffixOptions = {}> =
IfNotAnyOrNever<
S,
If<
IfNotAnyOrNever<S, {
ifNot: If<
IsNever<Suffix>,
S,
_RemoveSuffix<S, Suffix, ApplyDefaultOptions<RemoveSuffixOptions, DefaultRemoveSuffixOptions, Options>>
>
>;
>;
}>;

@@ -107,0 +106,0 @@ type _RemoveSuffix<S extends string, Suffix extends string, Options extends Required<RemoveSuffixOptions>> =

@@ -43,7 +43,7 @@ import type {If} from './if.d.ts';

export type RequireAllOrNone<ObjectType, KeysType extends keyof ObjectType = keyof ObjectType> =
IfNotAnyOrNever<ObjectType,
If<IsNever<KeysType>,
IfNotAnyOrNever<ObjectType, {
ifNot: If<IsNever<KeysType>,
ObjectType,
_RequireAllOrNone<ObjectType, If<IsAny<KeysType>, keyof ObjectType, KeysType>>
>>;
_RequireAllOrNone<ObjectType, If<IsAny<KeysType>, keyof ObjectType, KeysType>>>;
}>;

@@ -50,0 +50,0 @@ type _RequireAllOrNone<ObjectType, KeysType extends keyof ObjectType> = (

@@ -32,7 +32,7 @@ import type {Except} from './except.d.ts';

> =
IfNotAnyOrNever<ObjectType,
If<IsNever<KeysType>,
IfNotAnyOrNever<ObjectType, {
ifNot: If<IsNever<KeysType>,
never,
_RequireAtLeastOne<ObjectType, If<IsAny<KeysType>, keyof ObjectType, KeysType>>
>>;
_RequireAtLeastOne<ObjectType, If<IsAny<KeysType>, keyof ObjectType, KeysType>>>;
}>;

@@ -39,0 +39,0 @@ type _RequireAtLeastOne<

@@ -36,7 +36,7 @@ import type {If} from './if.d.ts';

export type RequireExactlyOne<ObjectType, KeysType extends keyof ObjectType = keyof ObjectType> =
IfNotAnyOrNever<ObjectType,
If<IsNever<KeysType>,
IfNotAnyOrNever<ObjectType, {
ifNot: If<IsNever<KeysType>,
never,
_RequireExactlyOne<ObjectType, If<IsAny<KeysType>, keyof ObjectType, KeysType>>
>>;
_RequireExactlyOne<ObjectType, If<IsAny<KeysType>, keyof ObjectType, KeysType>>>;
}>;

@@ -43,0 +43,0 @@ type _RequireExactlyOne<ObjectType, KeysType extends keyof ObjectType> =

@@ -38,7 +38,7 @@ import type {RequireExactlyOne} from './require-exactly-one.d.ts';

export type RequireOneOrNone<ObjectType, KeysType extends keyof ObjectType = keyof ObjectType> =
IfNotAnyOrNever<ObjectType,
If<IsNever<KeysType>,
IfNotAnyOrNever<ObjectType, {
ifNot: If<IsNever<KeysType>,
ObjectType,
_RequireOneOrNone<ObjectType, If<IsAny<KeysType>, keyof ObjectType, KeysType>>
>>;
_RequireOneOrNone<ObjectType, If<IsAny<KeysType>, keyof ObjectType, KeysType>>>;
}>;

@@ -45,0 +45,0 @@ type _RequireOneOrNone<ObjectType, KeysType extends keyof ObjectType> = (

import type {ApplyDefaultOptions} from './internal/object.d.ts';
import type {IfNotAnyOrNever, NonRecursiveType} from './internal/type.d.ts';
import type {IsAny} from './is-any.d.ts';
import type {IsUnknown} from './is-unknown.d.ts';
import type {OptionalKeysOf} from './optional-keys-of.d.ts';

@@ -94,14 +96,20 @@ import type {Simplify} from './simplify.d.ts';

export type Schema<Type, Value, Options extends SchemaOptions = {}> =
IfNotAnyOrNever<Type,
_Schema<Type, Value, ApplyDefaultOptions<SchemaOptions, DefaultSchemaOptions, Options>>,
Value, Value>;
IfNotAnyOrNever<Type, {
ifNot: _Schema<Type, Value, ApplyDefaultOptions<SchemaOptions, DefaultSchemaOptions, Options>>;
ifAny: Value;
ifNever: Value;
}>;
type _Schema<Type, Value, Options extends Required<SchemaOptions>> =
Type extends NonRecursiveType | Map<unknown, unknown> | Set<unknown> | ReadonlyMap<unknown, unknown> | ReadonlySet<unknown>
IsAny<Type> extends true
? Value
: Type extends UnknownArray
? Options['recurseIntoArrays'] extends false
: IsUnknown<Type> extends true
? Value
: Type extends NonRecursiveType | Map<unknown, unknown> | Set<unknown> | ReadonlyMap<unknown, unknown> | ReadonlySet<unknown>
? Value
: SchemaHelper<Type, Value, Options>
: SchemaHelper<Type, Value, Options>;
: Type extends UnknownArray
? Options['recurseIntoArrays'] extends false
? Value
: SchemaHelper<Type, Value, Options>
: SchemaHelper<Type, Value, Options>;

@@ -108,0 +116,0 @@ /**

@@ -1,2 +0,2 @@

import type {NonRecursiveType, StringToNumber} from './internal/index.d.ts';
import type {NonRecursiveType} from './internal/index.d.ts';
import type {IsAny} from './is-any.d.ts';

@@ -7,2 +7,3 @@ import type {NonNullableDeep} from './non-nullable-deep.d.ts';

import type {Simplify} from './simplify.d.ts';
import type {StringToNumber} from './string-to-number.d.ts';
import type {UnionToTuple} from './union-to-tuple.d.ts';

@@ -9,0 +10,0 @@ import type {UnknownArray} from './unknown-array.d.ts';

import type {IsAny} from './is-any.d.ts';
import type {NonRecursiveType, StringToNumber} from './internal/index.d.ts';
import type {NonRecursiveType} from './internal/index.d.ts';
import type {Paths} from './paths.d.ts';

@@ -9,2 +9,3 @@ import type {SetRequired} from './set-required.d.ts';

import type {UnknownArray} from './unknown-array.d.ts';
import type {StringToNumber} from './string-to-number.d.ts';

@@ -11,0 +12,0 @@ /**

@@ -100,4 +100,4 @@ import type {CollapseRestElement} from './internal/array.d.ts';

type _SomeExtend<TArray extends UnknownArray, Type, Options extends Required<SomeExtendOptions>> = IfNotAnyOrNever<TArray,
TArray extends readonly [infer First, ...infer Rest]
type _SomeExtend<TArray extends UnknownArray, Type, Options extends Required<SomeExtendOptions>> = IfNotAnyOrNever<TArray, {
ifNot: TArray extends readonly [infer First, ...infer Rest]
? IsNever<First> extends true

@@ -111,5 +111,7 @@ ? Or<Or<IsNever<Type>, IsAny<Type>>, Not<Options['strictNever']>> extends true

: _SomeExtend<Rest, Type, Options>
: false,
false, false>;
: false;
ifAny: false;
ifNever: false;
}>;
export {};

@@ -68,6 +68,8 @@ import type {IfNotAnyOrNever, IsExactOptionalPropertyTypesEnabled} from './internal/type.d.ts';

Array_ extends unknown // For distributing `Array_`
? IfNotAnyOrNever<Array_, _SplitOnRestElement<
Array_,
ApplyDefaultOptions<SplitOnRestElementOptions, DefaultSplitOnRestElementOptions, Options>
>> extends infer Result extends UnknownArray
? IfNotAnyOrNever<Array_, {
ifNot: _SplitOnRestElement<
Array_,
ApplyDefaultOptions<SplitOnRestElementOptions, DefaultSplitOnRestElementOptions, Options>
>;
}> extends infer Result extends UnknownArray
? If<IsArrayReadonly<Array_>, Readonly<Result>, Result>

@@ -74,0 +76,0 @@ : never // Should never happen

import type {IsNumericLiteral} from './is-literal.d.ts';
import type {IsNegative} from './numeric.d.ts';
import type {DigitCharacter} from './characters.d.ts';

@@ -12,5 +13,5 @@ /**

declare function stringRepeat<
Input extends string,
S extends string,
Count extends number,
>(input: Input, count: Count): StringRepeat<Input, Count>;
>(input: S, count: Count): StringRepeat<S, Count>;

@@ -26,26 +27,52 @@ // The return type is the exact string literal, not just `string`.

Note: If the specified count has a decimal part, the decimal part will be ignored.
@example
```
import type {StringRepeat} from 'type-fest';
type DecimalCount = StringRepeat<'foo', 2.5>;
//=> 'foofoo'
```
@category String
@category Template literal
*/
export type StringRepeat<
Input extends string,
Count extends number,
> = StringRepeatHelper<Input, Count>;
type StringRepeatHelper<
Input extends string,
Count extends number,
Counter extends never[] = [],
Accumulator extends string = '',
> =
IsNegative<Count> extends true
? never
: Input extends ''
? ''
: Count extends Counter['length']
? Accumulator
export type StringRepeat<S extends string, Count extends number> =
Count extends unknown // To distribute `Count`
? IsNegative<Count> extends true
? never
: S extends ''
? ''
: IsNumericLiteral<Count> extends false
? string
: StringRepeatHelper<Input, Count, [...Counter, never], `${Accumulator}${Input}`>;
: `${Count}` extends `${string}e${string}`
? string
: BuildStringDigitByDigit<S, `${Count}`>
: never;
type BuildStringDigitByDigit<S extends string, Count extends string, Accumulator extends string = ''> =
Count extends `${infer First extends DigitCharacter}${infer Rest}`
? BuildStringDigitByDigit<
S,
Rest,
`${RepeatStringTenTimes<Accumulator>}${DigitStringRepeat<S, First>}`
>
: Accumulator;
type RepeatStringTenTimes<S extends string> = `${S}${S}${S}${S}${S}${S}${S}${S}${S}${S}`;
type DigitStringRepeat<S extends string, Digit extends DigitCharacter> = [
'',
`${S}`,
`${S}${S}`,
`${S}${S}${S}`,
`${S}${S}${S}${S}`,
`${S}${S}${S}${S}${S}`,
`${S}${S}${S}${S}${S}${S}`,
`${S}${S}${S}${S}${S}${S}${S}`,
`${S}${S}${S}${S}${S}${S}${S}${S}`,
`${S}${S}${S}${S}${S}${S}${S}${S}${S}`,
][Digit];
export {};
import type {Join} from './join.d.ts';
import type {ArraySlice} from './array-slice.d.ts';
import type {StringToArray} from './internal/index.d.ts';
import type {StringToArray} from './string-to-array.d.ts';

@@ -5,0 +5,0 @@ /**

@@ -81,5 +81,7 @@ import type {If} from './if.d.ts';

*/
export type TupleOf<Length extends number, Fill = unknown> = IfNotAnyOrNever<Length,
_TupleOf<If<IsNegative<Length>, 0, Length>, Fill>,
Fill[], []>;
export type TupleOf<Length extends number, Fill = unknown> = IfNotAnyOrNever<Length, {
ifNot: _TupleOf<If<IsNegative<Length>, 0, Length>, Fill>;
ifAny: Fill[];
ifNever: [];
}>;

@@ -86,0 +88,0 @@ type _TupleOf<Length extends number, Fill> = number extends Length