type-fest 2.18.1 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/index.d.ts +81 -72
  2. package/package.json +11 -10
  3. package/readme.md +26 -16
  4. package/source/async-return-type.d.ts +1 -3
  5. package/source/asyncify.d.ts +1 -2
  6. package/source/basic.d.ts +1 -1
  7. package/source/camel-case.d.ts +2 -2
  8. package/source/camel-cased-properties-deep.d.ts +5 -5
  9. package/source/camel-cased-properties.d.ts +3 -3
  10. package/source/conditional-except.d.ts +2 -2
  11. package/source/conditional-keys.d.ts +11 -11
  12. package/source/conditional-pick-deep.d.ts +102 -0
  13. package/source/conditional-pick.d.ts +2 -2
  14. package/source/conditional-simplify.d.ts +32 -0
  15. package/source/delimiter-case.d.ts +30 -24
  16. package/source/delimiter-cased-properties-deep.d.ts +6 -6
  17. package/source/delimiter-cased-properties.d.ts +2 -2
  18. package/source/empty-object.d.ts +46 -0
  19. package/source/enforce-optional.d.ts +47 -0
  20. package/source/entries.d.ts +3 -3
  21. package/source/entry.d.ts +3 -3
  22. package/source/exact.d.ts +31 -9
  23. package/source/fixed-length-array.d.ts +2 -2
  24. package/source/get.d.ts +52 -45
  25. package/source/has-optional-keys.d.ts +1 -1
  26. package/source/has-required-keys.d.ts +1 -1
  27. package/source/iterable-element.d.ts +4 -4
  28. package/source/join.d.ts +2 -2
  29. package/source/jsonify.d.ts +42 -20
  30. package/source/last-array-element.d.ts +4 -4
  31. package/source/literal-to-primitive.d.ts +12 -12
  32. package/source/merge.d.ts +33 -10
  33. package/source/observable-like.d.ts +3 -2
  34. package/source/{remove-index-signature.d.ts → omit-index-signature.d.ts} +14 -11
  35. package/source/package-json.d.ts +55 -29
  36. package/source/partial-deep.d.ts +29 -31
  37. package/source/partial-on-undefined-deep.d.ts +12 -12
  38. package/source/pascal-cased-properties-deep.d.ts +5 -5
  39. package/source/pascal-cased-properties.d.ts +2 -2
  40. package/source/pick-index-signature.d.ts +102 -0
  41. package/source/readonly-deep.d.ts +14 -16
  42. package/source/require-all-or-none.d.ts +1 -1
  43. package/source/require-at-least-one.d.ts +4 -4
  44. package/source/schema.d.ts +22 -22
  45. package/source/set-non-nullable.d.ts +35 -0
  46. package/source/set-optional.d.ts +4 -4
  47. package/source/set-required.d.ts +4 -4
  48. package/source/simplify.d.ts +1 -26
  49. package/source/split.d.ts +2 -2
  50. package/source/spread.d.ts +4 -4
  51. package/source/tsconfig-json.d.ts +16 -12
  52. package/source/tuple-to-union.d.ts +51 -0
  53. package/source/union-to-intersection.d.ts +3 -3
  54. package/source/writable.d.ts +4 -4
  55. package/source/mutable.d.ts +0 -5
  56. package/source/promise-value.d.ts +0 -29
package/source/merge.d.ts CHANGED
@@ -1,7 +1,15 @@
1
- import type {Except} from './except';
2
- import type {Simplify} from './simplify';
1
+ import type {OmitIndexSignature} from './omit-index-signature';
2
+ import type {PickIndexSignature} from './pick-index-signature';
3
+ import type {EnforceOptional} from './enforce-optional';
3
4
 
4
- type Merge_<FirstType, SecondType> = Except<FirstType, Extract<keyof FirstType, keyof SecondType>> & SecondType;
5
+ // Merges two objects without worrying about index signatures or optional keys.
6
+ type SimpleMerge<Destination, Source> = {
7
+ [Key in keyof Destination | keyof Source]: Key extends keyof Source
8
+ ? Source[Key]
9
+ : Key extends keyof Destination
10
+ ? Destination[Key]
11
+ : never;
12
+ };
5
13
 
