type-fest
Advanced tools
| 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:*" |
+5
-0
@@ -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]) { |
+9
-3
@@ -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 @@ |
+10
-7
@@ -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>; |
+1
-1
@@ -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 @@ */ |
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
524734
2.67%200
1.52%12750
2.43%1053
0.48%23
4.55%