deep-guards 1.1.0 → 1.3.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/LICENSE CHANGED
@@ -186,7 +186,7 @@
186
186
  same "printed page" as the copyright notice for easier
187
187
  identification within third-party archives.
188
188
 
189
- Copyright [yyyy] [name of copyright owner]
189
+ Copyright 2024 Niall Coleman-Clarke
190
190
 
191
191
  Licensed under the Apache License, Version 2.0 (the "License");
192
192
  you may not use this file except in compliance with the License.
package/README.md CHANGED
@@ -54,6 +54,7 @@ if (vehicleGuard(value)) {
54
54
  6. [isUnionOf](#isunionof)
55
55
  7. [isIntersectionOf](#isintersectionof)
56
56
  8. [isExact](#isexact)
57
+ 9. [isInstance](#isinstance)
57
58
  3. [Structures](#structures)
58
59
  1. [isAnyArray](#isanyarray)
59
60
  2. [isAnyRecord](#isanyrecord)
@@ -119,7 +120,7 @@ Has signature:
119
120
 
120
121
  ```ts
121
122
  function isOneOf<
122
- const T extends (string | number | boolean | symbol | null | undefined)[]
123
+ const T extends (string | number | boolean | symbol | null | undefined)[],
123
124
  >(...values: T): Guard<(typeof values)[number]>;
124
125
  ```
125
126
 
@@ -138,10 +139,14 @@ Higher order guard. This takes in any amount of guards as arguments, and then pr
138
139
  Has signature:
139
140
 
140
141
  ```ts
141
- function isExact<const T>(expected: T, deep: boolean = true): Guard<T>;
142
+ function isExact<const T>(expected: T): Guard<T>;
142
143
  ```
143
144
 
144
- This will pass if the incoming value exactly matches the `expected` parameter, optionally computing a deep equality.
145
+ This will pass if the incoming value exactly matches the `expected` parameter. This memoizes checks upfront based on the expected value being passed in. So it's best to create these guards once, and then reuse the returned guard function.
146
+
147
+ ### isInstance
148
+
149
+ Takes in a class and produces a guard to see if values are instances of that class, by using `instanceof`
145
150
 
146
151
  ## Structures
147
152
 
@@ -228,7 +233,7 @@ const carGuard = isObjectOf({
228
233
  passengers: isArrayOf(
229
234
  isObjectOf({
230
235
  name: isString,
231
- })
236
+ }),
232
237
  ),
233
238
  });
234
239
 
@@ -240,7 +245,7 @@ const bikeGuard = isObjectOf({
240
245
 
241
246
  const vehicleGuard = isUnionOf(
242
247
  isDiscriminatedObjectOf("car", carGuard),
243
- isDiscriminatedObjectOf("bike", bikeGuard)
248
+ isDiscriminatedObjectOf("bike", bikeGuard),
244
249
  );
245
250
  ```
246
251
 
@@ -254,7 +259,7 @@ You can then do things like:
254
259
  const cars = guardOrThrow(
255
260
  JSON.parse(readFileSync("cars.json").toString()),
256
261
  isArrayOf(isCar),
257
- "Invalid car format"
262
+ "Invalid car format",
258
263
  );
259
264
  ```
260
265
 
@@ -272,7 +277,7 @@ const carGuard = isObjectOf({
272
277
  passengers: isArrayOf(
273
278
  isObjectOf({
274
279
  name: isString,
275
- })
280
+ }),
276
281
  ),
277
282
  });
278
283
 
@@ -11,5 +11,6 @@ type ArrayToIntersection<A extends readonly unknown[]> = A extends [
11
11
  ...infer R
12
12
  ] ? T & ArrayToIntersection<R> : unknown;
13
13
  export declare function isIntersectionOf<T extends readonly unknown[]>(...guards: GuardSchemaOf<T>): Guard<ArrayToIntersection<T>>;
14
- export declare function isExact<const T>(expected: T, deep?: boolean): Guard<T>;
14
+ export declare function isExact<const T>(expected: T): Guard<T>;
15
+ export declare function isInstance<C extends abstract new (...args: any) => unknown>(cls: C): Guard<InstanceType<C>>;
15
16
  export {};
package/dist/compound.js CHANGED
@@ -36,29 +36,79 @@ export function isIntersectionOf(...guards) {
36
36
  }
37
37
  return (value) => guards.every((guard) => guard(value));
38
38
  }
39
- function objectEntriesChecks(a, b) {
40
- const aKeys = objectKeys(a);
41
- const bKeySet = new Set(objectKeys(b));
42
- return (aKeys.length === bKeySet.size &&
43
- aKeys.every((k) => bKeySet.has(k) && isExact(a[k], true)(b[k])));
39
+ export function isExact(expected) {
40
+ // Primitive checks
41
+ if (typeof expected !== "object" || expected === null) {
42
+ // NaN check
43
+ if (typeof expected === "number" && Number.isNaN(expected)) {
44
+ return (value) => typeof value === "number" && Number.isNaN(value);
45
+ }
46
+ return (value) => value === expected;
47
+ }
48
+ // Date checks
49
+ if (expected instanceof Date) {
50
+ return (value) => value instanceof Date && expected.getTime() === value.getTime();
51
+ }
52
+ // RegExp checks
53
+ if (expected instanceof RegExp) {
54
+ return (value) => value instanceof RegExp &&
55
+ expected.source === value.source &&
56
+ expected.flags === value.flags;
57
+ }
58
+ // Error checks
59
+ if (expected instanceof Error) {
60
+ return (value) => value instanceof Error &&
61
+ expected.name === value.name &&
62
+ expected.message === value.message;
63
+ }
64
+ // Map checks
65
+ if (expected instanceof Map) {
66
+ const guards = Array.from(expected
67
+ .entries()
68
+ .map(([k, v]) => [k, isExact(v)]));
69
+ return (value) => value instanceof Map &&
70
+ expected.size === value.size &&
71
+ guards.every(([k, guard]) => value.has(k) && guard(value.get(k)));
72
+ }
73
+ // Set checks
74
+ if (expected instanceof Set) {
75
+ const guards = new Map(expected.values().map((v) => [v, isExact(v)]));
76
+ return (value) => value instanceof Set &&
77
+ expected.size === value.size &&
78
+ value.values().every((v) => guards.get(v)?.(v));
79
+ }
80
+ // Typed Array checks
81
+ if (ArrayBuffer.isView(expected) && !(expected instanceof DataView)) {
82
+ const guards = Array.from(expected).map((v) => isExact(v));
83
+ return (value) => ArrayBuffer.isView(value) &&
84
+ !(value instanceof DataView) &&
85
+ expected.constructor === value.constructor &&
86
+ expected.length ===
87
+ value.length &&
88
+ guards.every((guard, i) => guard(value[i]));
89
+ }
90
+ // Array checks
91
+ if (Array.isArray(expected)) {
92
+ const guards = expected.map((v) => isExact(v));
93
+ return (value) => Array.isArray(value) &&
94
+ expected.length === value.length &&
95
+ guards.every((guard, i) => guard(value[i]));
96
+ }
97
+ // Object checks
98
+ const guards = objectKeys(expected).map((k) => [k, isExact(expected[k])]);
99
+ function objectEntriesChecks(value) {
100
+ const valueKeys = new Set(objectKeys(value));
101
+ return (guards.length === valueKeys.size &&
102
+ guards.every(([k, guard]) => valueKeys.has(k) && guard(value[k])));
103
+ }
104
+ return (value) => typeof value === "object" &&
105
+ value != null &&
106
+ !Array.isArray(value) &&
107
+ objectKeys(value).length === guards.length &&
108
+ objectEntriesChecks(value);
44
109
  }
45
- export function isExact(expected, deep = true) {
46
- return (value) =>
47
- // Shallow checks
48
- expected === value ||
49
- (Number.isNaN(expected) && Number.isNaN(value)) ||
50
- (deep &&
51
- (Array.isArray(expected)
52
- ? // Array checks
53
- Array.isArray(value) &&
54
- expected.length === value.length &&
55
- expected.every((v, i) => isExact(v, true)(value[i]))
56
- : // Object checks
57
- expected != null &&
58
- value != null &&
59
- typeof expected === "object" &&
60
- typeof value === "object" &&
61
- !Array.isArray(value) &&
62
- objectEntriesChecks(expected, value)));
110
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
111
+ export function isInstance(cls) {
112
+ return (value) => value instanceof cls;
63
113
  }
64
114
  //# sourceMappingURL=compound.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"compound.js","sourceRoot":"src/","sources":["compound.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"compound.js","sourceRoot":"src/","sources":["compound.ts"],"names":[],"mappings":"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"}
@@ -7,7 +7,5 @@ export const isString = (value) => typeof value === "string";
7
7
  export const isSymbol = (value) => typeof value === "symbol";
8
8
  export const isBoolean = (value) => value === true || value === false;
9
9
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
10
- export const isFunction = (value
11
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
12
- ) => typeof value === "function";
10
+ export const isFunction = (value) => typeof value === "function";
13
11
  //# sourceMappingURL=primitives.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"primitives.js","sourceRoot":"src/","sources":["primitives.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,SAAS,GAAmB,CAAC,MAAM,EAAqB,EAAE,CAAC,IAAI,CAAC;AAE7E,MAAM,CAAC,MAAM,MAAM,GAAgB,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,IAAI,CAAC;AAE7D,MAAM,CAAC,MAAM,WAAW,GAAqB,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC;AAE5E,MAAM,CAAC,MAAM,QAAQ,GAAkB,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC;AAE5E,MAAM,CAAC,MAAM,SAAS,GAAkB,CAAC,KAAK,EAAmB,EAAE,CACjE,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;AAE1B,MAAM,CAAC,MAAM,QAAQ,GAAkB,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC;AAE5E,MAAM,CAAC,MAAM,QAAQ,GAAkB,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC;AAE5E,MAAM,CAAC,MAAM,SAAS,GAAmB,CAAC,KAAK,EAAE,EAAE,CACjD,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,KAAK,CAAC;AAEpC,8DAA8D;AAC9D,MAAM,CAAC,MAAM,UAAU,GAAuC,CAC5D,KAAK;AACL,8DAA8D;EACxB,EAAE,CAAC,OAAO,KAAK,KAAK,UAAU,CAAC"}
1
+ {"version":3,"file":"primitives.js","sourceRoot":"src/","sources":["primitives.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,SAAS,GAAmB,CAAC,MAAM,EAAqB,EAAE,CAAC,IAAI,CAAC;AAE7E,MAAM,CAAC,MAAM,MAAM,GAAgB,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,IAAI,CAAC;AAE7D,MAAM,CAAC,MAAM,WAAW,GAAqB,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC;AAE5E,MAAM,CAAC,MAAM,QAAQ,GAAkB,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC;AAE5E,MAAM,CAAC,MAAM,SAAS,GAAkB,CAAC,KAAK,EAAmB,EAAE,CACjE,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;AAE1B,MAAM,CAAC,MAAM,QAAQ,GAAkB,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC;AAE5E,MAAM,CAAC,MAAM,QAAQ,GAAkB,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC;AAE5E,MAAM,CAAC,MAAM,SAAS,GAAmB,CAAC,KAAK,EAAE,EAAE,CACjD,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,KAAK,CAAC;AAEpC,8DAA8D;AAC9D,MAAM,CAAC,MAAM,UAAU,GAAuC,CAC5D,KAAK,EAEiC,EAAE,CAAC,OAAO,KAAK,KAAK,UAAU,CAAC"}
package/eslint.config.js CHANGED
@@ -28,8 +28,10 @@ export default tslint.config(
28
28
  "@typescript-eslint/no-unnecessary-condition": "error",
29
29
  "@stylistic/arrow-parens": "off",
30
30
  "@stylistic/indent": "off",
31
+ "@stylistic/indent-binary-ops": "off",
31
32
  "@stylistic/generator-star-spacing": "off",
32
33
  "@stylistic/quotes": "off",
34
+ "@stylistic/quote-props": "off",
33
35
  "@stylistic/operator-linebreak": "off",
34
36
 
35
37
  // CORE
@@ -62,5 +64,5 @@ export default tslint.config(
62
64
  { varsIgnorePattern: "^_", argsIgnorePattern: "^_" },
63
65
  ],
64
66
  },
65
- }
67
+ },
66
68
  );
package/package.json CHANGED
@@ -1,18 +1,21 @@
1
1
  {
2
2
  "author": "eniallator",
3
3
  "description": "Deep guarding package",
4
+ "engines": {
5
+ "node": ">=25.4.0"
6
+ },
4
7
  "license": "Apache-2.0",
5
8
  "main": "dist/index.js",
6
9
  "name": "deep-guards",
7
- "packageManager": "yarn@4.9.2",
10
+ "packageManager": "yarn@4.12.0",
8
11
  "type": "module",
9
12
  "types": "dist/index.d.ts",
10
13
  "homepage": "https://github.com/eniallator/Deep-Guards",
11
- "version": "1.1.0",
14
+ "version": "1.3.0",
12
15
  "scripts": {
13
- "test": "jest",
16
+ "test": "vitest run --passWithNoTests",
14
17
  "build": "tsc",
15
- "lint": "eslint ./src ./tests",
18
+ "lint": "eslint ./src",
16
19
  "typecheck": "tsc --noEmit",
17
20
  "findissues": "yarn typecheck && yarn lint",
18
21
  "publish": "npm publish --tolerate-republish",
@@ -21,34 +24,18 @@
21
24
  "release": "powershell -ExecutionPolicy Bypass -File ./scripts/release.ps1"
22
25
  },
23
26
  "devDependencies": {
24
- "@babel/core": "^7.28.3",
25
- "@babel/preset-env": "^7.28.3",
26
- "@babel/preset-typescript": "^7.27.1",
27
- "@eslint/compat": "^1.3.2",
28
- "@eslint/js": "^9.33.0",
29
- "@jest/globals": "^30.0.5",
30
- "@stylistic/eslint-plugin": "^5.2.3",
31
- "@types/babel__core": "^7.20.5",
32
- "@types/babel__preset-env": "^7.10.0",
27
+ "@eslint/compat": "^2.0.2",
28
+ "@eslint/js": "^9.39.2",
29
+ "@stylistic/eslint-plugin": "^5.8.0",
33
30
  "@types/eslint__js": "^9.14.0",
34
- "@types/jest": "^30.0.0",
35
- "@typescript-eslint/eslint-plugin": "^8.39.1",
36
- "@typescript-eslint/parser": "^8.39.1",
37
- "babel-jest": "^30.0.5",
38
- "eslint": "^9.33.0",
31
+ "@types/node": "^25.2.3",
32
+ "@typescript-eslint/eslint-plugin": "^8.55.0",
33
+ "@typescript-eslint/parser": "^8.55.0",
34
+ "eslint": "^9.39.2",
39
35
  "eslint-plugin-eslint-comments": "^3.2.0",
40
36
  "eslint-plugin-import": "^2.32.0",
41
- "eslint-plugin-jest": "^29.0.1",
42
- "jest": "^30.0.5",
43
- "ts-jest": "^29.4.1",
44
- "typescript": "^5.9.2",
45
- "typescript-eslint": "^8.39.1"
46
- },
47
- "jest": {
48
- "globals": {
49
- "ts-jest": {
50
- "tsConfig": "tsconfig.test.json"
51
- }
52
- }
37
+ "typescript": "^5.9.3",
38
+ "typescript-eslint": "^8.55.0",
39
+ "vitest": "^4.0.18"
53
40
  }
54
41
  }
@@ -0,0 +1,254 @@
1
+ import { describe, expect, it } from "vitest";
2
+
3
+ import {
4
+ isExact,
5
+ isInstance,
6
+ isIntersectionOf,
7
+ isNonNullable,
8
+ isNot,
9
+ isNullable,
10
+ isOneOf,
11
+ isOptional,
12
+ isUnionOf,
13
+ } from "./compound.ts";
14
+ import { isNumber, isString } from "./primitives.ts";
15
+
16
+ describe("isOptional", () => {
17
+ const guard = isOptional(isString);
18
+
19
+ it("succeeds for the expected type or undefined", () => {
20
+ expect(guard("foo")).toBe(true);
21
+ expect(guard(undefined)).toBe(true);
22
+ });
23
+
24
+ it("fails for any other value", () => {
25
+ expect(guard(null)).toBe(false);
26
+ });
27
+ });
28
+
29
+ describe("isNullable", () => {
30
+ const guard = isNullable(isString);
31
+
32
+ it("succeeds for the expected type, null, or undefined", () => {
33
+ expect(guard("foo")).toBe(true);
34
+ expect(guard(null)).toBe(true);
35
+ expect(guard(undefined)).toBe(true);
36
+ });
37
+
38
+ it("fails any other value", () => {
39
+ expect(guard(1)).toBe(false);
40
+ });
41
+ });
42
+
43
+ describe("isNonNullable", () => {
44
+ it("succeeds for the expected type, null, or undefined", () => {
45
+ expect(isNonNullable("foo")).toBe(true);
46
+ expect(isNonNullable(1)).toBe(true);
47
+ });
48
+
49
+ it("fails any other value", () => {
50
+ expect(isNonNullable(null)).toBe(false);
51
+ expect(isNonNullable(undefined)).toBe(false);
52
+ });
53
+ });
54
+
55
+ describe("isNot", () => {
56
+ const guard = isNot(isString);
57
+
58
+ it("succeeds for any other value", () => {
59
+ expect(guard(1)).toBe(true);
60
+ });
61
+
62
+ it("fails for the isNot type", () => {
63
+ expect(guard("foo")).toBe(false);
64
+ });
65
+ });
66
+
67
+ describe("isOneOf", () => {
68
+ const guard = isOneOf(1, "foo", true);
69
+
70
+ it("succeeds for all of the values", () => {
71
+ expect(guard(1)).toBe(true);
72
+ expect(guard("foo")).toBe(true);
73
+ expect(guard(true)).toBe(true);
74
+ });
75
+
76
+ expect(guard(2)).toBe(false);
77
+ it("fails any other value", () => {
78
+ expect(guard(null)).toBe(false);
79
+ expect(guard("bar")).toBe(false);
80
+ expect(guard(false)).toBe(false);
81
+ });
82
+ });
83
+
84
+ describe("isUnionOf", () => {
85
+ const guard = isUnionOf(isString, isNumber);
86
+ it("succeeds for the union types", () => {
87
+ expect(guard(1)).toBe(true);
88
+ expect(guard("foo")).toBe(true);
89
+ });
90
+
91
+ it("fails for any other type", () => {
92
+ expect(guard(true)).toBe(false);
93
+ expect(guard(null)).toBe(false);
94
+ });
95
+ });
96
+
97
+ describe("isIntersectionOf", () => {
98
+ const guard = isIntersectionOf(isOneOf("foo", "bar", "baz"), isExact("foo"));
99
+
100
+ it("succeeds for the intersection", () => {
101
+ expect(guard("foo")).toBe(true);
102
+ });
103
+
104
+ it("fails for any other type", () => {
105
+ expect(guard("bar")).toBe(false);
106
+ expect(guard(1)).toBe(false);
107
+ });
108
+ });
109
+
110
+ describe("isExact", () => {
111
+ describe("deep", () => {
112
+ const guard = isExact({ foo: "bar", hello: ["world", { key: "test" }] });
113
+
114
+ it("succeeds for the exact value", () => {
115
+ expect(guard({ foo: "bar", hello: ["world", { key: "test" }] })).toBe(
116
+ true,
117
+ );
118
+ });
119
+
120
+ it("fails for any other value", () => {
121
+ expect(guard({ foo: "baz", hello: ["world", { key: "test" }] })).toBe(
122
+ false,
123
+ );
124
+ expect(guard({ foo: "bar", hello: ["world", { key: "tester" }] })).toBe(
125
+ false,
126
+ );
127
+ expect(guard(1)).toBe(false);
128
+ });
129
+ });
130
+
131
+ describe("shallow", () => {
132
+ const guard = isExact("foo");
133
+
134
+ it("succeeds for the exact value", () => {
135
+ expect(guard("foo")).toBe(true);
136
+ });
137
+
138
+ it("fails for any other value", () => {
139
+ expect(guard("bar")).toBe(false);
140
+ expect(guard(1)).toBe(false);
141
+ });
142
+ });
143
+
144
+ describe("Date", () => {
145
+ const date = new Date("2000-01-01");
146
+ const guard = isExact(date);
147
+
148
+ it("succeeds for the exact same date", () => {
149
+ expect(guard(new Date("2000-01-01"))).toBe(true);
150
+ });
151
+
152
+ it("fails for different dates", () => {
153
+ expect(guard(new Date("2000-01-02"))).toBe(false);
154
+ expect(guard(date.getTime())).toBe(false);
155
+ });
156
+ });
157
+
158
+ describe("RegExp", () => {
159
+ const regex = /test/gi;
160
+ const guard = isExact(regex);
161
+
162
+ it("succeeds for the exact same regex", () => {
163
+ expect(guard(/test/gi)).toBe(true);
164
+ });
165
+
166
+ it("fails for different regexes", () => {
167
+ expect(guard(/test/i)).toBe(false);
168
+ expect(guard(/test2/gi)).toBe(false);
169
+ expect(guard("test")).toBe(false);
170
+ });
171
+ });
172
+
173
+ describe("Error", () => {
174
+ const error = new Error("test error");
175
+ const guard = isExact(error);
176
+
177
+ it("succeeds for the exact same error", () => {
178
+ expect(guard(new Error("test error"))).toBe(true);
179
+ });
180
+
181
+ it("fails for different errors", () => {
182
+ expect(guard(new Error("other error"))).toBe(false);
183
+ expect(guard(new TypeError("test error"))).toBe(false);
184
+ expect(guard("test error")).toBe(false);
185
+ });
186
+ });
187
+
188
+ describe("Map", () => {
189
+ const map = new Map([["key", "value"]]);
190
+ const guard = isExact(map);
191
+
192
+ it("succeeds for the exact same map", () => {
193
+ expect(guard(new Map([["key", "value"]]))).toBe(true);
194
+ });
195
+
196
+ it("fails for different maps", () => {
197
+ expect(guard(new Map([["key", "other"]]))).toBe(false);
198
+ expect(guard(new Map([["other", "value"]]))).toBe(false);
199
+ expect(guard(new Map())).toBe(false);
200
+ expect(guard({})).toBe(false);
201
+ });
202
+ });
203
+
204
+ describe("Set", () => {
205
+ const set = new Set([1, 2, 3]);
206
+ const guard = isExact(set);
207
+
208
+ it("succeeds for the exact same set", () => {
209
+ expect(guard(new Set([1, 2, 3]))).toBe(true);
210
+ });
211
+
212
+ it("fails for different sets", () => {
213
+ expect(guard(new Set([1, 2]))).toBe(false);
214
+ expect(guard(new Set([1, 2, 4]))).toBe(false);
215
+ expect(guard([1, 2, 3])).toBe(false);
216
+ });
217
+ });
218
+
219
+ describe("Typed Array", () => {
220
+ const array = new Uint8Array([1, 2, 3]);
221
+ const guard = isExact(array);
222
+
223
+ it("succeeds for the exact same typed array", () => {
224
+ expect(guard(new Uint8Array([1, 2, 3]))).toBe(true);
225
+ });
226
+
227
+ it("fails for different typed arrays", () => {
228
+ expect(guard(new Uint8Array([1, 2]))).toBe(false);
229
+ expect(guard(new Uint8Array([1, 2, 4]))).toBe(false);
230
+ expect(guard(new Int8Array([1, 2, 3]))).toBe(false);
231
+ expect(guard([1, 2, 3])).toBe(false);
232
+ });
233
+ });
234
+ });
235
+
236
+ describe("isInstance", () => {
237
+ class Test {
238
+ foo: string = "bar";
239
+
240
+ constructor(foo: string) {
241
+ this.foo = foo;
242
+ }
243
+ }
244
+ const guard = isInstance(Test);
245
+
246
+ it("succeeds for an instance", () => {
247
+ expect(guard(new Test("baz"))).toBe(true);
248
+ });
249
+
250
+ it("fails for any other type", () => {
251
+ expect(guard({})).toBe(false);
252
+ expect(guard(null)).toBe(false);
253
+ });
254
+ });