You're Invited:Meet the Socket Team at RSAC and BSidesSF 2026, March 23–26.RSVP
Socket
Book a DemoSign in
Socket

type-fest

Package Overview
Dependencies
Maintainers
1
Versions
189
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.3.1
to
5.4.0
+84
source/array-reverse.d.ts
import type {If} from './if.d.ts';
import type {IsArrayReadonly} from './internal/array.d.ts';
import type {IfNotAnyOrNever, IsExactOptionalPropertyTypesEnabled} from './internal/type.d.ts';
import type {IsOptionalKeyOf} from './is-optional-key-of.d.ts';
import type {UnknownArray} from './unknown-array.d.ts';
/**
Reverse the order of elements in a tuple type.
@example
```ts
import type {ArrayReverse} from 'type-fest';
type A = ArrayReverse<[string, number, boolean]>;
//=> [boolean, number, string]
type B = ArrayReverse<readonly [string, number, ...boolean[]]>;
//=> readonly [...boolean[], number, string]
type C = ArrayReverse<['foo', 'bar'] | readonly [1, 2, 3]>;
//=> ['bar', 'foo'] | readonly [3, 2, 1]
type D = ArrayReverse<string[]>;
//=> string[]
type E = ArrayReverse<[]>;
//=> []
```
Note: If the tuple contains optional elements, the result will be a union of tuples, refer to the examples below:
@example
```ts
import type {ArrayReverse} from 'type-fest';
type A = ArrayReverse<[string, number, boolean?]>;
//=> [number, string] | [boolean, number, string]
type B = ArrayReverse<[string, number?, boolean?]>;
//=> [string] | [number, string] | [boolean, number, string]
type C = ArrayReverse<[string?, number?, boolean?]>;
//=> [] | [string] | [number, string] | [boolean, number, string]
type D = ArrayReverse<[string, number?, ...boolean[]]>;
//=> [string] | [...boolean[], number, string]
type E = ArrayReverse<[string?, number?, ...boolean[]]>;
//=> [] | [string] | [...boolean[], number, string]
```
@category Array
*/
export type ArrayReverse<TArray extends UnknownArray> = IfNotAnyOrNever<TArray,
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
type _ArrayReverse<
TArray extends UnknownArray,
BeforeRestAcc extends UnknownArray = [],
AfterRestAcc extends UnknownArray = [],
Result extends UnknownArray = never,
> =
keyof TArray & `${number}` extends never
// Enters this branch, if `TArray` is empty (e.g., `[]`),
// or `TArray` contains no non-rest elements preceding the rest element (e.g., `[...string[]]` or `[...string[], string]`).
? TArray extends readonly [...infer Rest, infer Last]
? _ArrayReverse<Rest, BeforeRestAcc, [...AfterRestAcc, Last], Result> // Accumulate elements that are present after the rest element in reverse order.
: Result | [...AfterRestAcc, ...TArray, ...BeforeRestAcc] // Add the rest element between the accumulated elements.
: TArray extends readonly [(infer First)?, ...infer Rest]
? IsOptionalKeyOf<TArray, '0'> extends true
? _ArrayReverse<
Rest,
[First | (If<IsExactOptionalPropertyTypesEnabled, never, undefined>), ...BeforeRestAcc], // Add `| undefined` for optional elements, if `exactOptionalPropertyTypes` is disabled.
AfterRestAcc,
Result | BeforeRestAcc
>
: _ArrayReverse<Rest, [First, ...BeforeRestAcc], AfterRestAcc, Result>
: never; // Should never happen, since `readonly [(infer First)?, ...infer Rest]` is a top-type for arrays.
export {};
import type {If} from './if.d.ts';
import type {NormalizedKeys} from './internal/object.d.ts';
import type {IfNotAnyOrNever, IsExactOptionalPropertyTypesEnabled, MapsSetsOrArrays} from './internal/type.d.ts';
import type {IsNever} from './is-never.d.ts';
import type {IsOptionalKeyOf} from './is-optional-key-of.d.ts';
import type {OmitIndexSignature} from './omit-index-signature.d.ts';
import type {PickIndexSignature} from './pick-index-signature.d.ts';
import type {RequiredKeysOf} from './required-keys-of.d.ts';
import type {Simplify} from './simplify.d.ts';
/**
Merge two object types into a new object type, where keys from the second override keys from the first.
@example
```ts
import type {ObjectMerge} from 'type-fest';
type PartialOverride = ObjectMerge<{foo: string; bar: string}, {foo: number; baz: number}>;
//=> {foo: number; baz: number; bar: string}
type CompleteOverride = ObjectMerge<{foo: string; bar: number}, {foo: number; bar: string; baz: boolean}>;
//=> {foo: number; bar: string; baz: boolean}
type NoOverride = ObjectMerge<{foo: string; bar: number}, {baz: boolean; qux: bigint}>;
//=> {baz: boolean; qux: bigint; foo: string; bar: number}
```
Use-cases:
Can be used to accurately type object spread and `Object.assign`. The built-in inference for these operations can sometimes be unsound, especially when index signatures are involved.
In the following example, both object spread and `Object.assign` produce a type that allows unsafe usage, whereas `ObjectMerge` produces a type that prevents this unsafe access.
@example
```ts
import type {ObjectMerge} from 'type-fest';
const left: {a: string} = {a: '1'};
const right: {[x: string]: number} = {a: 1};
const inferred = {...left, ...right};
//=> {a: string}
inferred.a.toUpperCase(); // No compile time error, but fails at runtime.
const objectAssign = Object.assign(left, right);
//=> {a: string} & {[x: string]: number}
objectAssign.a.toUpperCase(); // No compile time error, but fails at runtime.
declare const objectMerge: ObjectMerge<typeof left, typeof right>;
//=> {[x: string]: string | number; a: string | number}
// @ts-expect-error
objectMerge.a.toUpperCase(); // Correctly errors at compile time.
```
Can be used to merge generic type arguments.
In the following example, object spread without `ObjectMerge` produces an intersection type that is not particularly usable, whereas `ObjectMerge` produces a correctly merged and usable result.
@example
```ts
import type {ObjectMerge} from 'type-fest';
function withoutObjectMerge<T extends object, U extends object>(left: T, right: U) {
return {...left, ...right};
}
const result1 = withoutObjectMerge({a: 1}, {a: 'one'});
//=> {a: number} & {a: string}
const {a} = result1;
//=> never
function withObjectMerge<T extends object, U extends object>(left: T, right: U) {
return {...left, ...right} as unknown as ObjectMerge<T, U>;
}
const result2 = withObjectMerge({b: 1}, {b: 'one'});
//=> {b: string}
const {b} = result2;
//=> string
```
Note: If you want a simple merge where properties from the second object always override properties from the first object without considering runtime implications, refer to the {@link Merge} type.
@see {@link Merge}
@category Object
*/
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
type _ObjectMerge<
First extends object,
Second extends object,
NormalizedFirstLiteralKeys extends PropertyKey,
NormalizedSecondLiteralKeys extends PropertyKey,
NormalizedFirst extends object,
NormalizedSecond extends object,
> = Simplify<{
// Map over literal keys of `Second`, except those that are optional and also present in `First`.
-readonly [P in keyof Second as P extends NormalizedSecondLiteralKeys
? P extends NormalizedFirstLiteralKeys
? If<IsOptionalKeyOf<Second, P>, never, P>
: P
: never]:
| Second[P]
| (P extends NormalizedKeys<keyof PickIndexSignature<First>>
? If<IsOptionalKeyOf<Second, P>, First[NormalizedKeys<P> & keyof First], never>
: never)
} & {
// Map over literal keys of `First`, except those that are not present in `Second`.
-readonly [P in keyof First as P extends NormalizedFirstLiteralKeys
? P extends NormalizedSecondLiteralKeys
? never
: P
: never]:
| First[P]
// If there's a matching index signature in `Second`, then add the type for it as well,
// for example, in `ObjectMerge<{a: string}, {[x: string]: number}>`, `a` is of type `string | number`.
| (P extends NormalizedKeys<keyof Second>
? Second[NormalizedKeys<P> & keyof Second]
: never);
} & {
// Map over non-literal keys of `Second`.
-readonly [P in keyof Second as P extends NormalizedSecondLiteralKeys ? never : P]:
| Second[P]
// If there's a matching key in `First`, then add the type for it as well,
// for example, in `ObjectMerge<{a: number}, {[x: string]: string}>`,
// the resulting type is `{[x: string]: number | string; a: number | string}`.
// But, exclude keys from `First` that would surely get overwritten,
// for example, in `ObjectMerge<{a: number}, {[x: string]: string; a: string}>`,
// `a` from `First` would get overwritten by `a` from `Second`, so don't add type for it.
| (NormalizedKeys<P> & Exclude<keyof First, NormalizedKeys<RequiredKeysOf<OmitIndexSignature<Second>>>> extends infer NonOverwrittenKeysOfFirst
? If<IsNever<NonOverwrittenKeysOfFirst>, // This check is required because indexing with `never` doesn't always yield `never`, for example, `{[x: string]: number}[never]` results in `number`.
never,
NormalizedFirst[NonOverwrittenKeysOfFirst & keyof NormalizedFirst]>
: never); // Should never happen
} & {
// Map over non-literal keys of `First`.
-readonly [P in keyof First as P extends NormalizedFirstLiteralKeys ? never : P]:
| First[P]
| If<IsNever<NormalizedKeys<P> & keyof Second>, // This check is required because indexing with `never` doesn't always yield `never`, for example, `{[x: string]: number}[never]` results in `number`.
never,
NormalizedSecond[NormalizedKeys<P> & keyof NormalizedSecond]>;
} & {
// Handle optional keys of `Second` that are also present in `First`.
// Map over `First` instead of `Second` because the modifier is in accordance with `First`.
-readonly [P in keyof First as P extends NormalizedFirstLiteralKeys
? P extends NormalizedSecondLiteralKeys
? If<IsOptionalKeyOf<Second, NormalizedKeys<P> & keyof Second>, P, never>
: never
: never]:
| First[P]
| NormalizedSecond[NormalizedKeys<P> & keyof NormalizedSecond]
}>;
/**
Get literal keys of a type, including both string and number representations wherever applicable.
@example
```ts
type A = NormalizedLiteralKeys<{0: string; '1'?: number; foo: boolean}>;
//=> 0 | '0' | 1 | '1' | 'foo'
type B = NormalizedLiteralKeys<{[x: string]: string | number; 0: string; '1'?: number}>;
//=> 0 | '0' | 1 | '1'
type C = NormalizedLiteralKeys<{[x: string]: unknown}>;
//=> never
```
*/
type NormalizedLiteralKeys<Type> = Type extends unknown // For distributing `Type`
? NormalizedKeys<keyof OmitIndexSignature<Type>>
: never; // Should never happen
export {};
/**
Revert the `Partial` modifier on an object type.
Use-case: Infer the underlying type `T` when only `Partial<T>` is available or the original type may not be directly accessible.
@example
```
import type {UnwrapPartial} from 'type-fest';
type Config = Partial<{
port: number;
host: string;
secure?: boolean;
}>;
type InitializedConfig = UnwrapPartial<Config>;
//=> {port: number; host: string; secure?: boolean}
```
Note: If the provided type isn’t of `Partial<T>`, `UnwrapPartial` has no effect on the original type.
@category Object
*/
export type UnwrapPartial<PartialObjectType> =
PartialObjectType extends Partial<infer ObjectType>
? (
Partial<ObjectType> extends PartialObjectType
? ObjectType
: PartialObjectType
)
: PartialObjectType;
export {};
+3
-0

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

