@jakubmazanec/ts-utils 1.0.0-fdb1c25
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/LICENSE +18 -0
- package/dist/main.d.ts +2 -0
- package/dist/main.js +4 -0
- package/dist/main.js.map +1 -0
- package/dist/types/AtLeastOneRequired.d.ts +36 -0
- package/dist/types/AtLeastOneRequired.js +35 -0
- package/dist/types/AtLeastOneRequired.js.map +1 -0
- package/dist/types/DeepPartial.d.ts +60 -0
- package/dist/types/DeepPartial.js +3 -0
- package/dist/types/DeepPartial.js.map +1 -0
- package/dist/types/DeepReadonly.d.ts +34 -0
- package/dist/types/DeepReadonly.js +3 -0
- package/dist/types/DeepReadonly.js.map +1 -0
- package/dist/types/If.d.ts +15 -0
- package/dist/types/If.js +16 -0
- package/dist/types/If.js.map +1 -0
- package/dist/types/IsEqual.d.ts +26 -0
- package/dist/types/IsEqual.js +16 -0
- package/dist/types/IsEqual.js.map +1 -0
- package/dist/types/LiteralUnion.d.ts +21 -0
- package/dist/types/LiteralUnion.js +3 -0
- package/dist/types/LiteralUnion.js.map +1 -0
- package/dist/types/NonArray.d.ts +1 -0
- package/dist/types/NonArray.js +3 -0
- package/dist/types/NonArray.js.map +1 -0
- package/dist/types/NonArrayLike.d.ts +1 -0
- package/dist/types/NonArrayLike.js +3 -0
- package/dist/types/NonArrayLike.js.map +1 -0
- package/dist/types/OptionalKeys.d.ts +12 -0
- package/dist/types/OptionalKeys.js +11 -0
- package/dist/types/OptionalKeys.js.map +1 -0
- package/dist/types/Parameters.d.ts +17 -0
- package/dist/types/Parameters.js +18 -0
- package/dist/types/Parameters.js.map +1 -0
- package/dist/types/Primitive.d.ts +4 -0
- package/dist/types/Primitive.js +5 -0
- package/dist/types/Primitive.js.map +1 -0
- package/dist/types/RequiredKeys.d.ts +12 -0
- package/dist/types/RequiredKeys.js +11 -0
- package/dist/types/RequiredKeys.js.map +1 -0
- package/dist/types/ReturnType.d.ts +18 -0
- package/dist/types/ReturnType.js +19 -0
- package/dist/types/ReturnType.js.map +1 -0
- package/dist/types/TupleToUnion.d.ts +10 -0
- package/dist/types/TupleToUnion.js +11 -0
- package/dist/types/TupleToUnion.js.map +1 -0
- package/dist/types/UnionToIntersection.d.ts +15 -0
- package/dist/types/UnionToIntersection.js +11 -0
- package/dist/types/UnionToIntersection.js.map +1 -0
- package/dist/types.d.ts +15 -0
- package/dist/types.js +17 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/assert.d.ts +34 -0
- package/dist/utils/assert.js +41 -0
- package/dist/utils/assert.js.map +1 -0
- package/dist/utils/is.d.ts +28 -0
- package/dist/utils/is.js +31 -0
- package/dist/utils/is.js.map +1 -0
- package/dist/utils/isNonNullable.d.ts +18 -0
- package/dist/utils/isNonNullable.js +21 -0
- package/dist/utils/isNonNullable.js.map +1 -0
- package/dist/utils.d.ts +3 -0
- package/dist/utils.js +5 -0
- package/dist/utils.js.map +1 -0
- package/package.json +35 -0
- package/src/main.ts +2 -0
- package/src/types/AtLeastOneRequired.ts +37 -0
- package/src/types/DeepPartial.ts +83 -0
- package/src/types/DeepReadonly.ts +47 -0
- package/src/types/If.ts +15 -0
- package/src/types/IsEqual.ts +29 -0
- package/src/types/LiteralUnion.ts +22 -0
- package/src/types/NonArray.ts +3 -0
- package/src/types/NonArrayLike.ts +3 -0
- package/src/types/OptionalKeys.ts +15 -0
- package/src/types/Parameters.ts +20 -0
- package/src/types/Primitive.ts +4 -0
- package/src/types/RequiredKeys.ts +15 -0
- package/src/types/ReturnType.ts +21 -0
- package/src/types/TupleToUnion.ts +10 -0
- package/src/types/UnionToIntersection.ts +21 -0
- package/src/types.ts +15 -0
- package/src/utils/assert.ts +44 -0
- package/src/utils/is.ts +30 -0
- package/src/utils/isNonNullable.ts +20 -0
- package/src/utils.ts +3 -0
package/dist/types.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export * from "./types/AtLeastOneRequired.js";
|
|
2
|
+
export * from "./types/DeepPartial.js";
|
|
3
|
+
export * from "./types/DeepReadonly.js";
|
|
4
|
+
export * from "./types/If.js";
|
|
5
|
+
export * from "./types/IsEqual.js";
|
|
6
|
+
export * from "./types/LiteralUnion.js";
|
|
7
|
+
export * from "./types/NonArray.js";
|
|
8
|
+
export * from "./types/NonArrayLike.js";
|
|
9
|
+
export * from "./types/OptionalKeys.js";
|
|
10
|
+
export * from "./types/Parameters.js";
|
|
11
|
+
export * from "./types/Primitive.js";
|
|
12
|
+
export * from "./types/RequiredKeys.js";
|
|
13
|
+
export * from "./types/ReturnType.js";
|
|
14
|
+
export * from "./types/TupleToUnion.js";
|
|
15
|
+
export * from "./types/UnionToIntersection.js";
|
|
16
|
+
|
|
17
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["export * from './types/AtLeastOneRequired.js';\nexport * from './types/DeepPartial.js';\nexport * from './types/DeepReadonly.js';\nexport * from './types/If.js';\nexport * from './types/IsEqual.js';\nexport * from './types/LiteralUnion.js';\nexport * from './types/NonArray.js';\nexport * from './types/NonArrayLike.js';\nexport * from './types/OptionalKeys.js';\nexport * from './types/Parameters.js';\nexport * from './types/Primitive.js';\nexport * from './types/RequiredKeys.js';\nexport * from './types/ReturnType.js';\nexport * from './types/TupleToUnion.js';\nexport * from './types/UnionToIntersection.js';\n"],"names":[],"mappings":"AAAA,cAAc,+BAA+B,CAAC;AAC9C,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,gCAAgC,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A subclass of `Error` that indicates an assertion failure.
|
|
3
|
+
*/
|
|
4
|
+
export declare class AssertionError extends Error {
|
|
5
|
+
/**
|
|
6
|
+
* @param message Message added to the default error message
|
|
7
|
+
*/
|
|
8
|
+
constructor(message?: string);
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* A function that throws {@linkcode AssertionError} (with optional message defined with `errorMessage`) if
|
|
12
|
+
* `condition` is falsy.
|
|
13
|
+
* You can use it to narrow types:
|
|
14
|
+
*
|
|
15
|
+
* ```TypeScript
|
|
16
|
+
* interface Foo {
|
|
17
|
+
* kind: 'Foo';
|
|
18
|
+
* }
|
|
19
|
+
*
|
|
20
|
+
* interface Bar {
|
|
21
|
+
* kind: 'Bar';
|
|
22
|
+
* }
|
|
23
|
+
*
|
|
24
|
+
* declare const foobar: Foo | Bar;
|
|
25
|
+
*
|
|
26
|
+
* assert(is<Foo>(foobar, foobar.kind === 'Foo'));
|
|
27
|
+
*
|
|
28
|
+
* // `typeof foobar` is now `Foo`
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* @param condition Condition we're asserting isn't falsy
|
|
32
|
+
* @param errorMessage Message for the `AssertionError`
|
|
33
|
+
*/
|
|
34
|
+
export declare function assert(condition: unknown, errorMessage?: string): asserts condition;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A subclass of `Error` that indicates an assertion failure.
|
|
3
|
+
*/ export class AssertionError extends Error {
|
|
4
|
+
/**
|
|
5
|
+
* @param message Message added to the default error message
|
|
6
|
+
*/ constructor(message){
|
|
7
|
+
super(`Wrong assertion encountered${message ? `: "${message}"` : ""}!`);
|
|
8
|
+
this.name = "AssertionError";
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* A function that throws {@linkcode AssertionError} (with optional message defined with `errorMessage`) if
|
|
13
|
+
* `condition` is falsy.
|
|
14
|
+
* You can use it to narrow types:
|
|
15
|
+
*
|
|
16
|
+
* ```TypeScript
|
|
17
|
+
* interface Foo {
|
|
18
|
+
* kind: 'Foo';
|
|
19
|
+
* }
|
|
20
|
+
*
|
|
21
|
+
* interface Bar {
|
|
22
|
+
* kind: 'Bar';
|
|
23
|
+
* }
|
|
24
|
+
*
|
|
25
|
+
* declare const foobar: Foo | Bar;
|
|
26
|
+
*
|
|
27
|
+
* assert(is<Foo>(foobar, foobar.kind === 'Foo'));
|
|
28
|
+
*
|
|
29
|
+
* // `typeof foobar` is now `Foo`
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* @param condition Condition we're asserting isn't falsy
|
|
33
|
+
* @param errorMessage Message for the `AssertionError`
|
|
34
|
+
*/ export function assert(condition, errorMessage) {
|
|
35
|
+
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions -- we don't mind here
|
|
36
|
+
if (!condition) {
|
|
37
|
+
throw new AssertionError(errorMessage);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
//# sourceMappingURL=assert.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utils/assert.ts"],"sourcesContent":["/**\n * A subclass of `Error` that indicates an assertion failure.\n */\nexport class AssertionError extends Error {\n /**\n * @param message Message added to the default error message\n */\n constructor(message?: string) {\n super(`Wrong assertion encountered${message ? `: \"${message}\"` : ''}!`);\n\n this.name = 'AssertionError';\n }\n}\n\n/**\n * A function that throws {@linkcode AssertionError} (with optional message defined with `errorMessage`) if\n * `condition` is falsy.\n * You can use it to narrow types:\n *\n * ```TypeScript\n * interface Foo {\n * kind: 'Foo';\n * }\n *\n * interface Bar {\n * kind: 'Bar';\n * }\n *\n * declare const foobar: Foo | Bar;\n *\n * assert(is<Foo>(foobar, foobar.kind === 'Foo'));\n *\n * // `typeof foobar` is now `Foo`\n * ```\n *\n * @param condition Condition we're asserting isn't falsy\n * @param errorMessage Message for the `AssertionError`\n */\nexport function assert(condition: unknown, errorMessage?: string): asserts condition {\n // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions -- we don't mind here\n if (!condition) {\n throw new AssertionError(errorMessage);\n }\n}\n"],"names":["AssertionError","Error","constructor","message","name","assert","condition","errorMessage"],"mappings":"AAAA;;GAEG,CACH,OAAO,MAAMA,cAAc,SAASC,KAAK;IACvC;;KAEG,CACHC,YAAYC,OAAgB,CAAE;QAC5B,KAAK,CAAC,CAAC,2BAA2B,EAAEA,OAAO,GAAG,CAAC,GAAG,EAAEA,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAExE,IAAI,CAACC,IAAI,GAAG,gBAAgB,CAAC;KAC9B;CACF;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG,CACH,OAAO,SAASC,MAAM,CAACC,SAAkB,EAAEC,YAAqB,EAAqB;IACnF,+FAA+F;IAC/F,IAAI,CAACD,SAAS,EAAE;QACd,MAAM,IAAIN,cAAc,CAACO,YAAY,CAAC,CAAC;KACxC;CACF"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A generic type guard. If `isMatched` is `true`, TypeScript assumes `value` is of type `T`.
|
|
3
|
+
* You can use it to narrow types:
|
|
4
|
+
*
|
|
5
|
+
* ```TypeScript
|
|
6
|
+
* interface Foo {
|
|
7
|
+
* value: string;
|
|
8
|
+
* }
|
|
9
|
+
*
|
|
10
|
+
* interface Bar {
|
|
11
|
+
* value: number;
|
|
12
|
+
* }
|
|
13
|
+
*
|
|
14
|
+
* declare let foobar: Foo | Bar;
|
|
15
|
+
*
|
|
16
|
+
* if (is<Foo>(foobar, typeof foobar.value === 'string')) {
|
|
17
|
+
* // `typeof foobar` is now `Foo`
|
|
18
|
+
* } else {
|
|
19
|
+
* // `typeof foobar` is now `Bar`
|
|
20
|
+
* }
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* @typeParam T Potential type of `value`
|
|
24
|
+
* @param value Value being checked
|
|
25
|
+
* @param isMatched Specifies if `value` is of type `T`
|
|
26
|
+
* @return Value of `isMatched`
|
|
27
|
+
*/
|
|
28
|
+
export declare function is<T>(value: unknown, isMatched: boolean): value is T;
|
package/dist/utils/is.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A generic type guard. If `isMatched` is `true`, TypeScript assumes `value` is of type `T`.
|
|
3
|
+
* You can use it to narrow types:
|
|
4
|
+
*
|
|
5
|
+
* ```TypeScript
|
|
6
|
+
* interface Foo {
|
|
7
|
+
* value: string;
|
|
8
|
+
* }
|
|
9
|
+
*
|
|
10
|
+
* interface Bar {
|
|
11
|
+
* value: number;
|
|
12
|
+
* }
|
|
13
|
+
*
|
|
14
|
+
* declare let foobar: Foo | Bar;
|
|
15
|
+
*
|
|
16
|
+
* if (is<Foo>(foobar, typeof foobar.value === 'string')) {
|
|
17
|
+
* // `typeof foobar` is now `Foo`
|
|
18
|
+
* } else {
|
|
19
|
+
* // `typeof foobar` is now `Bar`
|
|
20
|
+
* }
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* @typeParam T Potential type of `value`
|
|
24
|
+
* @param value Value being checked
|
|
25
|
+
* @param isMatched Specifies if `value` is of type `T`
|
|
26
|
+
* @return Value of `isMatched`
|
|
27
|
+
*/ export function is(value, isMatched) {
|
|
28
|
+
return isMatched;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
//# sourceMappingURL=is.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utils/is.ts"],"sourcesContent":["/**\n * A generic type guard. If `isMatched` is `true`, TypeScript assumes `value` is of type `T`.\n * You can use it to narrow types:\n *\n * ```TypeScript\n * interface Foo {\n * value: string;\n * }\n *\n * interface Bar {\n * value: number;\n * }\n *\n * declare let foobar: Foo | Bar;\n *\n * if (is<Foo>(foobar, typeof foobar.value === 'string')) {\n * // `typeof foobar` is now `Foo`\n * } else {\n * // `typeof foobar` is now `Bar`\n * }\n * ```\n *\n * @typeParam T Potential type of `value`\n * @param value Value being checked\n * @param isMatched Specifies if `value` is of type `T`\n * @return Value of `isMatched`\n */\nexport function is<T>(value: unknown, isMatched: boolean): value is T {\n return isMatched;\n}\n"],"names":["is","value","isMatched"],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG,CACH,OAAO,SAASA,EAAE,CAAIC,KAAc,EAAEC,SAAkB,EAAc;IACpE,OAAOA,SAAS,CAAC;CAClB"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A type guard that checks whether variable is not `null` or `undefined`:
|
|
3
|
+
*
|
|
4
|
+
* ```TypeScript
|
|
5
|
+
* declare let foobar: string | null;
|
|
6
|
+
*
|
|
7
|
+
* if (isNonNullable(foobar)) {
|
|
8
|
+
* // `typeof foobar` is now `string`
|
|
9
|
+
* } else {
|
|
10
|
+
* // `typeof foobar` is now `null`
|
|
11
|
+
* }
|
|
12
|
+
* ```
|
|
13
|
+
*
|
|
14
|
+
* @typeParam T Type of `value`
|
|
15
|
+
* @param value Value being checked
|
|
16
|
+
* @return `true` if `value` is non-nullable
|
|
17
|
+
*/
|
|
18
|
+
export declare function isNonNullable<T>(value: T): value is NonNullable<T>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A type guard that checks whether variable is not `null` or `undefined`:
|
|
3
|
+
*
|
|
4
|
+
* ```TypeScript
|
|
5
|
+
* declare let foobar: string | null;
|
|
6
|
+
*
|
|
7
|
+
* if (isNonNullable(foobar)) {
|
|
8
|
+
* // `typeof foobar` is now `string`
|
|
9
|
+
* } else {
|
|
10
|
+
* // `typeof foobar` is now `null`
|
|
11
|
+
* }
|
|
12
|
+
* ```
|
|
13
|
+
*
|
|
14
|
+
* @typeParam T Type of `value`
|
|
15
|
+
* @param value Value being checked
|
|
16
|
+
* @return `true` if `value` is non-nullable
|
|
17
|
+
*/ export function isNonNullable(value) {
|
|
18
|
+
return value !== undefined && value !== null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
//# sourceMappingURL=isNonNullable.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utils/isNonNullable.ts"],"sourcesContent":["/**\n * A type guard that checks whether variable is not `null` or `undefined`:\n *\n * ```TypeScript\n * declare let foobar: string | null;\n *\n * if (isNonNullable(foobar)) {\n * // `typeof foobar` is now `string`\n * } else {\n * // `typeof foobar` is now `null`\n * }\n * ```\n *\n * @typeParam T Type of `value`\n * @param value Value being checked\n * @return `true` if `value` is non-nullable\n */\nexport function isNonNullable<T>(value: T): value is NonNullable<T> {\n return value !== undefined && value !== null;\n}\n"],"names":["isNonNullable","value","undefined"],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG,CACH,OAAO,SAASA,aAAa,CAAIC,KAAQ,EAA2B;IAClE,OAAOA,KAAK,KAAKC,SAAS,IAAID,KAAK,KAAK,IAAI,CAAC;CAC9C"}
|
package/dist/utils.d.ts
ADDED
package/dist/utils.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils.ts"],"sourcesContent":["export * from './utils/assert.js';\nexport * from './utils/is.js';\nexport * from './utils/isNonNullable.js';\n"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,0BAA0B,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@jakubmazanec/ts-utils",
|
|
3
|
+
"version": "1.0.0-fdb1c25",
|
|
4
|
+
"description": "Collection of TypeScript types and utilities.",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git@github.com:jakubmazanec/js-tools.git",
|
|
8
|
+
"directory": "packages/ts-utils"
|
|
9
|
+
},
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"author": "Jakub Mazanec <jakub@mazanec.dev>",
|
|
12
|
+
"sideEffects": false,
|
|
13
|
+
"type": "module",
|
|
14
|
+
"exports": "./dist/main.js",
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"src"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "swc src -d dist && tsc",
|
|
21
|
+
"clean": "del-cli dist *.tsbuildinfo",
|
|
22
|
+
"document": "typedoc --options typedoc.config.cjs",
|
|
23
|
+
"format": "prettier . --write --ignore-unknown --ignore-path ../../.prettierignore",
|
|
24
|
+
"lint": "eslint .",
|
|
25
|
+
"test": "cross-env NODE_OPTIONS=--experimental-vm-modules jest",
|
|
26
|
+
"typecheck": "tsc --project tsconfig.typecheck.json"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@jest/globals": "^28.1.3"
|
|
30
|
+
},
|
|
31
|
+
"packageManager": "npm@8.11.0",
|
|
32
|
+
"engines": {
|
|
33
|
+
"node": ">=16.15.0"
|
|
34
|
+
}
|
|
35
|
+
}
|
package/src/main.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Constructs new type from `T` so that at least one property from the set of properties `P` is required:
|
|
3
|
+
*
|
|
4
|
+
* ```TypeScript
|
|
5
|
+
* import { AtLeastOneRequired } from '@ori/ts-utils';
|
|
6
|
+
*
|
|
7
|
+
* type FooOrBar = AtLeastOneRequired<{foo: string; bar: string; qux: string}, 'foo' | 'bar'>;
|
|
8
|
+
*
|
|
9
|
+
* const fooOrBar1: FooOrBar = {
|
|
10
|
+
* foo: 'this is required',
|
|
11
|
+
* qux: 'this always required',
|
|
12
|
+
* };
|
|
13
|
+
*
|
|
14
|
+
* const fooOrBar2: FooOrBar = {
|
|
15
|
+
* bar: 'or this is required',
|
|
16
|
+
* qux: 'this always required',
|
|
17
|
+
* };
|
|
18
|
+
*
|
|
19
|
+
* const fooOrBar3: FooOrBar = {
|
|
20
|
+
* foo: 'we can have foo',
|
|
21
|
+
* bar: 'and bar',
|
|
22
|
+
* qux: 'this always required',
|
|
23
|
+
* };
|
|
24
|
+
*
|
|
25
|
+
* const fooOrBar4: FooOrBar = {
|
|
26
|
+
* // no foo nor bar
|
|
27
|
+
* qux: 'this always required',
|
|
28
|
+
* }; // error TS2322: Type '{ qux: string; }' is not assignable to type 'FooOrBar'
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* @typeParam T Base for the new type
|
|
32
|
+
* @typeParam P String literal or union of string literals specifying properties of `T`
|
|
33
|
+
*/
|
|
34
|
+
export type AtLeastOneRequired<T, P extends keyof T = keyof T> = {
|
|
35
|
+
[K in P]-?: Partial<Pick<T, Exclude<P, K>>> & Required<Pick<T, K>>;
|
|
36
|
+
}[P] &
|
|
37
|
+
Pick<T, Exclude<keyof T, P>>;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-empty-interface -- needed */
|
|
2
|
+
|
|
3
|
+
import type {Primitive} from './Primitive.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Same as built-in `Partial`, but works recursively. Useful when 1) you have a config object to which you need to merge another object, which would be a deep partial of a default object, or 2) you need to test or mock complex object, but most of its keys would be redundant for this purpose.
|
|
7
|
+
*
|
|
8
|
+
* ```TypeScript
|
|
9
|
+
* import { DeepPartial } from '@ori/ts-utils';
|
|
10
|
+
* import { UiSettings } from './UiSettings';
|
|
11
|
+
*
|
|
12
|
+
* let settings: UiSettings = {
|
|
13
|
+
* lineNumbers: true,
|
|
14
|
+
* scrollbar: {
|
|
15
|
+
* useShadows: false,
|
|
16
|
+
* vertical: 'visible',
|
|
17
|
+
* horizontal: 'auto',
|
|
18
|
+
* },
|
|
19
|
+
* minimap: {
|
|
20
|
+
* enabled: false,
|
|
21
|
+
* },
|
|
22
|
+
* folding: {
|
|
23
|
+
* enabled: true,
|
|
24
|
+
* },
|
|
25
|
+
* };
|
|
26
|
+
*
|
|
27
|
+
* function updateSettings(newSettings: DeepPartial<UiSettings>) {
|
|
28
|
+
* return { ...settings, ...newSettings };
|
|
29
|
+
* }
|
|
30
|
+
*
|
|
31
|
+
* settings = updateSettings({ minimap: { enabled: true } });
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* @typeParam T Base for the new type
|
|
35
|
+
*/
|
|
36
|
+
export type DeepPartial<T> = T extends Date | Primitive | RegExp
|
|
37
|
+
? T
|
|
38
|
+
: T extends Map<infer KeyType, infer ValueType>
|
|
39
|
+
? DeepPartialMap<KeyType, ValueType>
|
|
40
|
+
: T extends Set<infer ItemType>
|
|
41
|
+
? DeepPartialSet<ItemType>
|
|
42
|
+
: T extends ReadonlyMap<infer KeyType, infer ValueType>
|
|
43
|
+
? DeepPartialReadonlyMap<KeyType, ValueType>
|
|
44
|
+
: T extends ReadonlySet<infer ItemType>
|
|
45
|
+
? DeepPartialReadonlySet<ItemType>
|
|
46
|
+
: T extends (...args: any[]) => unknown
|
|
47
|
+
? T | undefined
|
|
48
|
+
: T extends object
|
|
49
|
+
? T extends Array<infer I> // Test for arrays/tuples, per https://github.com/microsoft/TypeScript/issues/35156
|
|
50
|
+
? I[] extends T // Test for arrays (non-tuples) specifically
|
|
51
|
+
? Array<DeepPartial<I | undefined>> // Recreate relevant array type to prevent eager evaluation of circular reference
|
|
52
|
+
: DeepPartialObject<T> // Tuples behave properly
|
|
53
|
+
: DeepPartialObject<T>
|
|
54
|
+
: unknown;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Helper type for {@linkcode DeepPartial}.
|
|
58
|
+
*/
|
|
59
|
+
interface DeepPartialMap<KeyType, ValueType>
|
|
60
|
+
extends Map<DeepPartial<KeyType>, DeepPartial<ValueType>> {}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Helper type for {@linkcode DeepPartial}.
|
|
64
|
+
*/
|
|
65
|
+
interface DeepPartialSet<T> extends Set<DeepPartial<T>> {}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Helper type for {@linkcode DeepPartial}.
|
|
69
|
+
*/
|
|
70
|
+
interface DeepPartialReadonlyMap<KeyType, ValueType>
|
|
71
|
+
extends ReadonlyMap<DeepPartial<KeyType>, DeepPartial<ValueType>> {}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Helper type for {@linkcode DeepPartial}.
|
|
75
|
+
*/
|
|
76
|
+
interface DeepPartialReadonlySet<T> extends ReadonlySet<DeepPartial<T>> {}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Helper type for {@linkcode DeepPartial}.
|
|
80
|
+
*/
|
|
81
|
+
type DeepPartialObject<ObjectType extends object> = {
|
|
82
|
+
[KeyType in keyof ObjectType]?: DeepPartial<ObjectType[KeyType]>;
|
|
83
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any -- needed */
|
|
2
|
+
|
|
3
|
+
import type {Primitive} from './Primitive.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Same as built-in `Readonly`, but works recursively:
|
|
7
|
+
*
|
|
8
|
+
* ```TypeScript
|
|
9
|
+
* import { DeepReadonly } from '@ori/ts-utils';
|
|
10
|
+
*
|
|
11
|
+
* const rawData = {
|
|
12
|
+
* foo: ['bar'],
|
|
13
|
+
* };
|
|
14
|
+
*
|
|
15
|
+
* const data: DeepReadonly<typeof rawData> = rawData;
|
|
16
|
+
*
|
|
17
|
+
* data.foo.push('bar'); // error TS2339: Property 'push' does not exist on type 'readonly string[]'
|
|
18
|
+
* ```
|
|
19
|
+
*
|
|
20
|
+
* @typeParam T Base for the new type
|
|
21
|
+
*/
|
|
22
|
+
export type DeepReadonly<T> = T extends Primitive | ((...args: any[]) => unknown)
|
|
23
|
+
? T
|
|
24
|
+
: T extends ReadonlyMap<infer K, infer V>
|
|
25
|
+
? DeepReadonlyMap<K, V>
|
|
26
|
+
: T extends ReadonlySet<infer I>
|
|
27
|
+
? DeepReadonlySet<I>
|
|
28
|
+
: T extends object
|
|
29
|
+
? DeepReadonlyObject<T>
|
|
30
|
+
: unknown;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Helper type for {@linkcode DeepReadonly}.
|
|
34
|
+
*/
|
|
35
|
+
type DeepReadonlyMap<K, V> = ReadonlyMap<DeepReadonly<K>, DeepReadonly<V>>;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Helper type for {@linkcode DeepReadonly}.
|
|
39
|
+
*/
|
|
40
|
+
type DeepReadonlySet<I> = ReadonlySet<DeepReadonly<I>>;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Helper type for {@linkcode DeepReadonly}.
|
|
44
|
+
*/
|
|
45
|
+
type DeepReadonlyObject<O extends object> = {
|
|
46
|
+
readonly [K in keyof O]: DeepReadonly<O[K]>;
|
|
47
|
+
};
|
package/src/types/If.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `If<X, Y, T, F>` is shorthand for conditional type `X extends Y ? T : F`:
|
|
3
|
+
*
|
|
4
|
+
* ```TypeScript
|
|
5
|
+
* // these two types are equivalent:
|
|
6
|
+
* type NonNullable<T> = T extends null | undefined ? never : T;
|
|
7
|
+
* type NonNullable<T> = If<T, null | undefined, never, T>;
|
|
8
|
+
* ```
|
|
9
|
+
*
|
|
10
|
+
* @typeParam X Type on the left of the `extends`
|
|
11
|
+
* @typeParam Y Type on the right of the `extends`
|
|
12
|
+
* @typeParam T Type returned when `X` is assignable to `Y`
|
|
13
|
+
* @typeParam F Type returned when `X` isn't assignable to `Y`
|
|
14
|
+
*/
|
|
15
|
+
export type If<X, Y, T, F> = X extends Y ? T : F;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Allows you to test if two types are the same:
|
|
3
|
+
*
|
|
4
|
+
* ```TypeScript
|
|
5
|
+
* type Result = IsEqual<string, number> // `typeof Result` is `false`
|
|
6
|
+
* ```
|
|
7
|
+
*
|
|
8
|
+
* ```TypeScript
|
|
9
|
+
* type Result = IsEqual<{foo: string}, {foo: string}> // `typeof Result` is `true`
|
|
10
|
+
* ```
|
|
11
|
+
*
|
|
12
|
+
* @typeParam A1 First type to compare
|
|
13
|
+
* @typeParam A2 Second type to compare
|
|
14
|
+
*/
|
|
15
|
+
export type IsEqual<A1, A2> = IsStrictlyEqual<Unite<A1>, Unite<A2>>;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Helper type for {@linkcode IsEqual}.
|
|
19
|
+
*/
|
|
20
|
+
type IsStrictlyEqual<A1, A2> = (<A>() => A extends A2 ? true : false) extends <A>() => A extends A1
|
|
21
|
+
? true
|
|
22
|
+
: false
|
|
23
|
+
? true
|
|
24
|
+
: false;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Helper type for {@linkcode IsEqual}.
|
|
28
|
+
*/
|
|
29
|
+
type Unite<T> = T extends Record<string, unknown> ? {[K in keyof T]: T[K]} : T;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type {Primitive} from './Primitive.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Creates union type by combining primitve types and literal types while allowing auto-completion in IDEs.
|
|
5
|
+
* This type is a workaround for [Microsoft/TypeScript#29729](https://github.com/Microsoft/TypeScript/issues/29729).
|
|
6
|
+
*
|
|
7
|
+
* ```TypeScript
|
|
8
|
+
* type Animal = 'cat' | 'dog' | string;
|
|
9
|
+
*
|
|
10
|
+
* const: animal: Animal = ''; // No auto-completion here...
|
|
11
|
+
* ```
|
|
12
|
+
*
|
|
13
|
+
* ```TypeScript
|
|
14
|
+
* type Animal = LiteralUnion<'cat' | 'dog', string>;
|
|
15
|
+
*
|
|
16
|
+
* const: animal: Animal = ''; // Auto-completion works: 'cat' and 'dog' is suggested!
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* @typeParam L Union of literal types
|
|
20
|
+
* @typeParam T Primitive type
|
|
21
|
+
*/
|
|
22
|
+
export type LiteralUnion<L, T extends Primitive> = L | (Record<never, never> & T);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extracts the optional keys of type `T`:
|
|
3
|
+
*
|
|
4
|
+
* ```TypeScript
|
|
5
|
+
* type Result = OptionalKeys<{ foo?: number; bar?: string; baz: boolean; }>; // `typeof Result` is `'foo' | 'bar`
|
|
6
|
+
* ```
|
|
7
|
+
*
|
|
8
|
+
* @typeParam T Base for the new type
|
|
9
|
+
*/
|
|
10
|
+
export type OptionalKeys<T extends object> = Exclude<
|
|
11
|
+
{
|
|
12
|
+
[K in keyof T]: T extends Record<K, T[K]> ? never : K;
|
|
13
|
+
}[keyof T],
|
|
14
|
+
undefined
|
|
15
|
+
>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any -- needed */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Constructs a tuple type from the types used in the parameters of a function type `T`.
|
|
5
|
+
* Similarly like built-in `Parameters` utility type, but works also on nullable and other types.
|
|
6
|
+
*
|
|
7
|
+
* ```TypeScript
|
|
8
|
+
* interface Foo {
|
|
9
|
+
* get?: (id: number) => string;
|
|
10
|
+
* }
|
|
11
|
+
*
|
|
12
|
+
* declare const foo: Foo;
|
|
13
|
+
*
|
|
14
|
+
* type Result = Parameters<typeof foo.get>; // `typeof Result` is `[id: number]`
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* @typeParam T Base for the new type
|
|
18
|
+
*/
|
|
19
|
+
export type Parameters<T extends '' | false | ((...args: any[]) => any) | null | undefined> =
|
|
20
|
+
T extends (...args: infer P) => any ? P : never;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extracts the non-optional keys of type `T`:
|
|
3
|
+
*
|
|
4
|
+
* ```TypeScript
|
|
5
|
+
* type Result = RequiredKeys<{ foo: number; bar: string; baz?: boolean; }>; // `typeof Result` is `'foo' | 'bar`
|
|
6
|
+
* ```
|
|
7
|
+
*
|
|
8
|
+
* @typeParam T Base for the new type
|
|
9
|
+
*/
|
|
10
|
+
export type RequiredKeys<T extends object> = Exclude<
|
|
11
|
+
{
|
|
12
|
+
[K in keyof T]: T extends Record<K, T[K]> ? K : never;
|
|
13
|
+
}[keyof T],
|
|
14
|
+
undefined
|
|
15
|
+
>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any -- needed */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Constructs a type consisting of the return type of function `T`.
|
|
5
|
+
* Similarly like built-in `ReturnType` utility type, but works also on nullable and other types,
|
|
6
|
+
* and if you use it with async function, it doesn't return the type as a `Promise`:
|
|
7
|
+
*
|
|
8
|
+
* ```TypeScript
|
|
9
|
+
* interface Foo {
|
|
10
|
+
* get?: (id: number) => Promise<string>;
|
|
11
|
+
* }
|
|
12
|
+
*
|
|
13
|
+
* declare const foo: Foo;
|
|
14
|
+
*
|
|
15
|
+
* type Result = ReturnType<typeof foo.get>; // `typeof Result` is `string`
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* @typeParam T Base for the new type
|
|
19
|
+
*/
|
|
20
|
+
export type ReturnType<T extends '' | false | ((...args: any[]) => any) | null | undefined> =
|
|
21
|
+
T extends (...args: any[]) => infer R ? (R extends PromiseLike<infer J> ? J : R) : never;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converts tuple type to union type:
|
|
3
|
+
*
|
|
4
|
+
* ```TypeScript
|
|
5
|
+
* type Result = TupleToUnion<['foo', 'bar']>; // `typeof Result` is `"foo" | "bar"`
|
|
6
|
+
* ```
|
|
7
|
+
*
|
|
8
|
+
* @typeParam T Base for the new type
|
|
9
|
+
*/
|
|
10
|
+
export type TupleToUnion<T extends unknown[] | readonly unknown[]> = T[number];
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converts union type to intersection type:
|
|
3
|
+
*
|
|
4
|
+
* ```TypeScript
|
|
5
|
+
* type Result = UnionToIntersection<{ foo: string } | { bar: string }>; // `typeof Result` is `{foo: string} & {bar: string}`
|
|
6
|
+
* ```
|
|
7
|
+
*
|
|
8
|
+
* @typeParam U Base for the new type
|
|
9
|
+
*/
|
|
10
|
+
export type UnionToIntersection<U> = boolean extends U
|
|
11
|
+
? UnionToIntersectionHelper<Exclude<U, boolean>> & boolean
|
|
12
|
+
: UnionToIntersectionHelper<U>;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Helper type for {@linkcode UnionToIntersection}.
|
|
16
|
+
*/
|
|
17
|
+
type UnionToIntersectionHelper<U> = (U extends unknown ? (k: U) => void : never) extends (
|
|
18
|
+
k: infer I,
|
|
19
|
+
) => void
|
|
20
|
+
? I
|
|
21
|
+
: never;
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export * from './types/AtLeastOneRequired.js';
|
|
2
|
+
export * from './types/DeepPartial.js';
|
|
3
|
+
export * from './types/DeepReadonly.js';
|
|
4
|
+
export * from './types/If.js';
|
|
5
|
+
export * from './types/IsEqual.js';
|
|
6
|
+
export * from './types/LiteralUnion.js';
|
|
7
|
+
export * from './types/NonArray.js';
|
|
8
|
+
export * from './types/NonArrayLike.js';
|
|
9
|
+
export * from './types/OptionalKeys.js';
|
|
10
|
+
export * from './types/Parameters.js';
|
|
11
|
+
export * from './types/Primitive.js';
|
|
12
|
+
export * from './types/RequiredKeys.js';
|
|
13
|
+
export * from './types/ReturnType.js';
|
|
14
|
+
export * from './types/TupleToUnion.js';
|
|
15
|
+
export * from './types/UnionToIntersection.js';
|