get-or-throw 1.4.0 → 1.5.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/.github/workflows/CODEOWNERS +1 -0
- package/.github/workflows/ci.yml +54 -0
- package/.prettierignore +1 -0
- package/.prettierrc.json +0 -1
- package/README.md +22 -16
- package/dist/index.cjs +7 -6
- package/dist/index.d.cts +2 -3
- package/dist/index.d.ts +2 -3
- package/dist/index.js +5 -5
- package/eslint.config.js +28 -0
- package/package.json +11 -4
- package/src/get-or-throw.test.ts +68 -0
- package/src/get-or-throw.ts +14 -22
- package/tsconfig.json +4 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
* @0x80
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
verify:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
strategy:
|
|
13
|
+
fail-fast: false
|
|
14
|
+
matrix:
|
|
15
|
+
command: [lint, type-check, test]
|
|
16
|
+
|
|
17
|
+
name: ${{ matrix.command }}
|
|
18
|
+
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v4
|
|
21
|
+
|
|
22
|
+
- name: Setup Node.js
|
|
23
|
+
uses: actions/setup-node@v4
|
|
24
|
+
with:
|
|
25
|
+
node-version: "22"
|
|
26
|
+
|
|
27
|
+
- name: Setup pnpm
|
|
28
|
+
uses: pnpm/action-setup@v2
|
|
29
|
+
with:
|
|
30
|
+
version: 8
|
|
31
|
+
|
|
32
|
+
- name: Get pnpm store directory
|
|
33
|
+
id: pnpm-cache
|
|
34
|
+
shell: bash
|
|
35
|
+
run: |
|
|
36
|
+
echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
|
|
37
|
+
|
|
38
|
+
- name: Setup pnpm cache
|
|
39
|
+
uses: actions/cache@v4
|
|
40
|
+
with:
|
|
41
|
+
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
|
|
42
|
+
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
43
|
+
# First tries exact match with lock file hash. If not found,
|
|
44
|
+
# falls back to any cache starting with 'pnpm-store-'.
|
|
45
|
+
# This way we get exact cache on repeated runs, but can still
|
|
46
|
+
# use older cache as starting point when dependencies change.
|
|
47
|
+
restore-keys: |
|
|
48
|
+
${{ runner.os }}-pnpm-store-
|
|
49
|
+
|
|
50
|
+
- name: Install dependencies
|
|
51
|
+
run: pnpm install
|
|
52
|
+
|
|
53
|
+
- name: Run ${{ matrix.command }}
|
|
54
|
+
run: pnpm ${{ matrix.command }}
|
package/.prettierignore
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
*.yml
|
package/.prettierrc.json
CHANGED
package/README.md
CHANGED
|
@@ -1,19 +1,22 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Get-Or-Throw / Got
|
|
2
2
|
|
|
3
|
-
A convenience function for
|
|
4
|
-
|
|
3
|
+
A convenience function for safely accessing values in dynamic objects and
|
|
4
|
+
arrays. It gets the value at a specified key or index, and throws an error if
|
|
5
|
+
the resulting value is `undefined` or `null`. Optionally, you can set custom
|
|
6
|
+
error message.
|
|
5
7
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
This was created to make it easy to adhere to Typescript's
|
|
9
|
+
[noUncheckedIndexedAccess](https://www.typescriptlang.org/tsconfig/#noUncheckedIndexedAccess)
|
|
10
|
+
setting, which is recommended for strict type checking.
|
|
9
11
|
|
|
10
12
|
## Features
|
|
11
13
|
|
|
12
|
-
-
|
|
14
|
+
- Typescript assertions for type narrowing.
|
|
13
15
|
- Works with both objects and arrays.
|
|
14
16
|
- Supports negative indexing for arrays.
|
|
15
17
|
- Allows for custom error messages.
|
|
16
18
|
- Zero dependencies.
|
|
19
|
+
- Provides `got` as alias for `getOrThrow`
|
|
17
20
|
|
|
18
21
|
## Installation
|
|
19
22
|
|
|
@@ -25,36 +28,39 @@ pnpm add get-or-throw
|
|
|
25
28
|
|
|
26
29
|
## Usage
|
|
27
30
|
|
|
31
|
+
The example code below uses the `got` alias but `getOrThrow` is also available
|
|
32
|
+
if you want to be more explicit.
|
|
33
|
+
|
|
28
34
|
```ts
|
|
29
35
|
const arr = [1, 2, 3];
|
|
30
|
-
|
|
36
|
+
const value = got(arr, 1); // Output: 2
|
|
31
37
|
|
|
32
38
|
/** Support for negative indexing */
|
|
33
39
|
const arr = [1, 2, 3];
|
|
34
|
-
|
|
40
|
+
const value = got(arr, -1); // Output: 3
|
|
35
41
|
|
|
36
42
|
/** This will throw an error: "Index 3 is out of bounds." */
|
|
37
|
-
|
|
43
|
+
const value = got(arr, 3);
|
|
38
44
|
|
|
39
45
|
const obj = { a: 1, b: 2, c: 3 };
|
|
40
|
-
|
|
46
|
+
const value = got(obj, "b"); // Output: 2
|
|
41
47
|
|
|
42
48
|
/** This will throw an error: "Key "d" does not exist in the object." */
|
|
43
|
-
|
|
49
|
+
const value = got(obj, "d");
|
|
44
50
|
|
|
45
51
|
/** This will throw an error: "Failed to find d" */
|
|
46
52
|
const key = "d";
|
|
47
|
-
|
|
53
|
+
const value = got(obj, key, `Failed to find ${key}`);
|
|
48
54
|
|
|
49
55
|
/** This will throw an error: "Value at index 1 is undefined or null." */
|
|
50
56
|
const arr = [1, null, 3];
|
|
51
|
-
|
|
57
|
+
const value = got(arr, 1);
|
|
52
58
|
|
|
53
59
|
/** This will throw an error: "Value at index 1 is undefined or null." */
|
|
54
60
|
const arr = [1, undefined, 3];
|
|
55
|
-
|
|
61
|
+
const value = got(arr, 1);
|
|
56
62
|
|
|
57
63
|
/** This will throw an error: "Value at key 'b' is undefined or null." */
|
|
58
64
|
const obj = { a: 1, b: undefined, c: 3 };
|
|
59
|
-
|
|
65
|
+
const value = got(obj, "b");
|
|
60
66
|
```
|
package/dist/index.cjs
CHANGED
|
@@ -20,7 +20,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var src_exports = {};
|
|
22
22
|
__export(src_exports, {
|
|
23
|
-
getOrThrow: () => getOrThrow
|
|
23
|
+
getOrThrow: () => getOrThrow,
|
|
24
|
+
got: () => getOrThrow
|
|
24
25
|
});
|
|
25
26
|
module.exports = __toCommonJS(src_exports);
|
|
26
27
|
|
|
@@ -34,17 +35,16 @@ function getOrThrow(objOrArr, keyOrIndex, errorMessage) {
|
|
|
34
35
|
}
|
|
35
36
|
if (index >= 0 && index < length) {
|
|
36
37
|
const value = objOrArr[index];
|
|
37
|
-
if (value
|
|
38
|
-
return value;
|
|
39
|
-
} else if (value === void 0) {
|
|
38
|
+
if (value === void 0) {
|
|
40
39
|
throw new Error(
|
|
41
40
|
errorMessage ?? `Value at index ${String(keyOrIndex)} is undefined.`
|
|
42
41
|
);
|
|
43
|
-
} else {
|
|
42
|
+
} else if (value === null) {
|
|
44
43
|
throw new Error(
|
|
45
44
|
errorMessage ?? `Value at index ${String(keyOrIndex)} is null.`
|
|
46
45
|
);
|
|
47
46
|
}
|
|
47
|
+
return value;
|
|
48
48
|
} else {
|
|
49
49
|
throw new Error(
|
|
50
50
|
errorMessage ?? `Index ${String(keyOrIndex)} is out of bounds.`
|
|
@@ -73,5 +73,6 @@ function getOrThrow(objOrArr, keyOrIndex, errorMessage) {
|
|
|
73
73
|
}
|
|
74
74
|
// Annotate the CommonJS export names for ESM import in node:
|
|
75
75
|
0 && (module.exports = {
|
|
76
|
-
getOrThrow
|
|
76
|
+
getOrThrow,
|
|
77
|
+
got
|
|
77
78
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
* @throws An error if the key or index does not exist, or if the resulting
|
|
11
11
|
* value is undefined or null.
|
|
12
12
|
*/
|
|
13
|
-
declare function getOrThrow<T extends object, K extends keyof T>(objOrArr: T, keyOrIndex: K, errorMessage?: string): NonNullable<T[K]>;
|
|
14
|
-
declare function getOrThrow<T>(objOrArr: T[], keyOrIndex: number, errorMessage?: string): NonNullable<T>;
|
|
13
|
+
declare function getOrThrow<T extends object, K extends keyof T>(objOrArr: T | (T | null)[], keyOrIndex: K | number, errorMessage?: string): NonNullable<T[K]> | NonNullable<T>;
|
|
15
14
|
|
|
16
|
-
export { getOrThrow };
|
|
15
|
+
export { getOrThrow, getOrThrow as got };
|
package/dist/index.d.ts
CHANGED
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
* @throws An error if the key or index does not exist, or if the resulting
|
|
11
11
|
* value is undefined or null.
|
|
12
12
|
*/
|
|
13
|
-
declare function getOrThrow<T extends object, K extends keyof T>(objOrArr: T, keyOrIndex: K, errorMessage?: string): NonNullable<T[K]>;
|
|
14
|
-
declare function getOrThrow<T>(objOrArr: T[], keyOrIndex: number, errorMessage?: string): NonNullable<T>;
|
|
13
|
+
declare function getOrThrow<T extends object, K extends keyof T>(objOrArr: T | (T | null)[], keyOrIndex: K | number, errorMessage?: string): NonNullable<T[K]> | NonNullable<T>;
|
|
15
14
|
|
|
16
|
-
export { getOrThrow };
|
|
15
|
+
export { getOrThrow, getOrThrow as got };
|
package/dist/index.js
CHANGED
|
@@ -8,17 +8,16 @@ function getOrThrow(objOrArr, keyOrIndex, errorMessage) {
|
|
|
8
8
|
}
|
|
9
9
|
if (index >= 0 && index < length) {
|
|
10
10
|
const value = objOrArr[index];
|
|
11
|
-
if (value
|
|
12
|
-
return value;
|
|
13
|
-
} else if (value === void 0) {
|
|
11
|
+
if (value === void 0) {
|
|
14
12
|
throw new Error(
|
|
15
13
|
errorMessage ?? `Value at index ${String(keyOrIndex)} is undefined.`
|
|
16
14
|
);
|
|
17
|
-
} else {
|
|
15
|
+
} else if (value === null) {
|
|
18
16
|
throw new Error(
|
|
19
17
|
errorMessage ?? `Value at index ${String(keyOrIndex)} is null.`
|
|
20
18
|
);
|
|
21
19
|
}
|
|
20
|
+
return value;
|
|
22
21
|
} else {
|
|
23
22
|
throw new Error(
|
|
24
23
|
errorMessage ?? `Index ${String(keyOrIndex)} is out of bounds.`
|
|
@@ -46,5 +45,6 @@ function getOrThrow(objOrArr, keyOrIndex, errorMessage) {
|
|
|
46
45
|
}
|
|
47
46
|
}
|
|
48
47
|
export {
|
|
49
|
-
getOrThrow
|
|
48
|
+
getOrThrow,
|
|
49
|
+
getOrThrow as got
|
|
50
50
|
};
|
package/eslint.config.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import eslint from "@eslint/js";
|
|
2
|
+
import tseslint from "typescript-eslint";
|
|
3
|
+
|
|
4
|
+
export default tseslint.config(
|
|
5
|
+
{
|
|
6
|
+
ignores: [
|
|
7
|
+
"dist/**",
|
|
8
|
+
"node_modules/**",
|
|
9
|
+
/**
|
|
10
|
+
* Ignore all config files int the root. We should instead solve this with
|
|
11
|
+
* projectService setting so that these files can also be linted, but
|
|
12
|
+
* let's get this to work first
|
|
13
|
+
*/
|
|
14
|
+
"*.{js,ts}",
|
|
15
|
+
],
|
|
16
|
+
},
|
|
17
|
+
eslint.configs.recommended,
|
|
18
|
+
tseslint.configs.strictTypeChecked,
|
|
19
|
+
tseslint.configs.stylisticTypeChecked,
|
|
20
|
+
{
|
|
21
|
+
languageOptions: {
|
|
22
|
+
parserOptions: {
|
|
23
|
+
projectService: true,
|
|
24
|
+
tsconfigRootDir: import.meta.dirname,
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "get-or-throw",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "A convenience function for
|
|
3
|
+
"version": "1.5.1",
|
|
4
|
+
"description": "A convenience function for safely getting values from dynamic objects and arrays",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
@@ -29,15 +29,22 @@
|
|
|
29
29
|
"homepage": "https://github.com/0x80/get-or-throw#readme",
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@codecompose/typescript-config": "^1.1.2",
|
|
32
|
+
"@eslint/js": "^9.22.0",
|
|
32
33
|
"del-cli": "^5.1.0",
|
|
34
|
+
"eslint": "^9.22.0",
|
|
33
35
|
"prettier": "^3.3.3",
|
|
34
36
|
"prettier-plugin-jsdoc": "^1.3.0",
|
|
35
37
|
"tsup": "^8.3.0",
|
|
36
|
-
"typescript": "^5.6.2"
|
|
38
|
+
"typescript": "^5.6.2",
|
|
39
|
+
"typescript-eslint": "^8.26.0",
|
|
40
|
+
"vitest": "^3.0.8"
|
|
37
41
|
},
|
|
38
42
|
"scripts": {
|
|
39
43
|
"build": "tsup",
|
|
40
44
|
"clean": "del dist tsconfig.tsbuildinfo",
|
|
41
|
-
"
|
|
45
|
+
"lint": "eslint .",
|
|
46
|
+
"type-check": "tsc --noEmit",
|
|
47
|
+
"test": "vitest",
|
|
48
|
+
"format": "prettier --write ."
|
|
42
49
|
}
|
|
43
50
|
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { getOrThrow, got } from "./get-or-throw";
|
|
3
|
+
|
|
4
|
+
describe("get-or-throw", () => {
|
|
5
|
+
describe("array access", () => {
|
|
6
|
+
it("should get value at positive index", () => {
|
|
7
|
+
const arr = [1, 2, 3];
|
|
8
|
+
expect(got(arr, 1)).toBe(2);
|
|
9
|
+
expect(getOrThrow(arr, 1)).toBe(2);
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it("should support negative indexing", () => {
|
|
13
|
+
const arr = [1, 2, 3];
|
|
14
|
+
expect(got(arr, -1)).toBe(3);
|
|
15
|
+
expect(got(arr, -2)).toBe(2);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it("should throw on out of bounds index", () => {
|
|
19
|
+
const arr = [1, 2, 3];
|
|
20
|
+
expect(() => got(arr, 3)).toThrow("Index 3 is out of bounds.");
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("should throw on null values", () => {
|
|
24
|
+
const arr = [1, null, 3];
|
|
25
|
+
expect(() => got(arr, 1)).toThrow("Value at index 1 is null.");
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it("should throw on undefined values", () => {
|
|
29
|
+
const arr = [1, undefined, 3];
|
|
30
|
+
expect(() => got(arr, 1)).toThrow("Value at index 1 is undefined.");
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
describe("object access", () => {
|
|
35
|
+
it("should get value at existing key", () => {
|
|
36
|
+
const obj = { a: 1, b: 2, c: 3 };
|
|
37
|
+
expect(got(obj, "b")).toBe(2);
|
|
38
|
+
expect(getOrThrow(obj, "b")).toBe(2);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it("should throw on non-existent key", () => {
|
|
42
|
+
const obj = { a: 1, b: 2, c: 3 };
|
|
43
|
+
expect(() => got(obj, "d" as keyof typeof obj)).toThrow(
|
|
44
|
+
'Key "d" does not exist in the object.',
|
|
45
|
+
);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it("should throw on null values", () => {
|
|
49
|
+
const obj = { a: 1, b: null, c: 3 };
|
|
50
|
+
expect(() => got(obj, "b")).toThrow('Value at key "b" is null.');
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it("should throw on undefined values", () => {
|
|
54
|
+
const obj = { a: 1, b: undefined, c: 3 };
|
|
55
|
+
expect(() => got(obj, "b")).toThrow('Value at key "b" is undefined.');
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
describe("custom error messages", () => {
|
|
60
|
+
it("should use custom error message when provided", () => {
|
|
61
|
+
const obj = { a: 1, b: 2, c: 3 };
|
|
62
|
+
const key = "d";
|
|
63
|
+
expect(() =>
|
|
64
|
+
got(obj, key as keyof typeof obj, `Failed to find ${key}`),
|
|
65
|
+
).toThrow("Failed to find d");
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
});
|
package/src/get-or-throw.ts
CHANGED
|
@@ -11,19 +11,9 @@
|
|
|
11
11
|
* value is undefined or null.
|
|
12
12
|
*/
|
|
13
13
|
export function getOrThrow<T extends object, K extends keyof T>(
|
|
14
|
-
objOrArr: T,
|
|
15
|
-
keyOrIndex: K,
|
|
16
|
-
errorMessage?: string
|
|
17
|
-
): NonNullable<T[K]>;
|
|
18
|
-
export function getOrThrow<T>(
|
|
19
|
-
objOrArr: T[],
|
|
20
|
-
keyOrIndex: number,
|
|
21
|
-
errorMessage?: string
|
|
22
|
-
): NonNullable<T>;
|
|
23
|
-
export function getOrThrow<T extends object, K extends keyof T>(
|
|
24
|
-
objOrArr: T | T[],
|
|
14
|
+
objOrArr: T | (T | null)[],
|
|
25
15
|
keyOrIndex: K | number,
|
|
26
|
-
errorMessage?: string
|
|
16
|
+
errorMessage?: string,
|
|
27
17
|
): NonNullable<T[K]> | NonNullable<T> {
|
|
28
18
|
if (Array.isArray(objOrArr)) {
|
|
29
19
|
const length = objOrArr.length;
|
|
@@ -37,20 +27,19 @@ export function getOrThrow<T extends object, K extends keyof T>(
|
|
|
37
27
|
if (index >= 0 && index < length) {
|
|
38
28
|
const value = objOrArr[index];
|
|
39
29
|
|
|
40
|
-
if (value
|
|
41
|
-
return value as NonNullable<T>;
|
|
42
|
-
} else if (value === undefined) {
|
|
30
|
+
if (value === undefined) {
|
|
43
31
|
throw new Error(
|
|
44
|
-
errorMessage ?? `Value at index ${String(keyOrIndex)} is undefined
|
|
32
|
+
errorMessage ?? `Value at index ${String(keyOrIndex)} is undefined.`,
|
|
45
33
|
);
|
|
46
|
-
} else {
|
|
34
|
+
} else if (value === null) {
|
|
47
35
|
throw new Error(
|
|
48
|
-
errorMessage ?? `Value at index ${String(keyOrIndex)} is null
|
|
36
|
+
errorMessage ?? `Value at index ${String(keyOrIndex)} is null.`,
|
|
49
37
|
);
|
|
50
38
|
}
|
|
39
|
+
return value;
|
|
51
40
|
} else {
|
|
52
41
|
throw new Error(
|
|
53
|
-
errorMessage ?? `Index ${String(keyOrIndex)} is out of bounds
|
|
42
|
+
errorMessage ?? `Index ${String(keyOrIndex)} is out of bounds.`,
|
|
54
43
|
);
|
|
55
44
|
}
|
|
56
45
|
} else {
|
|
@@ -61,18 +50,21 @@ export function getOrThrow<T extends object, K extends keyof T>(
|
|
|
61
50
|
return value as NonNullable<T[K]>;
|
|
62
51
|
} else if (value === undefined) {
|
|
63
52
|
throw new Error(
|
|
64
|
-
errorMessage ?? `Value at key "${String(keyOrIndex)}" is undefined
|
|
53
|
+
errorMessage ?? `Value at key "${String(keyOrIndex)}" is undefined.`,
|
|
65
54
|
);
|
|
66
55
|
} else {
|
|
67
56
|
throw new Error(
|
|
68
|
-
errorMessage ?? `Value at key "${String(keyOrIndex)}" is null
|
|
57
|
+
errorMessage ?? `Value at key "${String(keyOrIndex)}" is null.`,
|
|
69
58
|
);
|
|
70
59
|
}
|
|
71
60
|
} else {
|
|
72
61
|
throw new Error(
|
|
73
62
|
errorMessage ??
|
|
74
|
-
`Key "${String(keyOrIndex)}" does not exist in the object
|
|
63
|
+
`Key "${String(keyOrIndex)}" does not exist in the object.`,
|
|
75
64
|
);
|
|
76
65
|
}
|
|
77
66
|
}
|
|
78
67
|
}
|
|
68
|
+
|
|
69
|
+
/** Export the same function under the alias 'got' */
|
|
70
|
+
export { getOrThrow as got };
|