type-fest 2.10.0 → 2.11.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.11.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>;
@@ -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
+ };