6
14
  /**
7
15
  Merge two types into a new type. Keys of the second type overrides keys of the first type.
@@ -10,18 +18,33 @@ Merge two types into a new type. Keys of the second type overrides keys of the f
10
18
  ```
11
19
  import type {Merge} from 'type-fest';
12
20
 
13
- type Foo = {
14
- a: number;
15
- b: string;
16
- };
21
+ interface Foo {
22
+ [x: string]: unknown;
23
+ [x: number]: unknown;
24
+ foo: string;
25
+ bar: symbol;
26
+ }
17
27
 
18
28
  type Bar = {
19
- b: number;
29
+ [x: number]: number;
30
+ [x: symbol]: unknown;
31
+ bar: Date;
32
+ baz: boolean;
20
33
  };
21
34
 
22
- const ab: Merge<Foo, Bar> = {a: 1, b: 2};
35
+ export type FooBar = Merge<Foo, Bar>;
36
+ // => {
37
+ // [x: string]: unknown;
38
+ // [x: number]: number;
39
+ // [x: symbol]: unknown;
40
+ // foo: string;
41
+ // bar: Date;
42
+ // baz: boolean;
43
+ // }
23
44
  ```
24
45
 
25
46
  @category Object
26
47
  */
27
- export type Merge<FirstType, SecondType> = Simplify<Merge_<FirstType, SecondType>>;
48
+ export type Merge<Destination, Source> = EnforceOptional<
49
+ SimpleMerge<PickIndexSignature<Destination>, PickIndexSignature<Source>>
50
+ & SimpleMerge<OmitIndexSignature<Destination>, OmitIndexSignature<Source>>>;
@@ -1,4 +1,5 @@
1
1
  declare global {
2
+ // eslint-disable-next-line @typescript-eslint/consistent-type-definitions -- It has to be an `interface` so that it can be merged.
2
3
  interface SymbolConstructor {
3
4
  readonly observable: symbol;
4
5
  }
@@ -56,7 +57,7 @@ But `Observable` implementations have evolved to preferring case 2 and some impl
56
57
 
57
58
  @category Observable
58
59
  */
59
- export interface ObservableLike<ValueType = unknown> {
60
+ export type ObservableLike<ValueType = unknown> = {
60
61
  subscribe(observer?: Partial<Observer<ValueType>>): Unsubscribable;
61
62
  [Symbol.observable](): ObservableLike<ValueType>;
62
- }
63
+ };
@@ -1,5 +1,7 @@
1
1
  /**
2
- Remove any index signatures from the given object type, so that only explicitly defined properties remain.
2
+ Omit any index signatures from the given object type, leaving only explicitly defined properties.
3
+
4
+ This is the counterpart of `PickIndexSignature`.
3
5
 
4
6
  Use-cases:
5
7
  - Remove overly permissive signatures from third-party types.
@@ -34,20 +36,20 @@ type Keyed = {} extends Record<'foo' | 'bar', unknown>
34
36
  Using a [mapped type](https://www.typescriptlang.org/docs/handbook/2/mapped-types.html#further-exploration), you can then check for each `KeyType` of `ObjectType`...
35
37
 
36
38
  ```
37
- import type {RemoveIndexSignature} from 'type-fest';
39
+ import type {OmitIndexSignature} from 'type-fest';
38
40
 
39
- type RemoveIndexSignature<ObjectType> = {
41
+ type OmitIndexSignature<ObjectType> = {
40
42
  [KeyType in keyof ObjectType // Map each key of `ObjectType`...
41
- ]: ObjectType[KeyType]; // ...to its original value, i.e. `RemoveIndexSignature<Foo> == Foo`.
43
+ ]: ObjectType[KeyType]; // ...to its original value, i.e. `OmitIndexSignature<Foo> == Foo`.
42
44
  };
43
45
  ```
44
46
 
45
47
  ...whether an empty object (`{}`) would be assignable to an object with that `KeyType` (`Record<KeyType, unknown>`)...
46
48
 
47
49
  ```
48
- import type {RemoveIndexSignature} from 'type-fest';
50
+ import type {OmitIndexSignature} from 'type-fest';
49
51
 
50
- type RemoveIndexSignature<ObjectType> = {
52
+ type OmitIndexSignature<ObjectType> = {
51
53
  [KeyType in keyof ObjectType
52
54
  // Is `{}` assignable to `Record<KeyType, unknown>`?
53
55
  as {} extends Record<KeyType, unknown>
@@ -60,9 +62,9 @@ type RemoveIndexSignature<ObjectType> = {
60
62
  If `{}` is assignable, it means that `KeyType` is an index signature and we want to remove it. If it is not assignable, `KeyType` is a "real" key and we want to keep it.
61
63
 
62
64
  ```
63
- import type {RemoveIndexSignature} from 'type-fest';
65
+ import type {OmitIndexSignature} from 'type-fest';
64
66
 
65
- type RemoveIndexSignature<ObjectType> = {
67
+ type OmitIndexSignature<ObjectType> = {
66
68
  [KeyType in keyof ObjectType
67
69
  as {} extends Record<KeyType, unknown>
68
70
  ? never // => Remove this `KeyType`.
@@ -73,7 +75,7 @@ type RemoveIndexSignature<ObjectType> = {
73
75
 
74
76
  @example
75
77
  ```
76
- import type {RemoveIndexSignature} from 'type-fest';
78
+ import type {OmitIndexSignature} from 'type-fest';
77
79
 
78
80
  interface Example {
79
81
  // These index signatures will be removed.
@@ -91,13 +93,14 @@ interface Example {
91
93
  qux?: 'baz';
92
94
  }
93
95
 
94
- type ExampleWithoutIndexSignatures = RemoveIndexSignature<Example>;
96
+ type ExampleWithoutIndexSignatures = OmitIndexSignature<Example>;
95
97
  // => { foo: 'bar'; qux?: 'baz' | undefined; }
96
98
  ```
97
99
 
100
+ @see PickIndexSignature
98
101
  @category Object
99
102
  */
100
- export type RemoveIndexSignature<ObjectType> = {
103
+ export type OmitIndexSignature<ObjectType> = {
101
104
  [KeyType in keyof ObjectType as {} extends Record<KeyType, unknown>
102
105
  ? never
103
106
  : KeyType]: ObjectType[KeyType];
@@ -1,4 +1,5 @@
1
1
  import type {LiteralUnion} from './literal-union';
2
+ import type {JsonObject, JsonValue} from './basic';
2
3
 
3
4
  declare namespace PackageJson {
4
5
  /**
@@ -26,8 +27,8 @@ declare namespace PackageJson {
26
27
  email?: string;
27
28
  };
28
29
 
29
- export interface DirectoryLocations {
30
- [directoryType: string]: unknown;
30
+ export type DirectoryLocations = {
31
+ [directoryType: string]: JsonValue | undefined;
31
32
 
32
33
  /**
33
34
  Location for executable scripts. Sugar to generate entries in the `bin` property by walking the folder.
@@ -58,7 +59,7 @@ declare namespace PackageJson {
58
59
  Location for test files.
59
60
  */
60
61
  test?: string;
61
- }
62
+ };
62
63
 
63
64
  export type Scripts = {
64
65
  /**
@@ -211,27 +212,29 @@ declare namespace PackageJson {
211
212
  Conditions which provide a way to resolve a package entry point based on the environment.
212
213
  */
213
214
  export type ExportCondition = LiteralUnion<
214
- | 'import'
215
- | 'require'
216
- | 'node'
217
- | 'node-addons'
218
- | 'deno'
219
- | 'browser'
220
- | 'electron'
221
- | 'react-native'
222
- | 'default',
223
- string
215
+ | 'import'
216
+ | 'require'
217
+ | 'node'
218
+ | 'node-addons'
219
+ | 'deno'
220
+ | 'browser'
221
+ | 'electron'
222
+ | 'react-native'
223
+ | 'default',
224
+ string
224
225
  >;
225
226
 
227
+ type ExportConditions = {[condition in ExportCondition]: Exports};
228
+
226
229
  /**
227
230
  Entry points of a module, optionally with conditions and subpath exports.
228
231
  */
229
232
  export type Exports =
230
233
  | null
231
234
  | string
232
- | string[]
233
- | {[key in ExportCondition]: Exports}
234
- | {[key: string]: Exports}; // eslint-disable-line @typescript-eslint/consistent-indexed-object-style
235
+ | Array<string | ExportConditions>
236
+ | ExportConditions
237
+ | {[path: string]: Exports};
235
238
 
236
239
  /**
237
240
  Import map entries of a module, optionally with conditions.
@@ -240,6 +243,7 @@ declare namespace PackageJson {
240
243
  [key: string]: string | {[key in ExportCondition]: Exports};
241
244
  };
242
245
 
246
+ // eslint-disable-next-line @typescript-eslint/consistent-type-definitions
243
247
  export interface NonStandardEntryPoints {
244
248
  /**
245
249
  An ECMAScript module ID that is the primary entry point to the program.
@@ -272,7 +276,7 @@ declare namespace PackageJson {
272
276
  sideEffects?: boolean | string[];
273
277
  }
274
278
 
275
- export interface TypeScriptConfiguration {
279
+ export type TypeScriptConfiguration = {
276
280
  /**
277
281
  Location of the bundled TypeScript declaration file.
278
282
  */
@@ -287,12 +291,12 @@ declare namespace PackageJson {
287
291
  Location of the bundled TypeScript declaration file. Alias of `types`.
288
292
  */
289
293
  typings?: string;
290
- }
294
+ };
291
295
 
292
296
  /**
293
297
  An alternative configuration for Yarn workspaces.
294
298
  */
295
- export interface WorkspaceConfig {
299
+ export type WorkspaceConfig = {
296
300
  /**
297
301
  An array of workspace pattern strings which contain the workspace packages.
298
302
  */
@@ -304,7 +308,7 @@ declare namespace PackageJson {
304
308
  [Read more](https://classic.yarnpkg.com/blog/2018/02/15/nohoist/)
305
309
  */
306
310
  nohoist?: WorkspacePattern[];
307
- }
311
+ };
308
312
 
309
313
  /**
310
314
  A workspace pattern points to a directory or group of directories which contain packages that should be included in the workspace installation process.
@@ -317,7 +321,7 @@ declare namespace PackageJson {
317
321
  */
318
322
  type WorkspacePattern = string;
319
323
 
320
- export interface YarnConfiguration {
324
+ export type YarnConfiguration = {
321
325
  /**
322
326
  Used to configure [Yarn workspaces](https://classic.yarnpkg.com/docs/workspaces/).
323
327
 
@@ -338,18 +342,19 @@ declare namespace PackageJson {
338
342
  Selective version resolutions. Allows the definition of custom package versions inside dependencies without manual edits in the `yarn.lock` file.
339
343
  */
340
344
  resolutions?: Dependency;
341
- }
345
+ };
342
346
 
343
- export interface JSPMConfiguration {
347
+ export type JSPMConfiguration = {
344
348
  /**
345
349
  JSPM configuration.
346
350
  */
347
351
  jspm?: PackageJson;
348
- }
352
+ };
349
353
 
350
354
  /**
351
355
  Type for [npm's `package.json` file](https://docs.npmjs.com/creating-a-package-json-file). Containing standard npm properties.
352
356
  */
357
+ // eslint-disable-next-line @typescript-eslint/consistent-type-definitions
353
358
  export interface PackageJsonStandard {
354
359
  /**
355
360
  The name of the package.
@@ -479,7 +484,7 @@ declare namespace PackageJson {
479
484
  /**
480
485
  Is used to set configuration parameters used in package scripts that persist across upgrades.
481
486
  */
482
- config?: Record<string, unknown>;
487
+ config?: JsonObject;
483
488
 
484
489
  /**
485
490
  The dependencies of the package.
@@ -520,7 +525,7 @@ declare namespace PackageJson {
520
525
  Engines that this package runs on.
521
526
  */
522
527
  engines?: {
523
- [EngineName in 'npm' | 'node' | string]?: string;
528
+ [EngineName in 'npm' | 'node' | string]?: string; // eslint-disable-line @typescript-eslint/no-redundant-type-constituents
524
529
  };
525
530
 
526
531
  /**
@@ -621,11 +626,30 @@ declare namespace PackageJson {
621
626
  };
622
627
  }
623
628
 
624
- export interface PublishConfig {
629
+ /**
630
+ Type for [`package.json` file used by the Node.js runtime](https://nodejs.org/api/packages.html#nodejs-packagejson-field-definitions).
631
+ */
632
+ export type NodeJsStandard = {
633
+ /**
634
+ Defines which package manager is expected to be used when working on the current project. It can set to any of the [supported package managers](https://nodejs.org/api/corepack.html#supported-package-managers), and will ensure that your teams use the exact same package manager versions without having to install anything else than Node.js.
635
+
636
+ __This field is currently experimental and needs to be opted-in; check the [Corepack](https://nodejs.org/api/corepack.html) page for details about the procedure.__
637
+
638
+ @example
639
+ ```json
640
+ {
641
+ "packageManager": "<package manager name>@<version>"
642
+ }
643
+ ```
644
+ */
645
+ packageManager?: string;
646
+ };
647
+
648
+ export type PublishConfig = {
625
649
  /**
626
650
  Additional, less common properties from the [npm docs on `publishConfig`](https://docs.npmjs.com/cli/v7/configuring-npm/package-json#publishconfig).
627
651
  */
628
- [additionalProperties: string]: unknown;
652
+ [additionalProperties: string]: JsonValue | undefined;
629
653
 
630
654
  /**
631
655
  When publishing scoped packages, the access level defaults to restricted. If you want your scoped package to be publicly viewable (and installable) set `--access=public`. The only valid values for access are public and restricted. Unscoped packages always have an access level of public.
@@ -645,7 +669,7 @@ declare namespace PackageJson {
645
669
  Default: `'latest'`
646
670
  */
647
671
  tag?: string;
648
- }
672
+ };
649
673
  }
650
674
 
651
675
  /**
@@ -654,6 +678,8 @@ Type for [npm's `package.json` file](https://docs.npmjs.com/creating-a-package-j
654
678
  @category File
655
679
  */
656
680
  export type PackageJson =
681
+ JsonObject &
682
+ PackageJson.NodeJsStandard &
657
683
  PackageJson.PackageJsonStandard &
658
684
  PackageJson.NonStandardEntryPoints &
659
685
  PackageJson.TypeScriptConfiguration &
@@ -3,14 +3,14 @@ import type {BuiltIns} from './internal';
3
3
  /**
4
4
  @see PartialDeep
5
5
  */
6
- export interface PartialDeepOptions {
6
+ export type PartialDeepOptions = {
7
7
  /**
8
8
  Whether to affect the individual elements of arrays and tuples.
9
9
 
10
- @default true
10
+ @default false
11
11
  */
12
12
  readonly recurseIntoArrays?: boolean;
13
- }
13
+ };
14
14
 
15
15
  /**
16
16
  Create a type from another type with all keys and nested keys set to optional.
@@ -40,7 +40,7 @@ const applySavedSettings = (savedSettings: PartialDeep<Settings>) => {
40
40
  settings = applySavedSettings({textEditor: {fontWeight: 500}});
41
41
  ```
42
42
 
43
- By default, this also affects array and tuple types:
43
+ By default, this does not affect elements in array and tuple types. You can change this by passing `{recurseIntoArrays: true}` as the second type argument:
44
44
 
45
45
  ```
46
46
  import type {PartialDeep} from 'type-fest';
@@ -49,13 +49,11 @@ interface Settings {
49
49
  languages: string[];
50
50
  }
51
51
 
52
- const partialSettings: PartialDeep<Settings> = {
52
+ const partialSettings: PartialDeep<Settings, {recurseIntoArrays: true}> = {
53
53
  languages: [undefined]
54
54
  };
55
55
  ```
56
56
 
57
- If this is undesirable, you can pass `{recurseIntoArrays: false}` as the second type argument.
58
-
59
57
  @category Object
60
58
  @category Array
61
59
  @category Set
@@ -64,46 +62,46 @@ If this is undesirable, you can pass `{recurseIntoArrays: false}` as the second
64
62
  export type PartialDeep<T, Options extends PartialDeepOptions = {}> = T extends BuiltIns
65
63
  ? T
66
64
  : T extends Map<infer KeyType, infer ValueType>
67
- ? PartialMapDeep<KeyType, ValueType, Options>
68
- : T extends Set<infer ItemType>
69
- ? PartialSetDeep<ItemType, Options>
70
- : T extends ReadonlyMap<infer KeyType, infer ValueType>
71
- ? PartialReadonlyMapDeep<KeyType, ValueType, Options>
72
- : T extends ReadonlySet<infer ItemType>
73
- ? PartialReadonlySetDeep<ItemType, Options>
74
- : T extends ((...arguments: any[]) => unknown)
75
- ? T | undefined
76
- : T extends object
77
- ? T extends ReadonlyArray<infer ItemType> // Test for arrays/tuples, per https://github.com/microsoft/TypeScript/issues/35156
78
- ? Options['recurseIntoArrays'] extends false // If they opt out of array testing, just use the original type
79
- ? T
80
- : ItemType[] extends T // Test for arrays (non-tuples) specifically
81
- ? readonly ItemType[] extends T // Differentiate readonly and mutable arrays
82
- ? ReadonlyArray<PartialDeep<ItemType | undefined, Options>>
83
- : Array<PartialDeep<ItemType | undefined, Options>>
84
- : PartialObjectDeep<T, Options> // Tuples behave properly
85
- : PartialObjectDeep<T, Options>
86
- : unknown;
65
+ ? PartialMapDeep<KeyType, ValueType, Options>
66
+ : T extends Set<infer ItemType>
67
+ ? PartialSetDeep<ItemType, Options>
68
+ : T extends ReadonlyMap<infer KeyType, infer ValueType>
69
+ ? PartialReadonlyMapDeep<KeyType, ValueType, Options>
70
+ : T extends ReadonlySet<infer ItemType>
71
+ ? PartialReadonlySetDeep<ItemType, Options>
72
+ : T extends ((...arguments: any[]) => unknown)
73
+ ? T | undefined
74
+ : T extends object
75
+ ? T extends ReadonlyArray<infer ItemType> // Test for arrays/tuples, per https://github.com/microsoft/TypeScript/issues/35156
76
+ ? Options['recurseIntoArrays'] extends true
77
+ ? ItemType[] extends T // Test for arrays (non-tuples) specifically
78
+ ? readonly ItemType[] extends T // Differentiate readonly and mutable arrays
79
+ ? ReadonlyArray<PartialDeep<ItemType | undefined, Options>>
80
+ : Array<PartialDeep<ItemType | undefined, Options>>
81
+ : PartialObjectDeep<T, Options> // Tuples behave properly
82
+ : T // If they don't opt into array testing, just use the original type
83
+ : PartialObjectDeep<T, Options>
84
+ : unknown;
87
85
 
88
86
  /**
89
87
  Same as `PartialDeep`, but accepts only `Map`s and as inputs. Internal helper for `PartialDeep`.
90
88
  */
91
- interface PartialMapDeep<KeyType, ValueType, Options extends PartialDeepOptions> extends Map<PartialDeep<KeyType, Options>, PartialDeep<ValueType, Options>> {}
89
+ type PartialMapDeep<KeyType, ValueType, Options extends PartialDeepOptions> = {} & Map<PartialDeep<KeyType, Options>, PartialDeep<ValueType, Options>>;
92
90
 
93
91
  /**
94
92
  Same as `PartialDeep`, but accepts only `Set`s as inputs. Internal helper for `PartialDeep`.
95
93
  */
96
- interface PartialSetDeep<T, Options extends PartialDeepOptions> extends Set<PartialDeep<T, Options>> {}
94
+ type PartialSetDeep<T, Options extends PartialDeepOptions> = {} & Set<PartialDeep<T, Options>>;
97
95
 
98
96
  /**
99
97
  Same as `PartialDeep`, but accepts only `ReadonlyMap`s as inputs. Internal helper for `PartialDeep`.
100
98
  */
101
- interface PartialReadonlyMapDeep<KeyType, ValueType, Options extends PartialDeepOptions> extends ReadonlyMap<PartialDeep<KeyType, Options>, PartialDeep<ValueType, Options>> {}
99
+ type PartialReadonlyMapDeep<KeyType, ValueType, Options extends PartialDeepOptions> = {} & ReadonlyMap<PartialDeep<KeyType, Options>, PartialDeep<ValueType, Options>>;
102
100
 
103
101
  /**
104
102
  Same as `PartialDeep`, but accepts only `ReadonlySet`s as inputs. Internal helper for `PartialDeep`.
105
103
  */
106
- interface PartialReadonlySetDeep<T, Options extends PartialDeepOptions> extends ReadonlySet<PartialDeep<T, Options>> {}
104
+ type PartialReadonlySetDeep<T, Options extends PartialDeepOptions> = {} & ReadonlySet<PartialDeep<T, Options>>;
107
105
 
108
106
  /**
109
107
  Same as `PartialDeep`, but accepts only `object`s as inputs. Internal helper for `PartialDeep`.
@@ -4,14 +4,14 @@ import type {Merge} from './merge';
4
4
  /**
5
5
  @see PartialOnUndefinedDeep
6
6
  */
7
- export interface PartialOnUndefinedDeepOptions {
7
+ export type PartialOnUndefinedDeepOptions = {
8
8
  /**
9
9
  Whether to affect the individual elements of arrays and tuples.
10
10
 
11
11
  @default false
12
12
  */
13
13
  readonly recurseIntoArrays?: boolean;
14
- }
14
+ };
15
15
 
16
16
  /**
17
17
  Create a deep version of another type where all keys accepting `undefined` type are set to optional.
@@ -58,13 +58,13 @@ Utility type to get the value type by key and recursively call `PartialOnUndefin
58
58
  type PartialOnUndefinedDeepValue<T, Options extends PartialOnUndefinedDeepOptions> = T extends BuiltIns | ((...arguments: any[]) => unknown)
59
59
  ? T
60
60
  : T extends ReadonlyArray<infer U> // Test if type is array or tuple
61
- ? Options['recurseIntoArrays'] extends true // Check if option is activated
62
- ? U[] extends T // Check if array not tuple
63
- ? readonly U[] extends T
64
- ? ReadonlyArray<PartialOnUndefinedDeep<U, Options>> // Readonly array treatment
65
- : Array<PartialOnUndefinedDeep<U, Options>> // Mutable array treatment
66
- : PartialOnUndefinedDeep<{[Key in keyof T]: PartialOnUndefinedDeep<T[Key], Options>}, Options> // Tuple treatment
67
- : T
68
- : T extends Record<any, any> | undefined
69
- ? PartialOnUndefinedDeep<T, Options>
70
- : unknown;
61
+ ? Options['recurseIntoArrays'] extends true // Check if option is activated
62
+ ? U[] extends T // Check if array not tuple
63
+ ? readonly U[] extends T
64
+ ? ReadonlyArray<PartialOnUndefinedDeep<U, Options>> // Readonly array treatment
65
+ : Array<PartialOnUndefinedDeep<U, Options>> // Mutable array treatment
66
+ : PartialOnUndefinedDeep<{[Key in keyof T]: PartialOnUndefinedDeep<T[Key], Options>}, Options> // Tuple treatment
67
+ : T
68
+ : T extends Record<any, any> | undefined
69
+ ? PartialOnUndefinedDeep<T, Options>
70
+ : unknown;
@@ -47,8 +47,8 @@ const result: PascalCasedPropertiesDeep<UserWithFriends> = {
47
47
  export type PascalCasedPropertiesDeep<Value> = Value extends Function | Date | RegExp
48
48
  ? Value
49
49
  : Value extends Array<infer U>
50
- ? Array<PascalCasedPropertiesDeep<U>>
51
- : Value extends Set<infer U>
52
- ? Set<PascalCasedPropertiesDeep<U>> : {
53
- [K in keyof Value as PascalCase<K>]: PascalCasedPropertiesDeep<Value[K]>;
54
- };
50
+ ? Array<PascalCasedPropertiesDeep<U>>
51
+ : Value extends Set<infer U>
52
+ ? Set<PascalCasedPropertiesDeep<U>> : {
53
+ [K in keyof Value as PascalCase<K>]: PascalCasedPropertiesDeep<Value[K]>;
54
+ };
@@ -30,5 +30,5 @@ const result: PascalCasedProperties<User> = {
30
30
  export type PascalCasedProperties<Value> = Value extends Function
31
31
  ? Value
32
32
  : Value extends Array<infer U>
33
- ? Value
34
- : {[K in keyof Value as PascalCase<K>]: Value[K]};
33
+ ? Value
34
+ : {[K in keyof Value as PascalCase<K>]: Value[K]};
@@ -0,0 +1,102 @@
1
+ /**
2
+ Pick only index signatures from the given object type, leaving out all explicitly defined properties.
3
+
4
+ This is the counterpart of `OmitIndexSignature`.
5
+
6
+ When you use a type that will iterate through an object that has indexed keys and explicitly defined keys you end up with a type where only the indexed keys are kept. This is because `keyof` of an indexed type always returns `string | number | symbol`, because every key is possible in that object. With this type, you can save the indexed keys and reinject them later, like in the second example below.
7
+
8
+ @example
9
+ ```
10
+ import type {PickIndexSignature} from 'type-fest';
11
+
12
+ declare const symbolKey: unique symbol;
13
+
14
+ type Example = {
15
+ // These index signatures will remain.
16
+ [x: string]: unknown;
17
+ [x: number]: unknown;
18
+ [x: symbol]: unknown;
19
+ [x: `head-${string}`]: string;
20
+ [x: `${string}-tail`]: string;
21
+ [x: `head-${string}-tail`]: string;
22
+ [x: `${bigint}`]: string;
23
+ [x: `embedded-${number}`]: string;
24
+
25
+ // These explicitly defined keys will be removed.
26
+ ['snake-case-key']: string;
27
+ [symbolKey]: string;
28
+ foo: 'bar';
29
+ qux?: 'baz';
30
+ };
31
+
32
+ type ExampleIndexSignature = PickIndexSignature<Example>;
33
+ // {
34
+ // [x: string]: unknown;
35
+ // [x: number]: unknown;
36
+ // [x: symbol]: unknown;
37
+ // [x: `head-${string}`]: string;
38
+ // [x: `${string}-tail`]: string;
39
+ // [x: `head-${string}-tail`]: string;
40
+ // [x: `${bigint}`]: string;
41
+ // [x: `embedded-${number}`]: string;
42
+ // }
43
+ ```
44
+
45
+ @example
46
+ ```
47
+ import type {OmitIndexSignature, PickIndexSignature, Simplify} from 'type-fest';
48
+
49
+ type Foo = {
50
+ [x: string]: string;
51
+ foo: string;
52
+ bar: number;
53
+ };
54
+
55
+ // Imagine that you want a new type `Bar` that comes from `Foo`.
56
+ // => {
57
+ // [x: string]: string;
58
+ // bar: number;
59
+ // };
60
+
61
+ type Bar = Omit<Foo, 'foo'>;
62
+ // This is not working because `Omit` returns only indexed keys.
63
+ // => {
64
+ // [x: string]: string;
65
+ // [x: number]: string;
66
+ // }
67
+
68
+ // One solution is to save the indexed signatures to new type.
69
+ type FooIndexSignature = PickIndexSignature<Foo>;
70
+ // => {
71
+ // [x: string]: string;
72
+ // }
73
+
74
+ // Get a new type without index signatures.
75
+ type FooWithoutIndexSignature = OmitIndexSignature<Foo>;
76
+ // => {
77
+ // foo: string;
78
+ // bar: number;
79
+ // }
80
+
81
+ // At this point we can use Omit to get our new type.
82
+ type BarWithoutIndexSignature = Omit<FooWithoutIndexSignature, 'foo'>;
83
+ // => {
84
+ // bar: number;
85
+ // }
86
+
87
+ // And finally we can merge back the indexed signatures.
88
+ type BarWithIndexSignature = Simplify<BarWithoutIndexSignature & FooIndexSignature>;
89
+ // => {
90
+ // [x: string]: string;
91
+ // bar: number;
92
+ // }
93
+ ```
94
+
95
+ @see OmitIndexSignature
96
+ @category Object
97
+ */
98
+ export type PickIndexSignature<ObjectType> = {
99
+ [KeyType in keyof ObjectType as {} extends Record<KeyType, unknown>
100
+ ? KeyType
101
+ : never]: ObjectType[KeyType];
102
+ };