type-fest 4.29.0 → 4.30.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
@@ -128,6 +128,7 @@ export type {ArraySplice} from './source/array-splice';
128
128
  export type {ArrayTail} from './source/array-tail';
129
129
  export type {SetFieldType} from './source/set-field-type';
130
130
  export type {Paths} from './source/paths';
131
+ export type {SharedUnionFields} from './source/shared-union-fields';
131
132
  export type {SharedUnionFieldsDeep} from './source/shared-union-fields-deep';
132
133
  export type {IsNull} from './source/is-null';
133
134
  export type {IfNull} from './source/if-null';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "type-fest",
3
- "version": "4.29.0",
3
+ "version": "4.30.0",
4
4
  "description": "A collection of essential TypeScript types",
5
5
  "license": "(MIT OR CC0-1.0)",
6
6
  "repository": "sindresorhus/type-fest",
@@ -44,7 +44,7 @@
44
44
  "expect-type": "^1.1.0",
45
45
  "npm-run-all2": "^7.0.1",
46
46
  "tsd": "^0.31.2",
47
- "typescript": "~5.6.3",
47
+ "typescript": "~5.7.2",
48
48
  "xo": "^0.59.3"
49
49
  },
50
50
  "xo": {
package/readme.md CHANGED
@@ -201,6 +201,7 @@ Click the type names for complete docs.
201
201
  - [`ArrayTail`](source/array-tail.d.ts) - Extracts the type of an array or tuple minus the first element.
202
202
  - [`SetFieldType`](source/set-field-type.d.ts) - Create a type that changes the type of the given keys.
203
203
  - [`Paths`](source/paths.d.ts) - Generate a union of all possible paths to properties in the given object.
204
+ - [`SharedUnionFields`](source/shared-union-fields.d.ts) - Create a type with shared fields from a union of object types.
204
205
  - [`SharedUnionFieldsDeep`](source/shared-union-fields-deep.d.ts) - Create a type with shared fields from a union of object types, deeply traversing nested structures.
205
206
  - [`DistributedOmit`](source/distributed-omit.d.ts) - Omits keys from a type, distributing the operation over a union.
206
207
  - [`DistributedPick`](source/distributed-pick.d.ts) - Picks keys from a type, distributing the operation over a union.
@@ -22,4 +22,8 @@ add3(4);
22
22
 
23
23
  @category Array
24
24
  */
25
- export type ArrayTail<TArray extends UnknownArrayOrTuple> = TArray extends readonly [unknown, ...infer Tail] ? Tail : [];
25
+ export type ArrayTail<TArray extends UnknownArrayOrTuple> = TArray extends readonly [unknown?, ...infer Tail]
26
+ ? keyof TArray & `${number}` extends never
27
+ ? []
28
+ : Tail
29
+ : [];
@@ -1,3 +1,7 @@
1
+ // Can eventually be replaced with the built-in once this library supports
2
+ // TS5.4+ only. Tracked in https://github.com/sindresorhus/type-fest/issues/848
3
+ type NoInfer<T> = T extends infer U ? U : never;
4
+
1
5
  /**
2
6
  Returns a boolean for whether the given type is `any`.
3
7
 
@@ -26,4 +30,4 @@ const anyA = get(anyObject, 'a');
26
30
  @category Type Guard
27
31
  @category Utilities
28
32
  */
29
- export type IsAny<T> = 0 extends 1 & T ? true : false;
33
+ export type IsAny<T> = 0 extends 1 & NoInfer<T> ? true : false;
@@ -48,13 +48,13 @@ type Dog = {
48
48
  function displayPetInfo(petInfo: (Cat | Dog)['info']) {
49
49
  // typeof petInfo =>
50
50
  // {
51
- // name: string;
52
- // type: 'cat';
53
- // catType: string; // Needn't care about this field, because it's not a common pet info field.
51
+ // name: string;
52
+ // type: 'cat';
53
+ // catType: string; // Needn't care about this field, because it's not a common pet info field.
54
54
  // } | {
55
- // name: string;
56
- // type: 'dog';
57
- // dogType: string; // Needn't care about this field, because it's not a common pet info field.
55
+ // name: string;
56
+ // type: 'dog';
57
+ // dogType: string; // Needn't care about this field, because it's not a common pet info field.
58
58
  // }
59
59
 
60
60
  // petInfo type is complex and have some needless fields
@@ -66,8 +66,8 @@ function displayPetInfo(petInfo: (Cat | Dog)['info']) {
66
66
  function displayPetInfo(petInfo: SharedUnionFieldsDeep<Cat | Dog>['info']) {
67
67
  // typeof petInfo =>
68
68
  // {
69
- // name: string;
70
- // type: 'cat' | 'dog';
69
+ // name: string;
70
+ // type: 'cat' | 'dog';
71
71
  // }
72
72
 
73
73
  // petInfo type is simple and clear
@@ -77,6 +77,8 @@ function displayPetInfo(petInfo: SharedUnionFieldsDeep<Cat | Dog>['info']) {
77
77
  }
78
78
  ```
79
79
 
80
+ @see SharedUnionFields
81
+
80
82
  @category Object
81
83
  @category Union
82
84
  */
@@ -0,0 +1,83 @@
1
+ import type {NonRecursiveType, IsUnion} from './internal';
2
+ import type {IsNever} from './is-never';
3
+ import type {UnknownArray} from './unknown-array';
4
+
5
+ /**
6
+ Create a type with shared fields from a union of object types.
7
+
8
+ Use-cases:
9
+ - You want a safe object type where each key exists in the union object.
10
+ - You want to focus on the common fields of the union type and don't want to have to care about the other fields.
11
+
12
+ @example
13
+ ```
14
+ import type {SharedUnionFields} from 'type-fest';
15
+
16
+ type Cat = {
17
+ name: string;
18
+ type: 'cat';
19
+ catType: string;
20
+ };
21
+
22
+ type Dog = {
23
+ name: string;
24
+ type: 'dog';
25
+ dogType: string;
26
+ };
27
+
28
+ function displayPetInfo(petInfo: Cat | Dog) {
29
+ // typeof petInfo =>
30
+ // {
31
+ // name: string;
32
+ // type: 'cat';
33
+ // catType: string; // Needn't care about this field, because it's not a common pet info field.
34
+ // } | {
35
+ // name: string;
36
+ // type: 'dog';
37
+ // dogType: string; // Needn't care about this field, because it's not a common pet info field.
38
+ // }
39
+
40
+ // petInfo type is complex and have some needless fields
41
+
42
+ console.log('name: ', petInfo.name);
43
+ console.log('type: ', petInfo.type);
44
+ }
45
+
46
+ function displayPetInfo(petInfo: SharedUnionFields<Cat | Dog>) {
47
+ // typeof petInfo =>
48
+ // {
49
+ // name: string;
50
+ // type: 'cat' | 'dog';
51
+ // }
52
+
53
+ // petInfo type is simple and clear
54
+
55
+ console.log('name: ', petInfo.name);
56
+ console.log('type: ', petInfo.type);
57
+ }
58
+ ```
59
+
60
+ @see SharedUnionFieldsDeep
61
+
62
+ @category Object
63
+ @category Union
64
+ */
65
+ export type SharedUnionFields<Union> =
66
+ // If `Union` is not a union type, return `Union` directly.
67
+ IsUnion<Union> extends false
68
+ ? Union
69
+ // `Union extends` will convert `Union`
70
+ // to a [distributive conditionaltype](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#distributive-conditional-types).
71
+ // But this is not what we want, so we need to wrap `Union` with `[]` to prevent it.
72
+ : [Union] extends [NonRecursiveType | ReadonlyMap<unknown, unknown> | ReadonlySet<unknown> | UnknownArray]
73
+ ? Union
74
+ : [Union] extends [object]
75
+ // `keyof Union` can extract the same key in union type, if there is no same key, return never.
76
+ ? keyof Union extends infer Keys
77
+ ? IsNever<Keys> extends false
78
+ ? {
79
+ [Key in keyof Union]: Union[Key]
80
+ }
81
+ : {}
82
+ : Union
83
+ : Union;