type-fest 4.13.0 → 4.14.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
@@ -7,6 +7,7 @@ export * from './source/observable-like';
7
7
  // Utilities
8
8
  export type {KeysOfUnion} from './source/keys-of-union';
9
9
  export type {DistributedOmit} from './source/distributed-omit';
10
+ export type {DistributedPick} from './source/distributed-pick';
10
11
  export type {EmptyObject, IsEmptyObject} from './source/empty-object';
11
12
  export type {NonEmptyObject} from './source/non-empty-object';
12
13
  export type {UnknownRecord} from './source/unknown-record';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "type-fest",
3
- "version": "4.13.0",
3
+ "version": "4.14.0",
4
4
  "description": "A collection of essential TypeScript types",
5
5
  "license": "(MIT OR CC0-1.0)",
6
6
  "repository": "sindresorhus/type-fest",
@@ -16,7 +16,12 @@
16
16
  "node": ">=16"
17
17
  },
18
18
  "scripts": {
19
- "test": "xo && tsd && tsc && node script/test/source-files-extension.js"
19
+ "test:set-parameter-type": "tsc --noEmit test-d/set-parameter-type",
20
+ "test:source-files-extension": "node script/test/source-files-extension.js",
21
+ "test:tsc": "tsc",
22
+ "test:tsd": "tsd",
23
+ "test:xo": "xo",
24
+ "test": "run-p test:*"
20
25
  },
