deep-guards 1.0.3 → 1.0.5

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/README.md CHANGED
@@ -186,6 +186,8 @@ NOTE: This passes for empty records
186
186
 
187
187
  This is a function which takes in a structured object, containing keys of type `string | number | symbol`, and then values which are guard functions.
188
188
 
189
+ This also takes in a second boolean parameter for if the guard should check that the keys exactly match the structured guard object's keys. It then doesn't let any "leaky" objects through, which have extra keys. This defaults to false.
190
+
189
191
  As seen in the example at the start of this readme, you can do all sorts of complex nesting, as this produces a guard in the end.
190
192
 
191
193
  NOTE: This throws an error if you give it an empty object.\
@@ -197,7 +199,8 @@ These are common use cases for guarding setups, where they are made entirely out
197
199
 
198
200
  ### isDiscriminatedObjectOf
199
201
 
200
- This takes in a string literal `type`, and an `isObjectOf` guard. This then combines the two, where the returned guard has the signature: `Guard<{ type: T } & O>`.
202
+ This takes in a string literal for the discriminated value, and an `isObjectOf` guard, and then an optional key specifying which key is for the discriminated union. This then combines the object with the discriminator, where the returned guard has the signature: `Guard<{ [key]: T } & O>`.
203
+
201
204
  This is good for use cases where you don't have a discriminator on an individual type, but then do have it on the union type. For example:
202
205
 