export type {Merge} from './source/merge.d.ts';
export type {ObjectMerge} from './source/object-merge.d.ts';
export type {MergeDeep, MergeDeepOptions} from './source/merge-deep.d.ts';

@@ -36,2 +37,3 @@ export type {MergeExclusive} from './source/merge-exclusive.d.ts';

export type {PartialDeep, PartialDeepOptions} from './source/partial-deep.d.ts';
export type {UnwrapPartial} from './source/unwrap-partial.d.ts';
export type {RequiredDeep} from './source/required-deep.d.ts';

@@ -169,2 +171,3 @@ export type {PickDeep} from './source/pick-deep.d.ts';

export type {ExclusifyUnion} from './source/exclusify-union.d.ts';
export type {ArrayReverse} from './source/array-reverse.d.ts';

@@ -171,0 +174,0 @@ // Template literal types

+4
-4
{
"name": "type-fest",
"version": "5.3.1",
"version": "5.4.0",
"description": "A collection of essential TypeScript types",

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

"scripts": {
"test:tsc": "node --max-old-space-size=5120 ./node_modules/.bin/tsc",
"test:tsd": "tsd",
"test:xo": "xo",
"test:tsc": "node --max-old-space-size=6144 ./node_modules/.bin/tsc",
"test:tsd": "node --max-old-space-size=6144 ./node_modules/.bin/tsd",
"test:xo": "node --max-old-space-size=6144 ./node_modules/.bin/xo",
"test:linter": "node --test",

@@ -33,0 +33,0 @@ "test": "run-p test:*"

@@ -109,2 +109,3 @@ <div align="center">

- [`Merge`](source/merge.d.ts) - Merge two types into a new type. Keys of the second type overrides keys of the first type.
- [`ObjectMerge`](source/object-merge.d.ts) - Merge two object types into a new object type, where keys from the second override keys from the first.
- [`MergeDeep`](source/merge-deep.d.ts) - Merge two objects or two arrays/tuples recursively into a new type.

@@ -126,2 +127,3 @@ - [`MergeExclusive`](source/merge-exclusive.d.ts) - Create a type that has mutually exclusive keys.

- [`UndefinedOnPartialDeep`](source/undefined-on-partial-deep.d.ts) - Create a deep version of another type where all optional keys are set to also accept `undefined`.
- [`UnwrapPartial`](source/unwrap-partial.d.ts) - Revert the `Partial` modifier on an object type.
- [`ReadonlyDeep`](source/readonly-deep.d.ts) - Create a deeply immutable version of an `object`/`Map`/`Set`/`Array` type. Use [`Readonly<T>`](https://www.typescriptlang.org/docs/handbook/utility-types.html#readonlytype) if you only need one level deep.

@@ -268,2 +270,3 @@ - [`LiteralUnion`](source/literal-union.d.ts) - Create a union type by combining primitive types and literal types without sacrificing auto-completion in IDEs for the literal type part of the union. Workaround for [Microsoft/TypeScript#29729](https://github.com/Microsoft/TypeScript/issues/29729).

- [`ExcludeRestElement`](source/exclude-rest-element.d.ts) - Create a tuple with the [`rest`](https://www.typescriptlang.org/docs/handbook/2/objects.html#tuple-types) element removed.
- [`ArrayReverse`](source/array-reverse.d.ts) - Reverse the order of elements in a tuple type.

@@ -480,2 +483,4 @@ ### Numeric

```
`Partial<T>` can be reverted with [`UnwrapPartial`](source/unwrap-partial.d.ts).
</details>

@@ -482,0 +487,0 @@

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

```
// @exactOptionalPropertyTypes: true
import type {AllExtend} from 'type-fest';
// `exactOptionalPropertyTypes` enabled
type A = AllExtend<[1?, 2?, 3?], number>;
//=> true
```
// `exactOptionalPropertyTypes` disabled
type B = AllExtend<[1?, 2?, 3?], number>;
//=> false
```
// @exactOptionalPropertyTypes: false
import type {AllExtend} from 'type-fest';
// `exactOptionalPropertyTypes` disabled
type C = AllExtend<[1?, 2?, 3?], number | undefined>;
type A = AllExtend<[1?, 2?, 3?], number>;
//=> boolean
type B = AllExtend<[1?, 2?, 3?], number | undefined>;
//=> true

@@ -95,0 +98,0 @@ ```

@@ -48,3 +48,3 @@ import type {Sum} from './sum.d.ts';

type Slice = typeof slice;
//=> [1, '2', { readonly a: 3; }]
//=> [1, '2', {readonly a: 3}]

@@ -51,0 +51,0 @@ const value = slice[2].a;

@@ -79,11 +79,11 @@ import type {StaticPartOfArray, VariablePartOfArray} from './internal/index.d.ts';

type Months0 = ArraySplice<SomeMonths0, 1, 0, ['Feb', 'March']>;
//=> ['January', 'Feb', 'March', 'April', 'June'];
//=> ['January', 'Feb', 'March', 'April', 'June']
type SomeMonths1 = ['January', 'April', 'June'];
type Months1 = ArraySplice<SomeMonths1, 1, 1>;
//=> ['January', 'June'];
//=> ['January', 'June']
type SomeMonths2 = ['January', 'Foo', 'April'];
type Months2 = ArraySplice<SomeMonths2, 1, 1, ['Feb', 'March']>;
//=> ['January', 'Feb', 'March', 'April'];
//=> ['January', 'Feb', 'March', 'April']
```

@@ -90,0 +90,0 @@

@@ -86,3 +86,3 @@ import type {IsEqual} from './is-equal.d.ts';

// e: {
// h: string | boolean
// h: string | boolean;
// };

@@ -89,0 +89,0 @@ // j: boolean;

@@ -56,7 +56,7 @@ /**

//=> {
// foo: {
// foo: {
// a: string;
// complexType: SomeComplexType1 & SomeComplexType2;
// b: string;
// complexType: SomeComplexType1 & SomeComplexType2;
// };
// };
// }

@@ -63,0 +63,0 @@ ```

@@ -37,3 +37,3 @@ import type {KeysOfUnion} from './keys-of-union.d.ts';

const aValue = omittedUnion.a;
//=> Error: `a` is not a property of `{discriminant: 'A' | 'B'}`
// Error: `a` is not a property of `{discriminant: 'A' | 'B'}`
}

@@ -78,11 +78,11 @@ ```

const aValue = omittedUnion.a;
//=> OK
// OK
// @ts-expect-error
const fooValue = omittedUnion.foo;
//=> Error: `foo` is not a property of `{discriminant: 'A'; a: string}`
// Error: `foo` is not a property of `{discriminant: 'A'; a: string}`
// @ts-expect-error
const barValue = omittedUnion.bar;
//=> Error: `bar` is not a property of `{discriminant: 'A'; a: string}`
// Error: `bar` is not a property of `{discriminant: 'A'; a: string}`
}

@@ -89,0 +89,0 @@ ```

@@ -28,3 +28,3 @@ import type {KeysOfUnion} from './keys-of-union.d.ts';

type PickedUnion = Pick<Union, 'discriminant' | 'foo'>;
//=> {discriminant: 'A' | 'B', foo: {bar: string} | {baz: string}}
//=> {discriminant: 'A' | 'B'; foo: {bar: string} | {baz: string}}

@@ -40,3 +40,3 @@ declare const pickedUnion: PickedUnion;

const barValue = pickedUnion.foo.bar;
//=> Error: Property 'bar' does not exist on type '{bar: string} | {baz: string}'.
// Error: Property 'bar' does not exist on type '{bar: string} | {baz: string}'.
}

@@ -75,11 +75,11 @@ ```

const barValue = pickedUnion.foo.bar;
//=> OK
// OK
// @ts-expect-error
const extraneousValue = pickedUnion.extraneous;
//=> Error: Property `extraneous` does not exist on type `Pick<A, 'discriminant' | 'foo'>`.
// Error: Property `extraneous` does not exist on type `Pick<A, 'discriminant' | 'foo'>`.
// @ts-expect-error
const bazValue = pickedUnion.foo.baz;
//=> Error: `bar` is not a property of `{discriminant: 'A'; a: string}`.
// Error: `bar` is not a property of `{discriminant: 'A'; a: string}`.
}

@@ -86,0 +86,0 @@ ```

@@ -32,3 +32,3 @@ import type {ObjectValue} from './internal/index.d.ts';

onlyAcceptName({name: 'name', id: 1});
//=> `id` is excess
// `id` is excess

@@ -35,0 +35,0 @@ // TypeScript does not complain about excess properties when the provided value is a variable (not an object literal).

@@ -71,10 +71,10 @@ import type {ApplyDefaultOptions} from './internal/index.d.ts';

const fooWithoutA: FooWithoutA = {a: 1, b: '2'};
//=> errors: 'a' does not exist in type '{ b: string; }'
// errors: 'a' does not exist in type '{ b: string; }'
type FooWithoutB = Except<Foo, 'b', {requireExactProps: true}>;
//=> {a: number} & Partial<Record<"b", never>>
//=> {a: number} & Partial<Record<'b', never>>
// @ts-expect-error
const fooWithoutB: FooWithoutB = {a: 1, b: '2'};
//=> errors at 'b': Type 'string' is not assignable to type 'undefined'.
// errors at 'b': Type 'string' is not assignable to type 'undefined'.

@@ -94,3 +94,3 @@ // The `Omit` utility type doesn't work when omitting specific keys from objects containing index signatures.

type PostPayload = Omit<UserData, 'email'>;
//=> { [x: string]: string; [x: number]: string; }
//=> {[x: string]: string; [x: number]: string}

@@ -100,3 +100,3 @@ // In situations like this, `Except` works better.

type PostPayloadFixed = Except<UserData, 'email'>;
//=> { [x: string]: string; name: string; role: 'admin' | 'user'; }
//=> {[x: string]: string; name: string; role: 'admin' | 'user'}
```

@@ -103,0 +103,0 @@

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

type Config = ExclusifyUnion<FileConfig | InlineConfig>;
//=> {filePath: string; content?: never} | {content: string; filePath?: never}
//=> {
// filePath: string;
// content?: never;
// } | {
// content: string;
// filePath?: never;
// }

@@ -40,3 +46,3 @@ declare function loadConfig2(options: Config): void;

loadConfig2({filePath: './config.json', content: '{ "name": "app" }'});
//=> Error: Argument of type '{ filePath: string; content: string; }' is not assignable to parameter of type '{ filePath: string; content?: never; } | { content: string; filePath?: never; }'.
// Error: Argument of type '{ filePath: string; content: string; }' is not assignable to parameter of type '{ filePath: string; content?: never; } | { content: string; filePath?: never; }'.

@@ -68,3 +74,11 @@ loadConfig2({filePath: './config.json'}); // Ok

type Payment = ExclusifyUnion<CardPayment | PaypalPayment>;
//=> {amount: number; cardNumber: string; paypalId?: never} | {amount: number; paypalId: string; cardNumber?: never}
//=> {
// amount: number;
// cardNumber: string;
// paypalId?: never;
// } | {
// amount: number;
// paypalId: string;
// cardNumber?: never;
// }

@@ -82,12 +96,32 @@ function processPayment2(payment: Payment) {

type A = ExclusifyUnion<{a: string} | {b: number}>;
//=> {a: string; b?: never} | {a?: never; b: number}
//=> {a: string; b?: never} | {b: number; a?: never}
type B = ExclusifyUnion<{a: string} | {b: number} | {c: boolean}>;
//=> {a: string; b?: never; c?: never} | {a?: never; b: number; c?: never} | {a?: never; b?: never; c: boolean}
//=> {
// a: string;
// b?: never;
// c?: never;
// } | {
// b: number;
// a?: never;
// c?: never;
// } | {
// c: boolean;
// a?: never;
// b?: never;
// }
type C = ExclusifyUnion<{a: string; b: number} | {b: string; c: number}>;
//=> {a: string; b: number; c?: never} | {a?: never; b: string; c: number}
//=> {
// a: string;
// b: number;
// c?: never;
// } | {
// b: string;
// c: number;
// a?: never;
// }
type D = ExclusifyUnion<{a?: 1; readonly b: 2} | {d: 4}>;
//=> {a?: 1; readonly b: 2; d?: never} | {a?: never; b?: never; d: 4}
//=> {a?: 1; readonly b: 2; d?: never} | {d: 4; a?: never; b?: never}
```

@@ -94,0 +128,0 @@

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

color.pop();
//=> Error: Property 'pop' does not exist on type 'FixedLengthArray<number, 3>'.
// Error: Property 'pop' does not exist on type 'FixedLengthArray<number, 3>'.
```

@@ -60,3 +60,3 @@

const alpha = color[3];
//=> Error: Property '3' does not exist on type 'FixedLengthArray<number, 3>'.
// Error: Property '3' does not exist on type 'FixedLengthArray<number, 3>'.

@@ -71,15 +71,15 @@ // You can write to valid indices.

color[3] = 0.5;
//=> Error: Property '3' does not exist on type 'FixedLengthArray<number, 3>'.
// Error: Property '3' does not exist on type 'FixedLengthArray<number, 3>'.
// @ts-expect-error
color.push(0.5);
//=> Error: Property 'push' does not exist on type 'FixedLengthArray<number, 3>'.
// Error: Property 'push' does not exist on type 'FixedLengthArray<number, 3>'.
// @ts-expect-error
color = [0, 128, 255, 0.5];
//=> Error: Type '[number, number, number, number]' is not assignable to type 'FixedLengthArray<number, 3>'. Types of property 'length' are incompatible.
// Error: Type '[number, number, number, number]' is not assignable to type 'FixedLengthArray<number, 3>'. Types of property 'length' are incompatible.
// @ts-expect-error
color.length = 4;
//=> Error: Cannot assign to 'length' because it is a read-only property.
// Error: Cannot assign to 'length' because it is a read-only property.

@@ -86,0 +86,0 @@ function toHex([r, g, b]: readonly [number, number, number]) {

@@ -190,7 +190,13 @@ import type {ApplyDefaultOptions, ToString} from './internal/index.d.ts';

const getName = (apiResponse: ApiResponse) => get(apiResponse, 'hits.hits[0]._source.name');
//=> (apiResponse: ApiResponse) => {given: string[]; family: string}[] | undefined
//=> (apiResponse: ApiResponse) => {
// given: string[];
// family: string;
// }[] | undefined
// Path also supports a readonly array of strings
const getNameWithPathArray = (apiResponse: ApiResponse) => get(apiResponse, ['hits', 'hits', '0', '_source', 'name']);
//=> (apiResponse: ApiResponse) => {given: string[]; family: string}[] | undefined
//=> (apiResponse: ApiResponse) => {
// given: string[];
// family: string;
// }[] | undefined

@@ -202,3 +208,3 @@ // Non-strict mode:

type B = Get<Record<string, string>, 'foo', {strict: true}>;
// => string | undefined
//=> string | undefined
```

@@ -205,0 +211,0 @@

@@ -20,4 +20,4 @@ import type {IntRange} from './int-range.d.ts';

type Age = IntClosedRange<0, 120>;
//=> 0 | 1 | 2 | ... | 119 | 120
type Age = IntClosedRange<0, 20>;
//=> 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20

@@ -24,0 +24,0 @@ type FontSize = IntClosedRange<10, 20>;

@@ -20,4 +20,4 @@ import type {TupleOf} from './tuple-of.d.ts';

type Age = IntRange<0, 120>;
//=> 0 | 1 | 2 | ... | 119
type Age = IntRange<0, 20>;
//=> 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19

@@ -24,0 +24,0 @@ type FontSize = IntRange<10, 20>;

@@ -12,3 +12,3 @@ import type {Simplify} from '../simplify.d.ts';

import type {MapsSetsOrArrays, NonRecursiveType} from './type.d.ts';
import type {ToString} from './string.d.ts';
import type {StringToNumber, ToString} from './string.d.ts';

@@ -269,2 +269,26 @@ /**

/**
Normalize keys by including string and number representations wherever applicable.
@example
```ts
type A = NormalizedKeys<0 | '1'>;
//=> 0 | '0' | 1 | '1'
type B = NormalizedKeys<string>;
//=> string | number
type C = NormalizedKeys<number>;
//=> number | `${number}`
type D = NormalizedKeys<symbol | 'foo'>;
//=> symbol | 'foo'
```
*/
export type NormalizedKeys<Keys extends PropertyKey> =
| Keys
| (string extends Keys ? number : never)
| StringToNumber<Keys & string>
| ToString<Keys & number>;
export {};

@@ -210,3 +210,3 @@ import type {Primitive} from './primitive.d.ts';

const eitherId = getId({asString: runtimeBoolean});
//=> number | string
//=> string | number
```

@@ -240,3 +240,4 @@

const symbolLiteral = Symbol('literal');
const symbolValue = Symbol('value');
let symbolValue = Symbol('value1');
symbolValue = Symbol('value2');

@@ -243,0 +244,0 @@ get({[symbolLiteral]: 1} as const, symbolLiteral);

@@ -41,3 +41,3 @@ /**

type A = IsTrue<never>;
// ^? type A = never
//=> never

@@ -49,3 +49,3 @@ // If you don't want that behaviour, you can explicitly add an `IsNever` check before the distributive conditional.

type B = IsTrueFixed<never>;
// ^? type B = false
//=> false
```

@@ -52,0 +52,0 @@

@@ -15,3 +15,3 @@ import type {IsNull} from './is-null.d.ts';

type A = IsUnknown<unknown>;
//=> unknown
//=> true

@@ -18,0 +18,0 @@ type B = IsUnknown<any>;

@@ -22,13 +22,11 @@ import type {JsonPrimitive} from './json-value.d.ts';

JSON.stringify(error);
//=> {"map": {}}
console.log(JSON.stringify(error)); // {"map": {}}
const good: Jsonifiable = {
number: 3,
date: new Date(),
date: new Date('2025-12-25'),
missing: undefined,
};
JSON.stringify(good);
//=> {"number": 3, "date": "2022-10-17T22:22:35.920Z"}
console.log(JSON.stringify(good)); // {"number": 3, "date": "2025-12-25T00:00:00.000Z"}
```

@@ -35,0 +33,0 @@

@@ -20,3 +20,3 @@ /**

type StringKeysOfFoo = KeyAsString<Foo>;
//=> '1' | 'stringKey'
//=> 'stringKey' | '1'
```

@@ -23,0 +23,0 @@

@@ -449,21 +449,21 @@ import type {ConditionalSimplifyDeep} from './conditional-simplify-deep.d.ts';

type FooBar = MergeDeep<Foo, Bar>;
// { foo: "foo"; bar: "bar"; fooBar: number[]}
//=> {foo: 'foo'; bar: 'bar'; fooBar: number[]}
type FooBarSpread = MergeDeep<Foo, Bar, {arrayMergeMode: 'spread'}>;
// { foo: "foo"; bar: "bar"; fooBar: (string | number)[]}
//=> {foo: 'foo'; bar: 'bar'; fooBar: (string | number)[]}
type FooBarArray = MergeDeep<Foo[], Bar[]>;
// (Foo | Bar)[]
//=> (Foo | Bar)[]
type FooBarArrayDeep = MergeDeep<Foo[], Bar[], {recurseIntoArrays: true}>;
// FooBar[]
//=> {foo: 'foo'; bar: 'bar'; fooBar: number[]}[]
type FooBarArraySpreadDeep = MergeDeep<Foo[], Bar[], {recurseIntoArrays: true; arrayMergeMode: 'spread'}>;
// FooBarSpread[]
//=> {foo: 'foo'; bar: 'bar'; fooBar: (string | number)[]}[]
type FooBarTupleDeep = MergeDeep<[Foo, true, 42], [Bar, 'life'], {recurseIntoArrays: true}>;
// [FooBar, 'life', 42]
//=> [{foo: 'foo'; bar: 'bar'; fooBar: number[]}, 'life', 42]
type FooBarTupleWithArrayDeep = MergeDeep<[Foo[], true], [Bar[], 'life', 42], {recurseIntoArrays: true}>;
// [FooBar[], 'life', 42]
//=> [{foo: 'foo'; bar: 'bar'; fooBar: number[]}[], 'life', 42]
```

@@ -470,0 +470,0 @@

@@ -28,10 +28,10 @@ // Helper type. Not useful on its own.

exclusiveOptions = {exclusive1: true};
//=> Works
// Works
exclusiveOptions = {exclusive2: 'hi'};
//=> Works
// Works
// @ts-expect-error
exclusiveOptions = {exclusive1: true, exclusive2: 'hi'};
//=> Error
// Error
```

@@ -38,0 +38,0 @@

@@ -32,3 +32,3 @@ import type {OmitIndexSignature} from './omit-index-signature.d.ts';

export type FooBar = Merge<Foo, Bar>;
// => {
//=> {
// [x: string]: unknown;

@@ -43,2 +43,5 @@ // [x: number]: number;

Note: If you want a merge type that more accurately reflects the runtime behavior of object spread or `Object.assign`, refer to the {@link ObjectMerge} type.
@see {@link ObjectMerge}
@category Object

@@ -45,0 +48,0 @@ */

@@ -16,7 +16,7 @@ /**

foo('a');
//=> OK
// OK
// @ts-expect-error
foo('');
//=> Error: Argument of type '""' is not assignable to parameter of type 'never'.
// Error: Argument of type '""' is not assignable to parameter of type 'never'.

@@ -26,3 +26,3 @@ declare const someString: string;

foo(someString);
//=> Error: Argument of type 'string' is not assignable to parameter of type 'never'.
// Error: Argument of type 'string' is not assignable to parameter of type 'never'.
```

@@ -29,0 +29,0 @@

@@ -11,7 +11,7 @@ /**

sum(1, 2, 3);
//=> 6
// Ok
// @ts-expect-error
sum();
//=> Error: Expected at least 1 arguments, but got 0.
// Error: Expected at least 1 arguments, but got 0.
```

@@ -18,0 +18,0 @@

@@ -77,9 +77,9 @@ import type {IsFloat} from './is-float.d.ts';

type OctalInteger = Integer<0o10>;
//=> 0o10
//=> 8
type BinaryInteger = Integer<0b10>;
//=> 0b10
//=> 2
type HexadecimalInteger = Integer<0x10>;
//=> 0x10
//=> 16
```

@@ -86,0 +86,0 @@

@@ -8,2 +8,3 @@ import type {ArraySplice} from './array-splice.d.ts';

import type {SimplifyDeep} from './simplify-deep.d.ts';
import type {Simplify} from './simplify.d.ts';
import type {UnionToTuple} from './union-to-tuple.d.ts';

@@ -37,7 +38,3 @@ import type {UnknownArray} from './unknown-array.d.ts';

type UsefulInfo = OmitDeep<Info, 'userInfo.uselessInfo'>;
//=> {
// userInfo: {
// name: string;
// };
// };
//=> {userInfo: {name: string}}

@@ -56,11 +53,7 @@ // Supports removing multiple paths

type UsefulInfo1 = OmitDeep<Info1, 'userInfo.uselessInfo' | 'userInfo.uselessField'>;
//=> {
// userInfo: {
// name: string;
// };
// };
//=> {userInfo: {name: string}}
// Supports array
type A = OmitDeep<[1, 'foo', 2], '1'>;
//=> [1, unknown, 2];
//=> [1, unknown, 2]

@@ -82,12 +75,3 @@ // Supports recursing into array

type AddressInfo = OmitDeep<Info2, 'address.1.foo'>;
//=> {
// address: [
// {
// street: string;
// },
// {
// street2: string;
// };
// ];
// };
//=> {address: [{street: string}, {street2: string}]}
```

@@ -142,3 +126,3 @@

: Key extends PropertyKey
? Omit<ObjectT, Key>
? Simplify<Omit<ObjectT, Key>> // `Simplify` to prevent `Omit` from appearing in the resulting type
: ObjectT

@@ -145,0 +129,0 @@ : ObjectT;

@@ -20,3 +20,3 @@ /**

const keyed: Record<'foo', unknown> = {}; // Error
// => TS2739: Type '{}' is missing the following properties from type 'Record<"foo" | "bar", unknown>': foo, bar
// TS2739: Type '{}' is missing the following properties from type 'Record<"foo" | "bar", unknown>': foo, bar
```

@@ -30,8 +30,12 @@

: '❌ `{}` is NOT assignable to `Record<string, unknown>`';
// => '✅ `{}` is assignable to `Record<string, unknown>`'
type IndexedResult = Indexed;
//=> '✅ `{}` is assignable to `Record<string, unknown>`'
type Keyed = {} extends Record<'foo' | 'bar', unknown>
? '✅ `{}` is assignable to `Record<\'foo\' | \'bar\', unknown>`'
: '❌ `{}` is NOT assignable to `Record<\'foo\' | \'bar\', unknown>`';
// => "❌ `{}` is NOT assignable to `Record<'foo' | 'bar', unknown>`"
type KeyedResult = Keyed;
//=> '❌ `{}` is NOT assignable to `Record<\'foo\' | \'bar\', unknown>`'
```

@@ -84,3 +88,3 @@

type ExampleWithoutIndexSignatures = OmitIndexSignature<Example>;
// => { foo: 'bar'; qux?: 'baz' | undefined; }
//=> {foo: 'bar'; qux?: 'baz'}
```

@@ -87,0 +91,0 @@

@@ -18,3 +18,3 @@ import type {Merge} from './merge.d.ts';

type Bar = OverrideProperties<Foo, {b: number}>;
//=> {a: string, b: number}
//=> {a: string; b: number}

@@ -21,0 +21,0 @@ // @ts-expect-error

@@ -95,3 +95,3 @@ import type {StaticPartOfArray, VariablePartOfArray, NonRecursiveType, ToString, IsNumberLike, ApplyDefaultOptions} from './internal/index.d.ts';

type AllPaths = Paths<ArrayExample, {leavesOnly: false}>;
//=> 'array' | `array.${number}` | `array.${number}.foo` | 'tuple' | 'tuple.0' | 'tuple.1' | 'tuple.1.bar'
//=> 'array' | 'tuple' | `array.${number}` | `array.${number}.foo` | 'tuple.0' | 'tuple.1' | 'tuple.1.bar'

@@ -98,0 +98,0 @@ type LeafPaths = Paths<ArrayExample, {leavesOnly: true}>;

@@ -21,7 +21,7 @@ import type {TupleOf} from './tuple-of.d.ts';

const homeFencingTeam: FencingTeam = ['George', 'John'];
//=> Error: Type '[string, string]' is not assignable to type 'readonly [string, string, string]'.
// Error: Type '[string, string]' is not assignable to type 'readonly [string, string, string]'.
// @ts-expect-error
guestFencingTeam.push('Sam');
//=> Error: Property 'push' does not exist on type 'readonly [string, string, string]'.
// Error: Property 'push' does not exist on type 'readonly [string, string, string]'.
```

@@ -28,0 +28,0 @@

import type {BuiltIns, HasMultipleCallSignatures} from './internal/index.d.ts';
import type {IsNever} from './is-never.d.ts';
import type {Simplify} from './simplify.d.ts';

@@ -68,3 +69,3 @@ /**

: T extends object
? RequiredObjectDeep<T>
? Simplify<RequiredObjectDeep<T>> // `Simplify` to prevent `RequiredObjectDeep` from appearing in the resulting type
: unknown;

@@ -71,0 +72,0 @@

@@ -27,11 +27,14 @@ import type {ApplyDefaultOptions} from './internal/object.d.ts';

//=> {
// attendees: Array<{id: number; name: string}>;
// speakers: Array<{id: number; name: string}>;
// };
// attendees: {
// id: number;
// name: string;
// }[];
// speakers: {
// id: number;
// name: string;
// }[];
// }
type ParticipantsCount = Schema<Participants, number, {recurseIntoArrays: false}>;
//=> {
// attendees: number;
// speakers: number;
// };
//=> {attendees: number; speakers: number}
```

@@ -38,0 +41,0 @@

@@ -40,3 +40,3 @@ import type {NonRecursiveType, StringToNumber} from './internal/index.d.ts';

// };
// };
// }
```

@@ -43,0 +43,0 @@

@@ -67,7 +67,7 @@ import type {IsUnknown} from './is-unknown.d.ts';

const fn = (a: number) => a;
//=> fn: (a: number) => number;
//=> (a: number) => number
// We change type of `a` to `string`, but return type is still `number`.
type Fn = SetParameterType<typeof fn, {0: string}>;
//=> (a: string) => number;
//=> (a: string) => number
```

@@ -91,11 +91,11 @@

type HandleOk = SetParameterType<HandleMessage, {0: SuccessData; 1: 'ok'}>;
//=> (data: SuccessData, message: 'ok', ...arguments_: any[]) => void;
//=> (data: SuccessData, message: 'ok', ...arguments_: any[]) => void
// Another way to define the parameters to replace.
type HandleError = SetParameterType<HandleMessage, [data: ErrorData, message: 'error']>;
//=> (data: ErrorData, message: 'error', ...arguments_: any[]) => void;
//=> (data: ErrorData, message: 'error', ...arguments_: any[]) => void
// Change single parameter type.
type HandleWarn = SetParameterType<HandleMessage, {1: 'warn'}>;
//=> (data: Data, message: 'warn', ...arguments_: any[]) => void;
//=> (data: Data, message: 'warn', ...arguments_: any[]) => void

@@ -106,7 +106,7 @@ // Change rest parameter type.

type HandleLog = SetParameterType<HandleMessage, [data: Data, message: 'log', ...arguments_: string[]]>;
//=> (data: Data, message: 'log', ...arguments_: string[]) => void;
//=> (data: Data, message: 'log', ...arguments_: string[]) => void
// Way 2: Input rest parameter type by Object index.
type HandleLog2 = SetParameterType<HandleMessage, {2: string}>;
//=> (data: Data, message: string, ...arguments_: string[]) => void;
//=> (data: Data, message: string, ...arguments_: string[]) => void
```

@@ -113,0 +113,0 @@

@@ -28,9 +28,3 @@ import type {IsAny} from './is-any.d.ts';

type SomeRequiredDeep = SetRequiredDeep<Foo, 'a' | `c.${number}.d`>;
//=> {
// a: number; // Is now required
// b?: string;
// c?: {
// d: number; // Is now required
// }[];
// }
//=> {b?: string; c?: {d: number}[]; a: number}

@@ -37,0 +31,0 @@ // Set specific indices in an array to be required.

@@ -15,3 +15,3 @@ import type {IsUnknown} from './is-unknown.d.ts';

type MyWrappedFunction = SetReturnType<MyFunctionThatCanThrow, ReturnType<MyFunctionThatCanThrow> | undefined>;
//=> (foo: string, bar: number) => boolean | undefined;
//=> (foo: string, bar: number) => boolean | undefined
```

@@ -18,0 +18,0 @@

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

type T4 = SplitOnRestElement<[number, string?], {preserveOptionalModifier: false}>;
//=> [[number, string], [], []] or [[number, string | undefined], [], []]
//=> [[number, string], [], []]
type T5 = SplitOnRestElement<readonly [string?, ...number[]], {preserveOptionalModifier: false}>;
//=> readonly [[string], number[], []] or readonly [[string | undefined], number[], []]
//=> readonly [[string], number[], []]
```

@@ -59,0 +59,0 @@

@@ -29,3 +29,3 @@ import type {NumberAbsolute, ReverseSign} from './internal/index.d.ts';

type E = Subtract<PositiveInfinity, 9999>;
//=> PositiveInfinity
//=> Infinity

@@ -32,0 +32,0 @@ type F = Subtract<PositiveInfinity, PositiveInfinity>;

@@ -26,3 +26,3 @@ import type {TupleOf} from './tuple-of.d.ts';

type D = Sum<PositiveInfinity, -9999>;
//=> PositiveInfinity
//=> Infinity

@@ -29,0 +29,0 @@ type E = Sum<PositiveInfinity, NegativeInfinity>;

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

type ThreeToEight = Range<3, 9>;
//=> '3' | '4' | '5' | '6' | '7' | '8'
//=> '5' | '3' | '4' | '6' | '7' | '8'
```

@@ -36,0 +36,0 @@

@@ -16,23 +16,23 @@ import type {IsTuple} from './is-tuple.d.ts';

type Example1 = TupleToObject<[number, string, boolean]>;
//=> { 0: number; 1: string; 2: boolean }
//=> {0: number; 1: string; 2: boolean}
// Tuples with optional indices
type Example2 = TupleToObject<[number, string?, boolean?]>;
//=> { 0: number; 1?: string; 2?: boolean }
//=> {0: number; 1?: string; 2?: boolean}
// Readonly tuples
type Example3 = TupleToObject<readonly [number, string?]>;
//=> { readonly 0: number; readonly 1?: string }
//=> {readonly 0: number; readonly 1?: string}
// Non-tuple arrays get transformed into index signatures
type Example4 = TupleToObject<string[]>;
//=> { [x: number]: string }
//=> {[x: number]: string}
// Tuples with rest elements
type Example5 = TupleToObject<[number, string, ...boolean[]]>;
//=> { [x: number]: number | string | boolean; 0: number; 1: string }
//=> {[x: number]: string | number | boolean; 0: number; 1: string}
// Tuple labels are not preserved
type Example6 = TupleToObject<[x: number, y: number]>;
//=> { 0: number; 1: number }
//=> {0: number; 1: number}
```

@@ -39,0 +39,0 @@

@@ -42,3 +42,3 @@ /**

type ErroringType = typeof erroringType[number];
//=> Type 'Set<string>' has no matching index signature for type 'number'. ts(2537)
// Error: Type 'Set<string>' has no matching index signature for type 'number'. ts(2537)

@@ -45,0 +45,0 @@ const numberBool: {[n: number]: boolean} = {1: true};

@@ -13,3 +13,3 @@ /**

type Intersection = UnionToIntersection<Union>;
//=> {the(): void; great(arg: string): void; escape: boolean};
//=> {the(): void} & {great(arg: string): void} & {escape: boolean}
```

@@ -16,0 +16,0 @@

@@ -14,4 +14,3 @@ /**

toJson({hello: 'world'});
//=> '{"hello":"world"}'
toJson({hello: 'world'}); // Ok

@@ -22,7 +21,8 @@ function isObject(value: unknown): value is UnknownRecord {

isObject({hello: 'world'});
//=> true
const value: unknown = {hello: 'world'};
isObject('hello');
//=> false
if (isObject(value)) {
const v = value;
//=> UnknownRecord
}
```

@@ -29,0 +29,0 @@

@@ -11,3 +11,3 @@ /**

type A = ValueOf<{id: number; name: string; active: boolean}>;
//=> number | string | boolean
//=> string | number | boolean

@@ -18,3 +18,3 @@ type B = ValueOf<{id: number; name: string; active: boolean}, 'name'>;

type C = ValueOf<{id: number; name: string; active: boolean}, 'id' | 'name'>;
//=> number | string
//=> string | number
```

@@ -21,0 +21,0 @@

@@ -34,6 +34,6 @@ import type {

type Example1 = Words<'p2pNetwork', {splitOnNumbers: true}>;
//=> ["p", "2", "p", "Network"]
//=> ['p', '2', 'p', 'Network']
type Example2 = Words<'p2pNetwork', {splitOnNumbers: false}>;
//=> ["p2p", "Network"]
//=> ['p2p', 'Network']
```

@@ -40,0 +40,0 @@ */