type-fest 0.10.0 → 0.13.1

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
@@ -15,6 +15,14 @@ export {Promisable} from './source/promisable';
15
15
  export {Opaque} from './source/opaque';
16
16
  export {SetOptional} from './source/set-optional';
17
17
  export {SetRequired} from './source/set-required';
18
+ export {ValueOf} from './source/value-of';
19
+ export {PromiseValue} from './source/promise-value';
20
+ export {AsyncReturnType} from './source/async-return-type';
21
+ export {ConditionalExcept} from './source/conditional-except';
22
+ export {ConditionalKeys} from './source/conditional-keys';
23
+ export {ConditionalPick} from './source/conditional-pick';
24
+ export {UnionToIntersection} from './source/union-to-intersection';
25
+ export {Stringified} from './source/stringified';
18
26
 
19
27
  // Miscellaneous
20
28
  export {PackageJson} from './source/package-json';
package/license CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
3
+ Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https:/sindresorhus.com)
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
6
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "type-fest",
3
- "version": "0.10.0",
3
+ "version": "0.13.1",
4
4
  "description": "A collection of essential TypeScript types",
5
5
  "license": "(MIT OR CC0-1.0)",
6
6
  "repository": "sindresorhus/type-fest",
@@ -8,10 +8,10 @@
8
8
  "author": {
9
9
  "name": "Sindre Sorhus",
10
10
  "email": "sindresorhus@gmail.com",
11
- "url": "sindresorhus.com"
11
+ "url": "https://sindresorhus.com"
12
12
  },
13
13
  "engines": {
14
- "node": ">=8"
14
+ "node": ">=10"
15
15
  },
16
16
  "scripts": {
17
17
  "test": "xo && tsd"
@@ -32,22 +32,14 @@
32
32
  "json"
33
33
  ],
34
34
  "devDependencies": {
35
- "@sindresorhus/tsconfig": "^0.7.0",
36
- "@typescript-eslint/eslint-plugin": "2.17.0",
37
- "@typescript-eslint/parser": "2.17.0",
38
- "eslint-config-xo-typescript": "^0.24.1",
39
- "tsd": "^0.7.3",
40
- "typescript": "3.7.5",
41
- "xo": "^0.25.3"
35
+ "tsd": "^0.11.0",
36
+ "xo": "^0.28.2"
42
37
  },
38
+ "types": "index.d.ts",
43
39
  "xo": {
44
- "extends": "xo-typescript",
45
- "extensions": [
46
- "ts"
47
- ],
48
40
  "rules": {
49
- "import/no-unresolved": "off",
50
- "@typescript-eslint/indent": "off"
41
+ "@typescript-eslint/indent": "off",
42
+ "func-call-spacing": "off"
51
43
  }
52
44
  }
53
45
  }