203
206
  ```ts
@@ -1,4 +1,5 @@
1
- import { Guard, GuardSchemaOf } from "./types";
1
+ import { GuardSchemaOf } from "./helpers.js";
2
+ import { Guard } from "./types.js";
2
3
  export declare function isOptional<T>(guard: Guard<T>): Guard<T | undefined>;
3
4
  export declare function isNullable<T>(guard: Guard<T>): Guard<T | null | undefined>;
4
5
  export declare function isNonNullable<T>(value: T | null | undefined): value is T;
package/dist/compound.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { objectKeys } from "./helpers.js";
1
2
  export function isOptional(guard) {
2
3
  if (typeof guard !== "function") {
3
4
  throw new TypeError(`isOptional expects a guard parameter. Got instead: ${guard}`);
@@ -35,20 +36,29 @@ export function isIntersectionOf(...guards) {
35
36
  }
36
37
  return (value) => guards.every((guard) => guard(value));
37
38
  }
38
- function isEqual(a, b) {
39
- return (a === b ||
40
- (a != null &&
41
- b != null &&
42
- typeof a === "object" &&
43
- typeof b === "object" &&
44
- (Array.isArray(a)
45
- ? Array.isArray(b) &&
46
- a.length === b.length &&
47
- a.every((v, i) => isEqual(v, b[i]))
48
- : Object.keys(a).length === Object.keys(b).length &&
49
- Object.entries(a).every(([k, v]) => k in b && isEqual(v, b[k])))));
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])));
50
44
  }
51
45
  export function isExact(expected, deep = true) {
52
- return (value) => deep ? isEqual(expected, value) : expected === value;
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)));
53
63
  }
54
64
  //# 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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"}
package/dist/errors.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Guard } from "./types";
1
+ import { Guard } from "./types.js";
2
2
  export declare class GuardError extends Error {
3
3
  name: string;
4
4
  }
@@ -0,0 +1,9 @@
1
+ import { Guard } from "./types.js";
2
+ export type GuardSchemaOf<O extends object> = {
3
+ [K in keyof O]: Guard<O[K]>;
4
+ };
5
+ export type ObjectKey = string | number | symbol;
6
+ export declare const objectKeys: <K extends ObjectKey>(obj: Record<K, unknown>) => K[];
7
+ export declare function omit<O extends object>(obj: O, key: keyof O): {
8
+ [K in keyof O as K extends typeof key ? never : K]: O[K];
9
+ };
@@ -0,0 +1,8 @@
1
+ export const objectKeys = (obj) => Object.getOwnPropertyNames(obj).concat(Object.getOwnPropertySymbols(obj));
2
+ export function omit(obj, key) {
3
+ const omitted = { ...obj };
4
+ // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
5
+ delete omitted[key];
6
+ return omitted;
7
+ }
8
+ //# sourceMappingURL=helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.js","sourceRoot":"src/","sources":["helpers.ts"],"names":[],"mappings":"AAQA,MAAM,CAAC,MAAM,UAAU,GAAG,CAAsB,GAAuB,EAAO,EAAE,CAC7E,MAAM,CAAC,mBAAmB,CAAC,GAAG,CAAS,CAAC,MAAM,CAC7C,MAAM,CAAC,qBAAqB,CAAC,GAAG,CAAQ,CACzC,CAAC;AAEJ,MAAM,UAAU,IAAI,CAClB,GAAM,EACN,GAAY;IAEZ,MAAM,OAAO,GAAG,EAAE,GAAG,GAAG,EAAE,CAAC;IAC3B,gEAAgE;IAChE,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC;IACpB,OAAO,OAAO,CAAC;AACjB,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- export * from "./compound";
2
- export * from "./errors";
3
- export * from "./macros";
4
- export * from "./primitives";
5
- export * from "./structures";
6
- export * from "./types";
1
+ export * from "./compound.js";
2
+ export * from "./errors.js";
3
+ export * from "./macros.js";
4
+ export * from "./primitives.js";
5
+ export * from "./structures.js";
6
+ export * from "./types.js";
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
- export * from "./compound";
2
- export * from "./errors";
3
- export * from "./macros";
4
- export * from "./primitives";
5
- export * from "./structures";
6
- export * from "./types";
1
+ export * from "./compound.js";
2
+ export * from "./errors.js";
3
+ export * from "./macros.js";
4
+ export * from "./primitives.js";
5
+ export * from "./structures.js";
6
+ export * from "./types.js";
7
7
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"src/","sources":["index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"src/","sources":["index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC"}
package/dist/macros.d.ts CHANGED
@@ -1,4 +1,8 @@
1
- import { Guard } from "./types";
2
- export declare const isDiscriminatedObjectOf: <T extends string, O extends object>(type: T, guard: Guard<O>) => Guard<{
1
+ import { ObjectKey } from "./helpers.js";
2
+ import { Guard } from "./types.js";
3
+ export declare function isDiscriminatedObjectOf<const T extends string, O extends object>(value: T, guard: Guard<O>): Guard<{
3
4
  type: T;
4
5
  } & O>;
6
+ export declare function isDiscriminatedObjectOf<const T extends string, O extends object, const K extends ObjectKey>(value: T, guard: Guard<O>, key: K): Guard<{
7
+ [S in K]: T;
8
+ } & O>;
package/dist/macros.js CHANGED
@@ -1,4 +1,8 @@
1
- import { isExact, isIntersectionOf } from "./compound";
2
- import { isObjectOf } from "./structures";
3
- export const isDiscriminatedObjectOf = (type, guard) => isIntersectionOf(isObjectOf({ type: isExact(type) }), guard);
1
+ import { isExact } from "./compound.js";
2
+ import { omit } from "./helpers.js";
3
+ import { isObjectOf } from "./structures.js";
4
+ export function isDiscriminatedObjectOf(value, guard, key = "type") {
5
+ const discriminatorGuard = isObjectOf({ [key]: isExact(value) });
6
+ return (value) => discriminatorGuard(value) && guard(omit(value, key));
7
+ }
4
8
  //# sourceMappingURL=macros.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"macros.js","sourceRoot":"src/","sources":["macros.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG1C,MAAM,CAAC,MAAM,uBAAuB,GAAG,CACrC,IAAO,EACP,KAAe,EACS,EAAE,CAC1B,gBAAgB,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,KAAK,CAE1D,CAAC"}
1
+ {"version":3,"file":"macros.js","sourceRoot":"src/","sources":["macros.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAa,IAAI,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAY7C,MAAM,UAAU,uBAAuB,CAIrC,KAAQ,EACR,KAAe,EACf,MAAiB,MAAM;IAEvB,MAAM,kBAAkB,GAAG,UAAU,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,EAAE,CAE7D,CAAC;IACH,OAAO,CAAC,KAAK,EAAyC,EAAE,CACtD,kBAAkB,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;AACzD,CAAC"}
@@ -1,4 +1,4 @@
1
- import { Guard } from "./types";
1
+ import { Guard } from "./types.js";
2
2
  export declare const isUnknown: Guard<unknown>;
3
3
  export declare const isNull: Guard<null>;
4
4
  export declare const isUndefined: Guard<undefined>;
@@ -1,10 +1,11 @@
1
- import { Guard, GuardSchemaOf } from "./types";
2
- type ObjectKey = string | number | symbol;
1
+ import { GuardSchemaOf, ObjectKey } from "./helpers.js";
2
+ import { Guard } from "./types.js";
3
3
  export declare const isAnyArray: Guard<unknown[]>;
4
4
  export declare const isAnyRecord: Guard<Record<ObjectKey, unknown>>;
5
5
  export declare function isArrayOf<T>(guard: Guard<T>): Guard<T[]>;
6
6
  export declare function isTupleOf<T extends readonly unknown[]>(...tupleGuards: GuardSchemaOf<T>): Guard<T>;
7
7
  export declare function isRecordOf<K extends ObjectKey>(keyGuard: Guard<K>): Guard<Record<K, unknown>>;
8
8
  export declare function isRecordOf<K extends ObjectKey, V>(keyGuard: Guard<K>, valueGuard: Guard<V>): Guard<Record<K, V>>;
9
- export declare function isObjectOf<O extends object>(schema: GuardSchemaOf<O>): O extends unknown[] ? never : {} extends O ? never : Guard<O>;
9
+ type IsObjectOfGuard<O extends object> = O extends unknown[] ? never : {} extends O ? never : Guard<O>;
10
+ export declare function isObjectOf<O extends object>(schema: GuardSchemaOf<O>, exactKeys?: boolean): IsObjectOfGuard<O>;
10
11
  export {};
@@ -1,6 +1,4 @@
1
- function objectKeys(obj) {
2
- return Object.getOwnPropertyNames(obj).concat(Object.getOwnPropertySymbols(obj));
3
- }
1
+ import { objectKeys } from "./helpers.js";
4
2
  export const isAnyArray = (value) => Array.isArray(value);
5
3
  export const isAnyRecord = (value) => value != null && typeof value === "object" && !Array.isArray(value);
6
4
  export function isArrayOf(guard) {
@@ -29,9 +27,10 @@ export function isRecordOf(keyGuard, valueGuard) {
29
27
  !Array.isArray(value) &&
30
28
  objectKeys(value).every((key) => keyGuard(key) && (valueGuard?.(value[key]) ?? true));
31
29
  }
32
- export function isObjectOf(schema) {
33
- if (schema == null || typeof schema !== "object") {
34
- throw new TypeError(`isObjectOf expects a guard schema object. Got instead: ${schema}`);
30
+ export function isObjectOf(schema, exactKeys = false) {
31
+ const schemaUnknown = schema;
32
+ if (schemaUnknown == null || typeof schemaUnknown !== "object") {
33
+ throw new TypeError(`isObjectOf expects a guard schema object. Got instead: ${schemaUnknown}`);
35
34
  }
36
35
  const schemaKeys = objectKeys(schema);
37
36
  if (Array.isArray(schema) ||
@@ -44,6 +43,7 @@ export function isObjectOf(schema) {
44
43
  return ((value) => value != null &&
45
44
  typeof value === "object" &&
46
45
  !Array.isArray(value) &&
46
+ (!exactKeys || schemaKeys.length === objectKeys(value).length) &&
47
47
  schemaKeys.every((key) => key in value && schema[key](value[key])));
48
48
  }
49
49
  //# sourceMappingURL=structures.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"structures.js","sourceRoot":"src/","sources":["structures.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"structures.js","sourceRoot":"src/","sources":["structures.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,UAAU,EAAE,MAAM,cAAc,CAAC;AAGpE,MAAM,CAAC,MAAM,UAAU,GAAqB,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAE5E,MAAM,CAAC,MAAM,WAAW,GAAsC,CAC5D,KAAK,EACgC,EAAE,CACvC,KAAK,IAAI,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAEtE,MAAM,UAAU,SAAS,CAAI,KAAe;IAC1C,IAAI,OAAO,KAAK,KAAK,UAAU,EAAE,CAAC;QAChC,MAAM,IAAI,SAAS,CACjB,qDAAqD,KAAK,EAAE,CAC7D,CAAC;IACJ,CAAC;IAED,OAAO,CAAC,KAAK,EAAgB,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AAC7E,CAAC;AAED,MAAM,UAAU,SAAS,CACvB,GAAG,WAA6B;IAEhC,IAAI,WAAW,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,KAAK,KAAK,UAAU,CAAC,EAAE,CAAC;QAC7D,MAAM,IAAI,SAAS,CACjB,oDAAoD,IAAI,CAAC,SAAS,CAChE,WAAW,CACZ,EAAE,CACJ,CAAC;IACJ,CAAC;IAED,OAAO,CAAC,KAAK,EAAc,EAAE,CAC3B,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QACpB,KAAK,CAAC,MAAM,KAAK,WAAW,CAAC,MAAM;QACnC,WAAW,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACrD,CAAC;AASD,MAAM,UAAU,UAAU,CACxB,QAAkB,EAClB,UAAqB;IAErB,IAAI,OAAO,QAAQ,KAAK,UAAU,EAAE,CAAC;QACnC,MAAM,IAAI,SAAS,CACjB,+DAA+D,QAAQ,EAAE,CAC1E,CAAC;IACJ,CAAC;SAAM,IAAI,UAAU,IAAI,IAAI,IAAI,OAAO,UAAU,KAAK,UAAU,EAAE,CAAC;QAClE,MAAM,IAAI,SAAS,CACjB,2EAA2E,UAAU,EAAE,CACxF,CAAC;IACJ,CAAC;IAED,OAAO,CAAC,KAAK,EAAyB,EAAE,CACtC,KAAK,IAAI,IAAI;QACb,OAAO,KAAK,KAAK,QAAQ;QACzB,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QACrB,UAAU,CAAC,KAAK,CAAC,CAAC,KAAK,CACrB,CAAC,GAAG,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAC7D,CAAC;AACN,CAAC;AASD,MAAM,UAAU,UAAU,CACxB,MAAwB,EACxB,YAAqB,KAAK;IAE1B,MAAM,aAAa,GAAY,MAAM,CAAC;IACtC,IAAI,aAAa,IAAI,IAAI,IAAI,OAAO,aAAa,KAAK,QAAQ,EAAE,CAAC;QAC/D,MAAM,IAAI,SAAS,CACjB,0DAA0D,aAAa,EAAE,CAC1E,CAAC;IACJ,CAAC;IAED,MAAM,UAAU,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;IACtC,IACE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;QACrB,UAAU,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,MAAM,CAAC,GAAG,CAAC,KAAK,UAAU,CAAC,EAC3D,CAAC;QACD,MAAM,IAAI,SAAS,CACjB,yDAAyD,IAAI,CAAC,SAAS,CACrE,MAAM,CACP,EAAE,CACJ,CAAC;IACJ,CAAC;SAAM,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IACzD,CAAC;IAED,OAAO,CAAC,CAAC,KAAK,EAAc,EAAE,CAC5B,KAAK,IAAI,IAAI;QACb,OAAO,KAAK,KAAK,QAAQ;QACzB,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QACrB,CAAC,CAAC,SAAS,IAAI,UAAU,CAAC,MAAM,KAAK,UAAU,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC;QAC9D,UAAU,CAAC,KAAK,CACd,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,IAAI,KAAK,IAAI,MAAM,CAAC,GAAG,CAAC,CAAE,KAAW,CAAC,GAAG,CAAC,CAAC,CACxD,CAAuB,CAAC;AAC7B,CAAC"}
package/dist/types.d.ts CHANGED
@@ -1,5 +1,2 @@
1
1
  export type Guard<T> = (value: unknown) => value is T;
2
- export type GuardSchemaOf<O extends object> = {
3
- [K in keyof O]: Guard<O[K]>;
4
- };
5
2
  export type TypeFromGuard<G extends Guard<unknown>> = G extends Guard<infer T> ? T : never;
package/package.json CHANGED
@@ -8,7 +8,7 @@
8
8
  "type": "module",
9
9
  "types": "dist/index.d.ts",
10
10
  "homepage": "https://github.com/eniallator/Deep-Guards",
11
- "version": "1.0.3",
11
+ "version": "1.0.5",
12
12
  "scripts": {
13
13
  "test": "jest",
14
14
  "build": "tsc",
package/src/compound.ts CHANGED
@@ -1,4 +1,5 @@
1
- import { Guard, GuardSchemaOf } from "./types";
1
+ import { GuardSchemaOf, objectKeys } from "./helpers.js";
2
+ import { Guard } from "./types.js";
2
3
 
3
4
  export function isOptional<T>(guard: Guard<T>): Guard<T | undefined> {
4
5
  if (typeof guard !== "function") {
@@ -75,25 +76,31 @@ export function isIntersectionOf<T extends readonly unknown[]>(
75
76
  guards.every((guard) => guard(value));
76
77
  }
77
78
 
78
- function isEqual<T>(a: T, b: unknown): b is T {
79
+ function objectEntriesChecks<T extends object>(a: T, b: object): b is T {
80
+ const aKeys = objectKeys(a);
81
+ const bKeySet = new Set(objectKeys(b));
79
82
  return (
80
- a === b ||
81
- (a != null &&
82
- b != null &&
83
- typeof a === "object" &&
84
- typeof b === "object" &&
85
- (Array.isArray(a)
86
- ? Array.isArray(b) &&
87
- a.length === b.length &&
88
- a.every((v, i) => isEqual(v, b[i]))
89
- : Object.keys(a).length === Object.keys(b).length &&
90
- Object.entries(a).every(
91
- ([k, v]) => k in b && isEqual(v, (b as Record<string, unknown>)[k])
92
- )))
83
+ aKeys.length === bKeySet.size &&
84
+ aKeys.every((k) => bKeySet.has(k) && isExact(a[k], true)(b[k]))
93
85
  );
94
86
  }
95
87
 
96
88
  export function isExact<const T>(expected: T, deep: boolean = true): Guard<T> {
97
89
  return (value): value is T =>
98
- deep ? isEqual(expected, value) : expected === value;
90
+ // Shallow checks
91
+ expected === value ||
92
+ (Number.isNaN(expected) && Number.isNaN(value)) ||
93
+ (deep &&
94
+ (Array.isArray(expected)
95
+ ? // Array checks
96
+ Array.isArray(value) &&
97
+ expected.length === value.length &&
98
+ expected.every((v, i) => isExact(v, true)(value[i]))
99
+ : // Object checks
100
+ expected != null &&
101
+ value != null &&
102
+ typeof expected === "object" &&
103
+ typeof value === "object" &&
104
+ !Array.isArray(value) &&
105
+ objectEntriesChecks(expected, value)));
99
106
  }
package/src/errors.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Guard } from "./types";
1
+ import { Guard } from "./types.js";
2
2
 
3
3
  export class GuardError extends Error {
4
4
  name = "GuardError";
package/src/helpers.ts ADDED
@@ -0,0 +1,22 @@
1
+ import { Guard } from "./types.js";
2
+
3
+ export type GuardSchemaOf<O extends object> = {
4
+ [K in keyof O]: Guard<O[K]>;
5
+ };
6
+
7
+ export type ObjectKey = string | number | symbol;
8
+
9
+ export const objectKeys = <K extends ObjectKey>(obj: Record<K, unknown>): K[] =>
10
+ (Object.getOwnPropertyNames(obj) as K[]).concat(
11
+ Object.getOwnPropertySymbols(obj) as K[]
12
+ );
13
+
14
+ export function omit<O extends object>(
15
+ obj: O,
16
+ key: keyof O
17
+ ): { [K in keyof O as K extends typeof key ? never : K]: O[K] } {
18
+ const omitted = { ...obj };
19
+ // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
20
+ delete omitted[key];
21
+ return omitted;
22
+ }
package/src/index.ts CHANGED
@@ -1,6 +1,6 @@
1
- export * from "./compound";
2
- export * from "./errors";
3
- export * from "./macros";
4
- export * from "./primitives";
5
- export * from "./structures";
6
- export * from "./types";
1
+ export * from "./compound.js";
2
+ export * from "./errors.js";
3
+ export * from "./macros.js";
4
+ export * from "./primitives.js";
5
+ export * from "./structures.js";
6
+ export * from "./types.js";
package/src/macros.ts CHANGED
@@ -1,11 +1,28 @@
1
- import { isExact, isIntersectionOf } from "./compound";
2
- import { isObjectOf } from "./structures";
3
- import { Guard } from "./types";
1
+ import { isExact } from "./compound.js";
2
+ import { ObjectKey, omit } from "./helpers.js";
3
+ import { isObjectOf } from "./structures.js";
4
+ import { Guard } from "./types.js";
4
5
 
5
- export const isDiscriminatedObjectOf = <T extends string, O extends object>(
6
- type: T,
7
- guard: Guard<O>
8
- ): Guard<{ type: T } & O> =>
9
- isIntersectionOf(isObjectOf({ type: isExact(type) }), guard) satisfies Guard<
10
- { type: T } & O
11
- >;
6
+ export function isDiscriminatedObjectOf<
7
+ const T extends string,
8
+ O extends object
9
+ >(value: T, guard: Guard<O>): Guard<{ type: T } & O>;
10
+ export function isDiscriminatedObjectOf<
11
+ const T extends string,
12
+ O extends object,
13
+ const K extends ObjectKey
14
+ >(value: T, guard: Guard<O>, key: K): Guard<{ [S in K]: T } & O>;
15
+ export function isDiscriminatedObjectOf<
16
+ const T extends string,
17
+ O extends object
18
+ >(
19
+ value: T,
20
+ guard: Guard<O>,
21
+ key: ObjectKey = "type"
22
+ ): Guard<{ [S in typeof key]: T } & O> {
23
+ const discriminatorGuard = isObjectOf({ [key]: isExact(value) }) as Guard<{
24
+ [S in typeof key]: T;
25
+ }>;
26
+ return (value): value is { [S in typeof key]: T } & O =>
27
+ discriminatorGuard(value) && guard(omit(value, key));
28
+ }
package/src/primitives.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Guard } from "./types";
1
+ import { Guard } from "./types.js";
2
2
 
3
3
  export const isUnknown: Guard<unknown> = (_value): _value is unknown => true;
4
4
 
package/src/structures.ts CHANGED
@@ -1,12 +1,5 @@
1
- import { Guard, GuardSchemaOf } from "./types";
2
-
3
- type ObjectKey = string | number | symbol;
4
-
5
- function objectKeys<K extends ObjectKey>(obj: Record<K, unknown>): K[] {
6
- return (Object.getOwnPropertyNames(obj) as K[]).concat(
7
- Object.getOwnPropertySymbols(obj) as K[]
8
- );
9
- }
1
+ import { GuardSchemaOf, ObjectKey, objectKeys } from "./helpers.js";
2
+ import { Guard } from "./types.js";
10
3
 
11
4
  export const isAnyArray: Guard<unknown[]> = (value) => Array.isArray(value);
12
5
 
@@ -72,12 +65,21 @@ export function isRecordOf<K extends ObjectKey, V>(
72
65
  );
73
66
  }
74
67
 
68
+ type IsObjectOfGuard<O extends object> = O extends unknown[]
69
+ ? never
70
+ : // eslint-disable-next-line @typescript-eslint/no-empty-object-type
71
+ {} extends O
72
+ ? never
73
+ : Guard<O>;
74
+
75
75
  export function isObjectOf<O extends object>(
76
- schema: GuardSchemaOf<O>
77
- ): O extends unknown[] ? never : {} extends O ? never : Guard<O> {
78
- if (schema == null || typeof schema !== "object") {
76
+ schema: GuardSchemaOf<O>,
77
+ exactKeys: boolean = false
78
+ ): IsObjectOfGuard<O> {
79
+ const schemaUnknown: unknown = schema;
80
+ if (schemaUnknown == null || typeof schemaUnknown !== "object") {
79
81
  throw new TypeError(
80
- `isObjectOf expects a guard schema object. Got instead: ${schema}`
82
+ `isObjectOf expects a guard schema object. Got instead: ${schemaUnknown}`
81
83
  );
82
84
  }
83
85
 
@@ -99,7 +101,8 @@ export function isObjectOf<O extends object>(
99
101
  value != null &&
100
102
  typeof value === "object" &&
101
103
  !Array.isArray(value) &&
104
+ (!exactKeys || schemaKeys.length === objectKeys(value).length) &&
102
105
  schemaKeys.every(
103
106
  (key) => key in value && schema[key]((value as O)[key])
104
- )) as O extends unknown[] ? never : {} extends O ? never : Guard<O>;
107
+ )) as IsObjectOfGuard<O>;
105
108
  }
package/src/types.ts CHANGED
@@ -1,9 +1,5 @@
1
1
  export type Guard<T> = (value: unknown) => value is T;
2
2
 
3
- export type GuardSchemaOf<O extends object> = {
4
- [K in keyof O]: Guard<O[K]>;
5
- };
6
-
7
3
  export type TypeFromGuard<G extends Guard<unknown>> = G extends Guard<infer T>
8
4
  ? T
9
5
  : never;
@@ -9,7 +9,7 @@ import {
9
9
  isOptional,
10
10
  isString,
11
11
  isUnionOf,
12
- } from "../src";
12
+ } from "../dist";
13
13
 
14
14
  describe("isOptional", () => {
15
15
  const guard = isOptional(isString);
@@ -1,15 +1,38 @@
1
- import { isDiscriminatedObjectOf, isObjectOf, isString } from "../src";
1
+ import { isDiscriminatedObjectOf, isObjectOf, isString } from "../dist";
2
2
 
3
3
  describe("isDiscriminatedObjectOf", () => {
4
- const guard = isDiscriminatedObjectOf("foo", isObjectOf({ bar: isString }));
4
+ describe("no key override", () => {
5
+ const guard = isDiscriminatedObjectOf(
6
+ "foo",
7
+ isObjectOf({ bar: isString }, true)
8
+ );
5
9
 
6
- it("succeeds for an object of the value", () => {
7
- expect(guard({ type: "foo", bar: "baz" })).toBe(true);
10
+ it("succeeds for an object of the value", () => {
11
+ expect(guard({ type: "foo", bar: "baz" })).toBe(true);
12
+ });
13
+
14
+ it("fails for any other value", () => {
15
+ expect(guard({ type: "foo" })).toBe(false);
16
+ expect(guard({ bar: "baz" })).toBe(false);
17
+ expect(guard(1)).toBe(false);
18
+ });
8
19
  });
9
20
 
10
- it("fails for any other value", () => {
11
- expect(guard({ type: "foo" })).toBe(false);
12
- expect(guard({ bar: "baz" })).toBe(false);
13
- expect(guard(1)).toBe(false);
21
+ describe("overriding key", () => {
22
+ const guard = isDiscriminatedObjectOf(
23
+ "foo",
24
+ isObjectOf({ bar: isString }, true),
25
+ "test"
26
+ );
27
+
28
+ it("succeeds for an object of the value", () => {
29
+ expect(guard({ test: "foo", bar: "baz" })).toBe(true);
30
+ });
31
+
32
+ it("fails for any other value", () => {
33
+ expect(guard({ test: "foo" })).toBe(false);
34
+ expect(guard({ bar: "baz" })).toBe(false);
35
+ expect(guard(1)).toBe(false);
36
+ });
14
37
  });
15
38
  });
@@ -7,7 +7,7 @@ import {
7
7
  isString,
8
8
  isUndefined,
9
9
  isUnknown,
10
- } from "../src";
10
+ } from "../dist";
11
11
 
12
12
  describe("isUnknown", () => {
13
13
  it("succeeds for any value", () => {
@@ -9,7 +9,7 @@ import {
9
9
  isString,
10
10
  isSymbol,
11
11
  isTupleOf,
12
- } from "../src";
12
+ } from "../dist";
13
13
 
14
14
  describe("isAnyArray", () => {
15
15
  it("succeeds for an array", () => {
@@ -65,35 +65,80 @@ describe("isTupleOf", () => {
65
65
  });
66
66
 
67
67
  describe("isObjectOf", () => {
68
- const barSymbol = Symbol("bar");
69
- const guard = isObjectOf({
70
- foo: isString,
71
- [barSymbol]: isNumber,
72
- baz: isObjectOf({
73
- qux: isSymbol,
74
- }),
75
- });
68
+ describe("leaky", () => {
69
+ const barSymbol = Symbol("bar");
70
+ const guard = isObjectOf({
71
+ foo: isString,
72
+ [barSymbol]: isNumber,
73
+ baz: isObjectOf({
74
+ qux: isSymbol,
75
+ }),
76
+ });
77
+
78
+ it("succeeds for an object of the value", () => {
79
+ expect(
80
+ guard({
81
+ foo: "hello",
82
+ [barSymbol]: 1,
83
+ baz: { qux: Symbol("world!") },
84
+ quux: "this should not be checked",
85
+ })
86
+ ).toBe(true);
87
+ });
76
88
 
77
- it("succeeds for an object of the value", () => {
78
- expect(
79
- guard({
80
- foo: "hello",
81
- [barSymbol]: 1,
82
- baz: { qux: Symbol("world!") },
83
- quux: "this should not be checked",
84
- })
85
- ).toBe(true);
89
+ it("fails for any other value", () => {
90
+ expect(
91
+ guard({
92
+ foo: "hello",
93
+ [barSymbol]: "FAIL",
94
+ baz: { qux: Symbol("world!") },
95
+ })
96
+ ).toBe(false);
97
+ expect(guard(1)).toBe(false);
98
+ });
86
99
  });
87
100
 
88
- it("fails for any other value", () => {
89
- expect(
90
- guard({
91
- foo: "hello",
92
- [barSymbol]: "FAIL",
93
- baz: { qux: Symbol("world!") },
94
- })
95
- ).toBe(false);
96
- expect(guard(1)).toBe(false);
101
+ describe("exact keys", () => {
102
+ const barSymbol = Symbol("bar");
103
+ const guard = isObjectOf(
104
+ {
105
+ foo: isString,
106
+ [barSymbol]: isNumber,
107
+ baz: isObjectOf({
108
+ qux: isSymbol,
109
+ }),
110
+ },
111
+ true
112
+ );
113
+
114
+ it("succeeds for an object of the value", () => {
115
+ expect(
116
+ guard({
117
+ foo: "hello",
118
+ [barSymbol]: 1,
119
+ baz: { qux: Symbol("world!") },
120
+ })
121
+ ).toBe(true);
122
+ });
123
+
124
+ it("fails for any other value", () => {
125
+ expect(
126
+ guard({
127
+ foo: "hello",
128
+ [barSymbol]: 1,
129
+ baz: { qux: Symbol("world!") },
130
+ quux: "this should be checked",
131
+ })
132
+ ).toBe(false);
133
+ expect(
134
+ guard({
135
+ foo: "hello",
136
+ [barSymbol]: "FAIL",
137
+ baz: { qux: Symbol("world!") },
138
+ })
139
+ ).toBe(false);
140
+ expect(guard(1)).toBe(false);
141
+ });
97
142
  });
98
143
  });
99
144