21
26
  "files": [
22
27
  "index.d.ts",
@@ -37,9 +42,10 @@
37
42
  "devDependencies": {
38
43
  "@sindresorhus/tsconfig": "~0.7.0",
39
44
  "expect-type": "^0.15.0",
45
+ "npm-run-all2": "^6.1.2",
40
46
  "tsd": "^0.28.1",
41
47
  "typescript": "^5.2.2",
42
- "xo": "^0.56.0"
48
+ "xo": "^0.58.0"
43
49
  },
44
50
  "xo": {
45
51
  "rules": {
@@ -49,7 +55,14 @@
49
55
  "import/extensions": "off",
50
56
  "@typescript-eslint/no-redeclare": "off",
51
57
  "@typescript-eslint/no-confusing-void-expression": "off",
52
- "@typescript-eslint/no-unsafe-argument": "off"
58
+ "@typescript-eslint/no-unsafe-argument": "off",
59
+ "object-curly-newline": [
60
+ "error",
61
+ {
62
+ "multiline": true,
63
+ "consistent": true
64
+ }
65
+ ]
53
66
  }
54
67
  },
55
68
  "tsd": {
package/readme.md CHANGED
@@ -183,6 +183,7 @@ Click the type names for complete docs.
183
183
  - [`Paths`](source/paths.d.ts) - Generate a union of all possible paths to properties in the given object.
184
184
  - [`SharedUnionFieldsDeep`](source/shared-union-fields-deep.d.ts) - Create a type with shared fields from a union of object types, deeply traversing nested structures.
185
185
  - [`DistributedOmit`](source/distributed-omit.d.ts) - Omits keys from a type, distributing the operation over a union.
186
+ - [`DistributedPick`](source/distributed-pick.d.ts) - Picks keys from a type, distributing the operation over a union.
186
187
 
187
188
  ### Type Guard
188
189
 
@@ -29,4 +29,4 @@ const getFooAsync: AsyncifiedFooGetter = (someArg) => {
29
29
 
30
30
  @category Async
31
31
  */
32
- export type Asyncify<Fn extends (...arguments_: any[]) => any> = SetReturnType<Fn, Promise<Awaited<ReturnType<Fn>>>>;
32
+ export type Asyncify<Function_ extends (...arguments_: any[]) => any> = SetReturnType<Function_, Promise<Awaited<ReturnType<Function_>>>>;
@@ -0,0 +1,85 @@
1
+ import type {KeysOfUnion} from './keys-of-union';
2
+
3
+ /**
4
+ Pick keys from a type, distributing the operation over a union.
5
+
6
+ TypeScript's `Pick` doesn't distribute over unions, leading to the erasure of unique properties from union members when picking keys. This creates a type that only retains properties common to all union members, making it impossible to access member-specific properties after the Pick. Essentially, using `Pick` on a union type merges the types into a less specific one, hindering type narrowing and property access based on discriminants. This type solves that.
7
+
8
+ Example:
9
+
10
+ ```
11
+ type A = {
12
+ discriminant: 'A';
13
+ foo: {
14
+ bar: string;
15
+ };
16
+ };
17
+
18
+ type B = {
19
+ discriminant: 'B';
20
+ foo: {
21
+ baz: string;
22
+ };
23
+ };
24
+
25
+ type Union = A | B;
26
+
27
+ type PickedUnion = Pick<Union, 'discriminant' | 'foo'>;
28
+ //=> {discriminant: 'A' | 'B', foo: {bar: string} | {baz: string}}
29
+
30
+ const pickedUnion: PickedUnion = createPickedUnion();
31
+
32
+ if (pickedUnion.discriminant === 'A') {
33
+ // We would like to narrow `pickedUnion`'s type
34
+ // to `A` here, but we can't because `Pick`
35
+ // doesn't distribute over unions.
36
+
37
+ pickedUnion.foo.bar;
38
+ //=> Error: Property 'bar' does not exist on type '{bar: string} | {baz: string}'.
39
+ }
40
+ ```
41
+
42
+ @example
43
+ ```
44
+ type A = {
45
+ discriminant: 'A';
46
+ foo: {
47
+ bar: string;
48
+ };
49
+ extraneous: boolean;
50
+ };
51
+
52
+ type B = {
53
+ discriminant: 'B';
54
+ foo: {
55
+ baz: string;
56
+ };
57
+ extraneous: boolean;
58
+ };
59
+
60
+ // Notice that `foo.bar` exists in `A` but not in `B`.
61
+
62
+ type Union = A | B;
63
+
64
+ type PickedUnion = DistributedPick<Union, 'discriminant' | 'foo'>;
65
+
66
+ const pickedUnion: PickedUnion = createPickedUnion();
67
+
68
+ if (pickedUnion.discriminant === 'A') {
69
+ pickedUnion.foo.bar;
70
+ //=> OK
71
+
72
+ pickedUnion.extraneous;
73
+ //=> Error: Property `extraneous` does not exist on type `Pick<A, 'discriminant' | 'foo'>`.
74
+
75
+ pickedUnion.foo.baz;
76
+ //=> Error: `bar` is not a property of `{discriminant: 'A'; a: string}`.
77
+ }
78
+ ```
79
+
80
+ @category Object
81
+ */
82
+ export type DistributedPick<ObjectType, KeyType extends KeysOfUnion<ObjectType>> =
83
+ ObjectType extends unknown
84
+ ? Pick<ObjectType, Extract<KeyType, keyof ObjectType>>
85
+ : never;
@@ -98,7 +98,7 @@ export type BuiltIns = Primitive | void | Date | RegExp;
98
98
  /**
99
99
  Matches non-recursive types.
100
100
  */
101
- export type NonRecursiveType = BuiltIns | Function | (new (...args: any[]) => unknown);
101
+ export type NonRecursiveType = BuiltIns | Function | (new (...arguments_: any[]) => unknown);
102
102
 
103
103
  /**
104
104
  Returns a boolean for whether the given type is a plain key-value object.
@@ -38,7 +38,7 @@ Note that types containing overloaded functions are not made deeply readonly due
38
38
  */
39
39
  export type ReadonlyDeep<T> = T extends BuiltIns
40
40
  ? T
41
- : T extends new (...args: any[]) => unknown
41
+ : T extends new (...arguments_: any[]) => unknown
42
42
  ? T // Skip class constructors
43
43
  : T extends (...arguments_: any[]) => unknown
44
44
  ? {} extends ReadonlyObjectDeep<T>
@@ -1,5 +1,5 @@
1
1
  import type {IsUnknown} from './is-unknown';
2
- import type {StaticPartOfArray} from './internal';
2
+ import type {StaticPartOfArray, VariablePartOfArray} from './internal';
3
3
  import type {UnknownArray} from './unknown-array';
4
4
 
5
5
  /**
@@ -32,7 +32,10 @@ type MergeObjectToArray<TArray extends UnknownArray, TObject, TArrayCopy extends
32
32
  ? number extends TObject['length']
33
33
  ? TObject
34
34
  : {
35
- [K in keyof TArray]: K extends keyof TObject ? TObject[K] : TArray[K]
35
+ [K in keyof TArray]:
36
+ number extends K
37
+ ? VariablePartOfArray<TArray>[number]
38
+ : K extends keyof TObject ? TObject[K] : TArray[K]
36
39
  }
37
40
  : TObject extends object
38
41
  // If `TObject` is a object witch key is number like `{0: string, 1: number}`
@@ -101,14 +104,14 @@ type HandleLog2 = SetParameterType<HandleMessage, {2: string}>;
101
104
 
102
105
  @category Function
103
106
  */
104
- export type SetParameterType<Fn extends (...arguments_: any[]) => unknown, P extends Record<number, unknown>> =
107
+ export type SetParameterType<Function_ extends (...arguments_: any[]) => unknown, P extends Record<number, unknown>> =
105
108
  // Just using `Parameters<Fn>` isn't ideal because it doesn't handle the `this` fake parameter.
106
- Fn extends (this: infer ThisArg, ...arguments_: infer Arguments) => unknown
109
+ Function_ extends (this: infer ThisArgument, ...arguments_: infer Arguments) => unknown
107
110
  ? (
108
111
  // If a function did not specify the `this` fake parameter, it will be inferred to `unknown`.
109
112
  // We want to detect this situation just to display a friendlier type upon hovering on an IntelliSense-powered IDE.
110
- IsUnknown<ThisArg> extends true
111
- ? (...arguments_: MergeObjectToArray<Arguments, P>) => ReturnType<Fn>
112
- : (this: ThisArg, ...arguments_: MergeObjectToArray<Arguments, P>) => ReturnType<Fn>
113
+ IsUnknown<ThisArgument> extends true
114
+ ? (...arguments_: MergeObjectToArray<Arguments, P>) => ReturnType<Function_>
115
+ : (this: ThisArgument, ...arguments_: MergeObjectToArray<Arguments, P>) => ReturnType<Function_>
113
116
  )
114
- : Fn; // This part should be unreachable
117
+ : Function_; // This part should be unreachable
@@ -17,13 +17,13 @@ type MyWrappedFunction = SetReturnType<MyFunctionThatCanThrow, SomeOtherType | u
17
17
 
18
18
  @category Function
19
19
  */
20
- export type SetReturnType<Fn extends (...arguments_: any[]) => any, TypeToReturn> =
20
+ export type SetReturnType<Function_ extends (...arguments_: any[]) => any, TypeToReturn> =
21
21
  // Just using `Parameters<Fn>` isn't ideal because it doesn't handle the `this` fake parameter.
22
- Fn extends (this: infer ThisArg, ...arguments_: infer Arguments) => any ? (
22
+ Function_ extends (this: infer ThisArgument, ...arguments_: infer Arguments) => any ? (
23
23
  // If a function did not specify the `this` fake parameter, it will be inferred to `unknown`.
24
24
  // We want to detect this situation just to display a friendlier type upon hovering on an IntelliSense-powered IDE.
25
- IsUnknown<ThisArg> extends true ? (...arguments_: Arguments) => TypeToReturn : (this: ThisArg, ...arguments_: Arguments) => TypeToReturn
25
+ IsUnknown<ThisArgument> extends true ? (...arguments_: Arguments) => TypeToReturn : (this: ThisArgument, ...arguments_: Arguments) => TypeToReturn
26
26
  ) : (
27
27
  // This part should be unreachable, but we make it meaningful just in case…
28
- (...arguments_: Parameters<Fn>) => TypeToReturn
28
+ (...arguments_: Parameters<Function_>) => TypeToReturn
29
29
  );
@@ -68,6 +68,7 @@ declare namespace TsConfigJson {
68
68
  | 'es2022'
69
69
  | 'esnext';
70
70
 
71
+ // eslint-disable-next-line unicorn/prevent-abbreviations
71
72
  export type Lib =
72
73
  | 'ES5'
73
74
  | 'ES6'