package/readme.md CHANGED
@@ -74,6 +74,14 @@ Click the type names for complete docs.
74
74
  - [`Opaque`](source/opaque.d.ts) - Create an [opaque type](https://codemix.com/opaque-types-in-javascript/).
75
75
  - [`SetOptional`](source/set-optional.d.ts) - Create a type that makes the given keys optional.
76
76
  - [`SetRequired`](source/set-required.d.ts) - Create a type that makes the given keys required.
77
+ - [`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.
78
+ - [`PromiseValue`](source/promise-value.d.ts) - Returns the type that is wrapped inside a `Promise`.
79
+ - [`AsyncReturnType`](source/async-return-type.d.ts) - Unwrap the return type of a function that returns a `Promise`.
80
+ - [`ConditionalKeys`](source/conditional-keys.d.ts) - Extract keys from a shape where values extend the given `Condition` type.
81
+ - [`ConditionalPick`](source/conditional-pick.d.ts) - Like `Pick` except it selects properties from a shape where the values extend the given `Condition` type.
82
+ - [`ConditionalExcept`](source/conditional-except.d.ts) - Like `Omit` except it removes properties from a shape where the values extend the given `Condition` type.
83
+ - [`UnionToIntersection`](source/union-to-intersection.d.ts) - Convert a union type to an intersection type.
84
+ - [`Stringified`](source/stringified.d.ts) - Create a type with the keys of the given type changed to `string` type.
77
85
 
78
86
  ### Miscellaneous
79
87
 
@@ -86,6 +94,8 @@ Click the type names for complete docs.
86
94
 
87
95
  - [`Diff` and `Spread`](https://github.com/sindresorhus/type-fest/pull/7) - The PR author didn't provide any real-world use-cases and the PR went stale. If you think this type is useful, provide some real-world use-cases and we might reconsider.
88
96
  - [`Dictionary`](https://github.com/sindresorhus/type-fest/issues/33) - You only save a few characters (`Dictionary<number>` vs `Record<string, number>`) from [`Record`](https://github.com/Microsoft/TypeScript/blob/2961bc3fc0ea1117d4e53bc8e97fa76119bc33e3/src/lib/es5.d.ts#L1429-L1434), which is more flexible and well-known. Also, you shouldn't use an object as a dictionary. We have `Map` in JavaScript now.
97
+ - [`SubType`](https://github.com/sindresorhus/type-fest/issues/22) - The type is powerful, but lacks good use-cases and is prone to misuse.
98
+ - [`ExtractProperties` and `ExtractMethods`](https://github.com/sindresorhus/type-fest/pull/4) - The types violate the single responsibility principle. Instead, refine your types into more granular type hierarchies.
89
99
 
90
100
  ## Tips
91
101
 
@@ -0,0 +1,23 @@
1
+ import {PromiseValue} from './promise-value';
2
+
3
+ type AsyncFunction = (...args: any[]) => Promise<unknown>;
4
+
5
+ /**
6
+ Unwrap the return type of a function that returns a `Promise`.
7
+
8
+ There has been [discussion](https://github.com/microsoft/TypeScript/pull/35998) about implementing this type in TypeScript.
9
+
10
+ @example
11
+ ```ts
12
+ import {AsyncReturnType} from 'type-fest';
13
+ import {asyncFunction} from 'api';
14
+
15
+ // This type resolves to the unwrapped return type of `asyncFunction`.
16
+ type Value = AsyncReturnType<typeof asyncFunction>;
17
+
18
+ async function doSomething(value: Value) {}
19
+
20
+ asyncFunction().then(value => doSomething(value));
21
+ ```
22
+ */
23
+ export type AsyncReturnType<Target extends AsyncFunction> = PromiseValue<ReturnType<Target>>;
package/source/basic.d.ts CHANGED
@@ -40,7 +40,7 @@ Matches a JSON object.
40
40
 
41
41
  This type can be useful to enforce some input to be JSON-compatible or as a super-type to be extended from. Don't use this as a direct return type as the user would have to double-cast it: `jsonObject as unknown as CustomResponse`. Instead, you could extend your CustomResponse type from it to ensure your type only uses JSON-compatible types: `interface CustomResponse extends JsonObject { … }`.
42
42
  */
43
- export type JsonObject = {[key: string]: JsonValue};
43
+ export type JsonObject = {[Key in string]?: JsonValue};
44
44
 
45
45
  /**
46
46
  Matches a JSON array.
@@ -0,0 +1,43 @@
1
+ import {Except} from './except';
2
+ import {ConditionalKeys} from './conditional-keys';
3
+
4
+ /**
5
+ Exclude keys from a shape that matches the given `Condition`.
6
+
7
+ This is useful when you want to create a new type with a specific set of keys from a shape. For example, you might want to exclude all the primitive properties from a class and form a new shape containing everything but the primitive properties.
8
+
9
+ @example
10
+ ```
11
+ import {Primitive, ConditionalExcept} from 'type-fest';
12
+
13
+ class Awesome {
14
+ name: string;
15
+ successes: number;
16
+ failures: bigint;
17
+
18
+ run() {}
19
+ }
20
+
21
+ type ExceptPrimitivesFromAwesome = ConditionalExcept<Awesome, Primitive>;
22
+ //=> {run: () => void}
23
+ ```
24
+
25
+ @example
26
+ ```
27
+ import {ConditionalExcept} from 'type-fest';
28
+
29
+ interface Example {
30
+ a: string;
31
+ b: string | number;
32
+ c: () => void;
33
+ d: {};
34
+ }
35
+
36
+ type NonStringKeysOnly = ConditionalExcept<Example, string>;
37
+ //=> {b: string | number; c: () => void; d: {}}
38
+ ```
39
+ */
40
+ export type ConditionalExcept<Base, Condition> = Except<
41
+ Base,
42
+ ConditionalKeys<Base, Condition>
43
+ >;
@@ -0,0 +1,43 @@
1
+ /**
2
+ Extract the keys from a type where the value type of the key extends the given `Condition`.
3
+
4
+ Internally this is used for the `ConditionalPick` and `ConditionalExcept` types.
5
+
6
+ @example
7
+ ```
8
+ import {ConditionalKeys} from 'type-fest';
9
+
10
+ interface Example {
11
+ a: string;
12
+ b: string | number;
13
+ c?: string;
14
+ d: {};
15
+ }
16
+
17
+ type StringKeysOnly = ConditionalKeys<Example, string>;
18
+ //=> 'a'
19
+ ```
20
+
21
+ To support partial types, make sure your `Condition` is a union of undefined (for example, `string | undefined`) as demonstrated below.
22
+
23
+ @example
24
+ ```
25
+ type StringKeysAndUndefined = ConditionalKeys<Example, string | undefined>;
26
+ //=> 'a' | 'c'
27
+ ```
28
+ */
29
+ export type ConditionalKeys<Base, Condition> = NonNullable<
30
+ // Wrap in `NonNullable` to strip away the `undefined` type from the produced union.
31
+ {
32
+ // Map through all the keys of the given base type.
33
+ [Key in keyof Base]:
34
+ // Pick only keys with types extending the given `Condition` type.
35
+ Base[Key] extends Condition
36
+ // Retain this key since the condition passes.
37
+ ? Key
38
+ // Discard this key since the condition fails.
39
+ : never;
40
+
41
+ // Convert the produced object into a union type of the keys which passed the conditional test.
42
+ }[keyof Base]
43
+ >;
@@ -0,0 +1,42 @@
1
+ import {ConditionalKeys} from './conditional-keys';
2
+
3
+ /**
4
+ Pick keys from the shape that matches the given `Condition`.
5
+
6
+ This is useful when you want to create a new type from a specific subset of an existing type. For example, you might want to pick all the primitive properties from a class and form a new automatically derived type.
7
+
8
+ @example
9
+ ```
10
+ import {Primitive, ConditionalPick} from 'type-fest';
11
+
12
+ class Awesome {
13
+ name: string;
14
+ successes: number;
15
+ failures: bigint;
16
+
17
+ run() {}
18
+ }
19
+
20
+ type PickPrimitivesFromAwesome = ConditionalPick<Awesome, Primitive>;
21
+ //=> {name: string; successes: number; failures: bigint}
22
+ ```
23
+
24
+ @example
25
+ ```
26
+ import {ConditionalPick} from 'type-fest';
27
+
28
+ interface Example {
29
+ a: string;
30
+ b: string | number;
31
+ c: () => void;
32
+ d: {};
33
+ }
34
+
35
+ type StringKeysOnly = ConditionalPick<Example, string>;
36
+ //=> {a: string}
37
+ ```
38
+ */
39
+ export type ConditionalPick<Base, Condition> = Pick<
40
+ Base,
41
+ ConditionalKeys<Base, Condition>
42
+ >;
@@ -257,11 +257,48 @@ declare namespace PackageJson {
257
257
  typings?: string;
258
258
  }
259
259
 
260
+ /**
261
+ An alternative configuration for Yarn workspaces.
262
+ */
263
+ export interface WorkspaceConfig {
264
+ /**
265
+ An array of workspace pattern strings which contain the workspace packages.
266
+ */
267
+ packages?: WorkspacePattern[];
268
+
269
+ /**
270
+ Designed to solve the problem of packages which break when their `node_modules` are moved to the root workspace directory - a process known as hoisting. For these packages, both within your workspace, and also some that have been installed via `node_modules`, it is important to have a mechanism for preventing the default Yarn workspace behavior. By adding workspace pattern strings here, Yarn will resume non-workspace behavior for any package which matches the defined patterns.
271
+
272
+ [Read more](https://classic.yarnpkg.com/blog/2018/02/15/nohoist/)
273
+ */
274
+ nohoist?: WorkspacePattern[];
275
+ }
276
+
277
+ /**
278
+ A workspace pattern points to a directory or group of directories which contain packages that should be included in the workspace installation process.
279
+
280
+ The patterns are handled with [minimatch](https://github.com/isaacs/minimatch).
281
+
282
+ @example
283
+ `docs` → Include the docs directory and install its dependencies.
284
+ `packages/*` → Include all nested directories within the packages directory, like `packages/cli` and `packages/core`.
285
+ */
286
+ type WorkspacePattern = string;
287
+
260
288
  export interface YarnConfiguration {
261
289
  /**
262
- If your package only allows one version of a given dependency, and you’d like to enforce the same behavior as `yarn install --flat` on the command line, set this to `true`.
290
+ Used to configure [Yarn workspaces](https://classic.yarnpkg.com/docs/workspaces/).
291
+
292
+ Workspaces allow you to manage multiple packages within the same repository in such a way that you only need to run `yarn install` once to install all of them in a single pass.
293
+
294
+ Please note that the top-level `private` property of `package.json` **must** be set to `true` in order to use workspaces.
295
+ */
296
+ workspaces?: WorkspacePattern[] | WorkspaceConfig;
297
+
298
+ /**
299
+ If your package only allows one version of a given dependency, and you’d like to enforce the same behavior as `yarn install --flat` on the command-line, set this to `true`.
263
300
 
264
- Note that if your `package.json` contains `"flat": true` and other packages depend on yours (e.g. you are building a library rather than an application), those other packages will also need `"flat": true` in their `package.json` or be installed with `yarn install --flat` on the command-line.
301
+ Note that if your `package.json` contains `"flat": true` and other packages depend on yours (e.g. you are building a library rather than an app), those other packages will also need `"flat": true` in their `package.json` or be installed with `yarn install --flat` on the command-line.
265
302
  */
266
303
  flat?: boolean;
267
304
 
@@ -0,0 +1,20 @@
1
+ /**
2
+ Returns the type that is wrapped inside a `Promise` type.
3
+ If the type is not a `Promise`, the type itself is returned.
4
+
5
+ @example
6
+ ```
7
+ import {PromiseValue} from 'type-fest';
8
+
9
+ type AsyncData = Promise<string>;
10
+ let asyncData: PromiseValue<AsyncData> = Promise.resolve('ABC');
11
+
12
+ type Data = PromiseValue<AsyncData>;
13
+ let data: Data = await asyncData;
14
+
15
+ // Here's an example that shows how this type reacts to non-Promise types.
16
+ type SyncData = PromiseValue<string>;
17
+ let syncData: SyncData = getSyncData();
18
+ ```
19
+ */
20
+ export type PromiseValue<PromiseType, Otherwise = PromiseType> = PromiseType extends Promise<infer Value> ? Value : Otherwise;
@@ -1,5 +1,4 @@
1
1
  // TODO: Remove this when we target TypeScript >=3.5.
2
- // eslint-disable-next-line @typescript-eslint/generic-type-naming
3
2
  type _Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
4
3
 
5
4
  /**
@@ -1,3 +1,5 @@
1
+ import {Except} from './except';
2
+
1
3
  /**
2
4
  Create a type that makes the given keys optional. The remaining keys are kept as is. The sister of the `SetRequired` type.
3
5
 
@@ -23,7 +25,7 @@ type SomeOptional = SetOptional<Foo, 'b' | 'c'>;
23
25
  */
24
26
  export type SetOptional<BaseType, Keys extends keyof BaseType = keyof BaseType> =
25
27
  // Pick just the keys that are not optional from the base type.
26
- Pick<BaseType, Exclude<keyof BaseType, Keys>> &
28
+ Except<BaseType, Keys> &
27
29
  // Pick the keys that should be optional from the base type and make them optional.
28
30
  Partial<Pick<BaseType, Keys>> extends
29
31
  // If `InferredType` extends the previous, then for each key, use the inferred type key.
@@ -1,3 +1,5 @@
1
+ import {Except} from './except';
2
+
1
3
  /**
2
4
  Create a type that makes the given keys required. The remaining keys are kept as is. The sister of the `SetOptional` type.
3
5
 
@@ -23,7 +25,7 @@ type SomeRequired = SetRequired<Foo, 'b' | 'c'>;
23
25
  */
24
26
  export type SetRequired<BaseType, Keys extends keyof BaseType = keyof BaseType> =
25
27
  // Pick just the keys that are not required from the base type.
26
- Pick<BaseType, Exclude<keyof BaseType, Keys>> &
28
+ Except<BaseType, Keys> &
27
29
  // Pick the keys that should be required from the base type and make them required.
28
30
  Required<Pick<BaseType, Keys>> extends
29
31
  // If `InferredType` extends the previous, then for each key, use the inferred type key.
@@ -0,0 +1,21 @@
1
+ /**
2
+ Create a type with the keys of the given type changed to `string` type.
3
+
4
+ Use-case: Changing interface values to strings in order to use them in a form model.
5
+
6
+ @example
7
+ ```
8
+ import {Stringified} from 'type-fest';
9
+
10
+ type Car {
11
+ model: string;
12
+ speed: number;
13
+ }
14
+
15
+ const carForm: Stringified<Car> = {
16
+ model: 'Foo',
17
+ speed: '101'
18
+ };
19
+ ```
20
+ */
21
+ export type Stringified<ObjectType> = {[KeyType in keyof ObjectType]: string};
@@ -0,0 +1,58 @@
1
+ /**
2
+ Convert a union type to an intersection type using [distributive conditional types](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#distributive-conditional-types).
3
+
4
+ Inspired by [this Stack Overflow answer](https://stackoverflow.com/a/50375286/2172153).
5
+
6
+ @example
7
+ ```
8
+ import {UnionToIntersection} from 'type-fest';
9
+
10
+ type Union = {the(): void} | {great(arg: string): void} | {escape: boolean};
11
+
12
+ type Intersection = UnionToIntersection<Union>;
13
+ //=> {the(): void; great(arg: string): void; escape: boolean};
14
+ ```
15
+
16
+ A more applicable example which could make its way into your library code follows.
17
+
18
+ @example
19
+ ```
20
+ import {UnionToIntersection} from 'type-fest';
21
+
22
+ class CommandOne {
23
+ commands: {
24
+ a1: () => undefined,
25
+ b1: () => undefined,
26
+ }
27
+ }
28
+
29
+ class CommandTwo {
30
+ commands: {
31
+ a2: (argA: string) => undefined,
32
+ b2: (argB: string) => undefined,
33
+ }
34
+ }
35
+
36
+ const union = [new CommandOne(), new CommandTwo()].map(instance => instance.commands);
37
+ type Union = typeof union;
38
+ //=> {a1(): void; b1(): void} | {a2(argA: string): void; b2(argB: string): void}
39
+
40
+ type Intersection = UnionToIntersection<Union>;
41
+ //=> {a1(): void; b1(): void; a2(argA: string): void; b2(argB: string): void}
42
+ ```
43
+ */
44
+ export type UnionToIntersection<Union> = (
45
+ // `extends any` is always going to be the case and is used to convert the
46
+ // `Union` into a [distributive conditional
47
+ // type](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#distributive-conditional-types).
48
+ Union extends unknown
49
+ // The union type is used as the only argument to a function since the union
50
+ // of function arguments is an intersection.
51
+ ? (distributedUnion: Union) => void
52
+ // This won't happen.
53
+ : never
54
+ // Infer the `Intersection` type since TypeScript represents the positional
55
+ // arguments of unions of functions as an intersection of the union.
56
+ ) extends ((mergedIntersection: infer Intersection) => void)
57
+ ? Intersection
58
+ : never;
@@ -0,0 +1,40 @@
1
+ /**
2
+ Create a union of the given object's values, and optionally specify which keys to get the values from.
3
+
4
+ Please upvote [this issue](https://github.com/microsoft/TypeScript/issues/31438) if you want to have this type as a built-in in TypeScript.
5
+
6
+ @example
7
+ ```
8
+ // data.json
9
+ {
10
+ 'foo': 1,
11
+ 'bar': 2,
12
+ 'biz': 3
13
+ }
14
+
15
+ // main.ts
16
+ import {ValueOf} from 'type-fest';
17
+ import data = require('./data.json');
18
+
19
+ export function getData(name: string): ValueOf<typeof data> {
20
+ return data[name];
21
+ }
22
+
23
+ export function onlyBar(name: string): ValueOf<typeof data, 'bar'> {
24
+ return data[name];
25
+ }
26
+
27
+ // file.ts
28
+ import {getData, onlyBar} from './main';
29
+
30
+ getData('foo');
31
+ //=> 1
32
+
33
+ onlyBar('foo');
34
+ //=> TypeError ...
35
+
36
+ onlyBar('bar');
37
+ //=> 2
38
+ ```
39
+ */
40
+ export type ValueOf<ObjectType, ValueType extends keyof ObjectType = keyof ObjectType> = ObjectType[ValueType];