type-fest 2.10.0 → 2.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.d.ts CHANGED
@@ -18,6 +18,7 @@ export {ReadonlyDeep} from './source/readonly-deep';
18
18
  export {LiteralUnion} from './source/literal-union';
19
19
  export {Promisable} from './source/promisable';
20
20
  export {Opaque} from './source/opaque';
21
+ export {InvariantOf} from './source/invariant-of';
21
22
  export {SetOptional} from './source/set-optional';
22
23
  export {SetRequired} from './source/set-required';
23
24
  export {ValueOf} from './source/value-of';
@@ -38,6 +39,7 @@ export {SetReturnType} from './source/set-return-type';
38
39
  export {Asyncify} from './source/asyncify';
39
40
  export {Simplify} from './source/simplify';
40
41
  export {Jsonify} from './source/jsonify';
42
+ export {Schema} from './source/schema';
41
43
  export {LiteralToPrimitive} from './source/literal-to-primitive';
42
44
  export {
43
45
  PositiveInfinity,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "type-fest",
3
- "version": "2.10.0",
3
+ "version": "2.12.0",
4
4
  "description": "A collection of essential TypeScript types",
5
5
  "license": "(MIT OR CC0-1.0)",
6
6
  "repository": "sindresorhus/type-fest",
package/readme.md CHANGED
@@ -104,6 +104,7 @@ Click the type names for complete docs.
104
104
  - [`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.
105
105
  - [`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).
106
106
  - [`Opaque`](source/opaque.d.ts) - Create an [opaque type](https://codemix.com/opaque-types-in-javascript/).
107
+ - [`InvariantOf`](source/invariant-of.d.ts) - Create an [invariant type](https://basarat.gitbook.io/typescript/type-system/type-compatibility#footnote-invariance), which is a type that does not accept supertypes and subtypes.
107
108
  - [`SetOptional`](source/set-optional.d.ts) - Create a type that makes the given keys optional.
108
109
  - [`SetRequired`](source/set-required.d.ts) - Create a type that makes the given keys required.
109
110
  - [`ValueOf`](source/value-of.d.ts) - Create a union of the given object's values, and optionally specify which keys to get the values from.
@@ -120,6 +121,7 @@ Click the type names for complete docs.
120
121
  - [`Simplify`](source/simplify.d.ts) - Useful to flatten the type output to improve type hints shown in editors. And also to transform an interface into a type to aide with assignability.
121
122
  - [`Get`](source/get.d.ts) - Get a deeply-nested property from an object using a key path, like [Lodash's `.get()`](https://lodash.com/docs/latest#get) function.
122
123
  - [`StringKeyOf`](source/string-key-of.d.ts) - Get keys of the given type as strings.
124
+ - [`Schema`](source/schema.d.ts) - Create a deep version of another object type where property values are recursively replaced into a given value type.
123
125
 
124
126
  ### JSON
125
127
 
@@ -196,12 +198,14 @@ Click the type names for complete docs.
196
198
  - [`Url2Json`](https://github.com/sindresorhus/type-fest/pull/262) - Inferring search parameters from a URL string is a cute idea, but not very useful in practice, since search parameters are usually dynamic and defined separately.
197
199
  - [`Nullish`](https://github.com/sindresorhus/type-fest/pull/318) - The type only saves a couple of characters, not everyone knows what "nullish" means, and I'm also trying to [get away from `null`](https://github.com/sindresorhus/meta/discussions/7).
198
200
  - [`TitleCase`](https://github.com/sindresorhus/type-fest/pull/303) - It's not solving a common need and is a better fit for a separate package.
201
+ - [`ExtendOr` and `ExtendAnd`](https://github.com/sindresorhus/type-fest/pull/247) - The benefits don't outweigh having to learn what they mean.
199
202
 
200
203
  ## Alternative type names
201
204
 
202
205
  *If you know one of our types by a different name, add it here for discovery.*
203
206
 
204
207
  - `PartialBy` - See [`SetOptional`](https://github.com/sindresorhus/type-fest/blob/main/source/set-optional.d.ts)
208
+ - `RecordDeep`- See [`Schema`](https://github.com/sindresorhus/type-fest/blob/main/source/schema.d.ts)
205
209
 
206
210
  ## Tips
207
211
 
package/source/get.d.ts CHANGED
@@ -12,7 +12,7 @@ Like the `Get` type but receives an array of strings as a path parameter.
12
12
  type GetWithPath<BaseType, Keys extends readonly string[], Options extends GetOptions = {}> =
13
13
  Keys extends []
14
14
  ? BaseType
15
- : Keys extends [infer Head, ...infer Tail]
15
+ : Keys extends readonly [infer Head, ...infer Tail]
16
16
  ? GetWithPath<
17
17
  PropertyOf<BaseType, Extract<Head, string>, Options>,
18
18
  Extract<Tail, string[]>,
@@ -139,7 +139,7 @@ Use-case: Retrieve a property from deep inside an API response or some other com
139
139
  import {Get} from 'type-fest';
140
140
  import * as lodash from 'lodash';
141
141
 
142
- const get = <BaseType, Path extends string | string[]>(object: BaseType, path: Path): Get<BaseType, Path> =>
142
+ const get = <BaseType, Path extends string | readonly string[]>(object: BaseType, path: Path): Get<BaseType, Path> =>
143
143
  lodash.get(object, path);
144
144
 
145
145
  interface ApiResponse {
@@ -161,9 +161,9 @@ const getName = (apiResponse: ApiResponse) =>
161
161
  get(apiResponse, 'hits.hits[0]._source.name');
162
162
  //=> Array<{given: string[]; family: string}>
163
163
 
164
- // Path also supports an array of strings
164
+ // Path also supports a readonly array of strings
165
165
  const getNameWithPathArray = (apiResponse: ApiResponse) =>
166
- get(apiResponse, ['hits','hits', '0', '_source', 'name']);
166
+ get(apiResponse, ['hits','hits', '0', '_source', 'name'] as const);
167
167
  //=> Array<{given: string[]; family: string}>
168
168
 
169
169
  // Strict mode:
@@ -175,5 +175,5 @@ Get<Record<string, string>, 'foo', {strict: true}> // => string | undefined
175
175
  @category Array
176
176
  @category Template literal
177
177
  */
178
- export type Get<BaseType, Path extends string | string[], Options extends GetOptions = {}> =
178
+ export type Get<BaseType, Path extends string | readonly string[], Options extends GetOptions = {}> =
179
179
  GetWithPath<BaseType, Path extends string ? ToPath<Path> : Path, Options>;
@@ -0,0 +1,72 @@
1
+ import {Opaque} from './opaque';
2
+
3
+ /**
4
+ Create an [invariant type](https://basarat.gitbook.io/typescript/type-system/type-compatibility#footnote-invariance), which is a type that does not accept supertypes and subtypes.
5
+
6
+ Use-case:
7
+ - Prevent runtime errors that may occur due to assigning subtypes to supertypes.
8
+ - Improve type signature of object methods like [`Object.keys()` or `Object.entries()`](https://github.com/microsoft/TypeScript/pull/12253#issuecomment-263132208) by sealing the object type.
9
+
10
+ @example
11
+ ```
12
+ class Animal {
13
+ constructor(public name: string){}
14
+ }
15
+
16
+ class Cat extends Animal {
17
+ meow() {}
18
+ }
19
+
20
+ let animalArray: Animal[] = [animal];
21
+ let catArray: Cat[] = [cat];
22
+
23
+ animalArray = catArray; // Okay if covariant
24
+ animalArray.push(new Animal('another animal')); // Pushed an animal into catArray
25
+ catArray.forEach(c => c.meow()); // Allowed but, error at runtime
26
+
27
+ let invariantAnimalArray: InvariantOf<Animal>[] = [animal] as InvariantOf<Animal>[];
28
+ let invariantCatArray: InvariantOf<Cat>[] = [cat] as InvariantOf<Cat>[];
29
+
30
+ invariantAnimalArray = invariantCatArray; // Error: Type 'InvariantOf<Cat>[]' is not assignable to type 'InvariantOf<Animal>[]'.
31
+ ```
32
+
33
+ @example
34
+ ```
35
+ // In covariance (default)
36
+
37
+ interface FooBar {
38
+ foo: number;
39
+ bar: string
40
+ }
41
+
42
+ interface FooBarBaz extends FooBar {
43
+ baz: boolean
44
+ }
45
+
46
+ declare const fooBar: FooBar
47
+ declare const fooBarBaz: FooBarBaz
48
+
49
+ function keyOfFooBar(fooBar: FooBar) {
50
+ return Object.keys(fooBar) as (keyof FooBar)[]
51
+ }
52
+
53
+ keyOfFooBar(fooBar) //=> (keyof FooBar)[]
54
+ keyOfFooBar(fooBarBaz) //=> (keyof FooBar)[] but, (keyof FooBarBaz)[] at runtime
55
+
56
+ // In invariance
57
+
58
+ export function invariantOf<Type>(value: Type): InvariantOf<Type> {
59
+ return value as InvariantOf<Type>;
60
+ }
61
+
62
+ function keyOfInvariantFooBar(fooBar: InvariantOf<FooBar>) {
63
+ return Object.keys(fooBar) as (keyof FooBar)[]
64
+ }
65
+
66
+ keyOfInvariantFooBar(invariantOf(fooBar)); // (keyof FooBar)[]
67
+ keyOfInvariantFooBar(invariantOf(fooBarBaz)); // Error: Argument of type 'InvariantOf<FooBarBaz>' is not assignable to parameter of type 'InvariantOf<FooBar>'.
68
+ ```
69
+
70
+ @category Type
71
+ */
72
+ export type InvariantOf<Type> = Opaque<Type, (argument: Type) => Type>;
@@ -214,6 +214,7 @@ declare namespace PackageJson {
214
214
  | 'import'
215
215
  | 'require'
216
216
  | 'node'
217
+ | 'node-addons'
217
218
  | 'deno'
218
219
  | 'browser'
219
220
  | 'electron'
@@ -231,6 +232,13 @@ declare namespace PackageJson {
231
232
  | {[key in ExportCondition]: Exports}
232
233
  | {[key: string]: Exports}; // eslint-disable-line @typescript-eslint/consistent-indexed-object-style
233
234
 
235
+ /**
236
+ Import map entries of a module, optionally with conditions.
237
+ */
238
+ export type Imports = { // eslint-disable-line @typescript-eslint/consistent-indexed-object-style
239
+ [key: string]: string | {[key in ExportCondition]: Exports};
240
+ };
241
+
234
242
  export interface NonStandardEntryPoints {
235
243
  /**
236
244
  An ECMAScript module ID that is the primary entry point to the program.
@@ -415,12 +423,19 @@ declare namespace PackageJson {
415
423
  main?: string;
416
424
 
417
425
  /**
418
- Standard entry points of the package, with enhanced support for ECMAScript Modules.
426
+ Subpath exports to define entry points of the package.
419
427
 
420
- [Read more.](https://nodejs.org/api/esm.html#esm_package_entry_points)
428
+ [Read more.](https://nodejs.org/api/packages.html#subpath-exports)
421
429
  */
422
430
  exports?: Exports;
423
431
 
432
+ /**
433
+ Subpath imports to define internal package import maps that only apply to import specifiers from within the package itself.
434
+
435
+ [Read more.](https://nodejs.org/api/packages.html#subpath-imports)
436
+ */
437
+ imports?: Imports;
438
+
424
439
  /**
425
440
  The executable files that should be installed into the `PATH`.
426
441
  */
@@ -34,11 +34,17 @@ data.foo.push('bar');
34
34
  @category Set
35
35
  @category Map
36
36
  */
37
- export type ReadonlyDeep<T> = T extends BuiltIns | ((...arguments: any[]) => unknown)
37
+ export type ReadonlyDeep<T> = T extends BuiltIns
38
38
  ? T
39
- : T extends ReadonlyMap<infer KeyType, infer ValueType>
39
+ : T extends (...arguments: any[]) => unknown
40
+ ? {} extends ReadonlyObjectDeep<T>
41
+ ? T
42
+ : HasMultipleCallSignatures<T> extends true
43
+ ? T
44
+ : ((...arguments: Parameters<T>) => ReturnType<T>) & ReadonlyObjectDeep<T>
45
+ : T extends Readonly<ReadonlyMap<infer KeyType, infer ValueType>>
40
46
  ? ReadonlyMapDeep<KeyType, ValueType>
41
- : T extends ReadonlySet<infer ItemType>
47
+ : T extends Readonly<ReadonlySet<infer ItemType>>
42
48
  ? ReadonlySetDeep<ItemType>
43
49
  : T extends object
44
50
  ? ReadonlyObjectDeep<T>
@@ -48,13 +54,13 @@ export type ReadonlyDeep<T> = T extends BuiltIns | ((...arguments: any[]) => unk
48
54
  Same as `ReadonlyDeep`, but accepts only `ReadonlyMap`s as inputs. Internal helper for `ReadonlyDeep`.
49
55
  */
50
56
  interface ReadonlyMapDeep<KeyType, ValueType>
51
- extends ReadonlyMap<ReadonlyDeep<KeyType>, ReadonlyDeep<ValueType>> {}
57
+ extends Readonly<ReadonlyMap<ReadonlyDeep<KeyType>, ReadonlyDeep<ValueType>>> {}
52
58
 
53
59
  /**
54
60
  Same as `ReadonlyDeep`, but accepts only `ReadonlySet`s as inputs. Internal helper for `ReadonlyDeep`.
55
61
  */
56
62
  interface ReadonlySetDeep<ItemType>
57
- extends ReadonlySet<ReadonlyDeep<ItemType>> {}
63
+ extends Readonly<ReadonlySet<ReadonlyDeep<ItemType>>> {}
58
64
 
59
65
  /**
60
66
  Same as `ReadonlyDeep`, but accepts only `object`s as inputs. Internal helper for `ReadonlyDeep`.
@@ -62,3 +68,18 @@ Same as `ReadonlyDeep`, but accepts only `object`s as inputs. Internal helper fo
62
68
  type ReadonlyObjectDeep<ObjectType extends object> = {
63
69
  readonly [KeyType in keyof ObjectType]: ReadonlyDeep<ObjectType[KeyType]>
64
70
  };
71
+
72
+ /**
73
+ Test if the given function has multiple call signatures.
74
+
75
+ Needed to handle the case of a single call signature with properties.
76
+
77
+ Multiple call signatures cannot currently be supported due to a TypeScript limitation.
78
+ @see https://github.com/microsoft/TypeScript/issues/29732
79
+ */
80
+ type HasMultipleCallSignatures<T extends (...arguments: any[]) => unknown> =
81
+ T extends {(...arguments: infer A): unknown; (...arguments: any[]): unknown}
82
+ ? unknown[] extends A
83
+ ? false
84
+ : true
85
+ : false;
@@ -0,0 +1,72 @@
1
+ /**
2
+ Create a deep version of another object type where property values are recursively replaced into a given value type.
3
+
4
+ Use-cases:
5
+ - Form validation: Define how each field should be validated.
6
+ - Form settings: Define configuration for input fields.
7
+ - Parsing: Define types that specify special behavior for specific fields.
8
+
9
+ @example
10
+ ```
11
+ import {Schema} from 'type-fest';
12
+
13
+ interface User {
14
+ id: string;
15
+ name: {
16
+ firstname: string;
17
+ lastname: string;
18
+ };
19
+ created: Date;
20
+ active: boolean;
21
+ passwordHash: string;
22
+ }
23
+
24
+ type UserMask = Schema<User, 'mask' | 'hide' | 'show'>;
25
+
26
+ const userMaskSettings: UserMask = {
27
+ id: 'show',
28
+ name: {
29
+ firstname: 'show',
30
+ lastname: 'mask',
31
+ },
32
+ phoneNumbers: 'mask',
33
+ created: 'show',
34
+ active: 'show',
35
+ passwordHash: 'hide',
36
+ }
37
+ ```
38
+
39
+ @category Object
40
+ */
41
+ export type Schema<ObjectType, ValueType> = ObjectType extends string
42
+ ? ValueType
43
+ : ObjectType extends Map<unknown, unknown>
44
+ ? ValueType
45
+ : ObjectType extends Set<unknown>
46
+ ? ValueType
47
+ : ObjectType extends ReadonlyMap<unknown, unknown>
48
+ ? ValueType
49
+ : ObjectType extends ReadonlySet<unknown>
50
+ ? ValueType
51
+ : ObjectType extends readonly unknown[]
52
+ ? ValueType
53
+ : ObjectType extends unknown[]
54
+ ? ValueType
55
+ : ObjectType extends (...arguments: unknown[]) => unknown
56
+ ? ValueType
57
+ : ObjectType extends Date
58
+ ? ValueType
59
+ : ObjectType extends Function
60
+ ? ValueType
61
+ : ObjectType extends RegExp
62
+ ? ValueType
63
+ : ObjectType extends object
64
+ ? SchemaObject<ObjectType, ValueType>
65
+ : ValueType;
66
+
67
+ /**
68
+ Same as `Schema`, but accepts only `object`s as inputs. Internal helper for `Schema`.
69
+ */
70
+ type SchemaObject<ObjectType extends object, K> = {
71
+ [KeyType in keyof ObjectType]: Schema<ObjectType[KeyType], K> | K;
72
+ };