@oscarpalmer/jhunal 0.2.0 → 0.4.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.
Files changed (42) hide show
  1. package/README.md +2 -0
  2. package/dist/helpers.cjs +45 -0
  3. package/dist/helpers.js +41 -0
  4. package/dist/index.cjs +4 -106
  5. package/dist/index.js +1 -107
  6. package/dist/is.cjs +19 -0
  7. package/dist/is.js +14 -0
  8. package/dist/model.cjs +2 -0
  9. package/dist/model.js +1 -0
  10. package/dist/schematic.cjs +17 -0
  11. package/dist/schematic.js +13 -0
  12. package/dist/validation/schema.validation.cjs +54 -0
  13. package/dist/validation/schema.validation.js +49 -0
  14. package/dist/validation/type.validation.cjs +33 -0
  15. package/dist/validation/type.validation.js +29 -0
  16. package/dist/validation/value.validation.cjs +35 -0
  17. package/dist/validation/value.validation.js +31 -0
  18. package/package.json +1 -1
  19. package/src/helpers.ts +49 -0
  20. package/src/index.ts +2 -282
  21. package/src/is.ts +22 -0
  22. package/src/model.ts +168 -0
  23. package/src/schematic.ts +30 -0
  24. package/src/validation/schema.validation.ts +63 -0
  25. package/src/validation/type.validation.ts +34 -0
  26. package/src/validation/value.validation.ts +46 -0
  27. package/types/helpers.d.cts +43 -0
  28. package/types/helpers.d.ts +2 -0
  29. package/types/index.d.cts +25 -14
  30. package/types/index.d.ts +2 -75
  31. package/types/is.d.cts +15 -0
  32. package/types/is.d.ts +3 -0
  33. package/types/model.d.cts +365 -0
  34. package/types/model.d.ts +91 -0
  35. package/types/schematic.d.cts +360 -0
  36. package/types/schematic.d.ts +9 -0
  37. package/types/validation/schema.validation.d.cts +55 -0
  38. package/types/validation/schema.validation.d.ts +3 -0
  39. package/types/validation/type.validation.d.cts +43 -0
  40. package/types/validation/type.validation.d.ts +2 -0
  41. package/types/validation/value.validation.d.cts +43 -0
  42. package/types/validation/value.validation.d.ts +2 -0
package/types/index.d.cts CHANGED
@@ -270,20 +270,25 @@ export type UnionToTuple<T, L = LastOfUnion<T>> = IsNever<T> extends false ? [
270
270
  L
271
271
  ] : [
272
272
  ];
273
+ export type AutoInferExclude = "date-like" | "numerical";
273
274
  export type GetKey<Value> = {
274
- [Key in keyof Values]: Value extends Values[Key] ? Key : never;
275
- }[keyof Values];
275
+ [Key in Exclude<ValueKey, AutoInferExclude>]: Value extends Values[Key] ? Key : never;
276
+ }[Exclude<ValueKey, AutoInferExclude>] extends infer SpecificKey ? SpecificKey extends never ? {
277
+ [Key in AutoInferExclude]: Value extends Values[Key] ? Key : never;
278
+ }[AutoInferExclude] : SpecificKey : never;
276
279
  export type GetTypes<Value extends unknown[]> = Value extends [
277
- infer Single
278
- ] ? Single : Value;
280
+ infer Type
281
+ ] ? Type : Value;
279
282
  export type GetType<Value> = GetTypes<UnionToTuple<GetKey<Value>>>;
280
- export type InferProperty<Value> = Value extends Property ? Value["type"] extends keyof Values ? Values[Value["type"]] : Value["type"] extends (keyof Values)[] ? Values[Value["type"][number]] : never : never;
281
- export type InferValue<Value> = Value extends keyof Values ? Values[Value] : Value extends (keyof Values)[] ? Values[Value[number]] : never;
282
- export type Inferred<Model extends Schema> = {
283
+ export type InferProperty<Value> = Value extends Property ? InferPropertyType<Value["type"]> : never;
284
+ export type InferPropertyType<Value> = Value extends (infer Type)[] ? InferPropertyTypeValue<Type>[] : InferPropertyTypeValue<Value>;
285
+ export type InferPropertyTypeValue<Value> = Value extends PropertyType ? Value extends Schema ? Inferred<Value> : Value extends Schematic<infer Model> ? Model : Value extends ValueKey ? Values[Value] : Value extends (infer NestedElementType)[] ? InferPropertyTypeValue<NestedElementType>[] : Value : never;
286
+ export type InferValue<Value> = Value extends ValueKey ? Values[Value] : Value extends ValueKey[] ? Values[Value[number]] : never;
287
+ export type Inferred<Model extends Schema> = Simplify<{
283
288
  [Key in InferredRequiredProperties<Model>]: Model[Key] extends Property ? InferProperty<Model[Key]> : InferValue<Model[Key]>;
284
289
  } & {
285
290
  [Key in InferredOptionalProperties<Model>]?: Model[Key] extends Property ? InferProperty<Model[Key]> : never;
286
- };
291
+ }>;
287
292
  export type InferredOptionalProperties<Model extends Schema> = {
288
293
  [Key in keyof Model]: Model[Key] extends Property ? Model[Key]["required"] extends false ? Key : never : never;
289
294
  }[keyof Model];
@@ -296,8 +301,9 @@ export type OptionalProperty<Type> = {
296
301
  };
297
302
  export type Property = {
298
303
  required?: boolean;
299
- type: keyof Values | (keyof Values)[];
304
+ type: PropertyType | PropertyType[];
300
305
  };
306
+ export type PropertyType = Schema | Schematic<unknown> | ValueKey;
301
307
  export type RequiredProperty<Type> = {
302
308
  required: true;
303
309
  type: GetType<Type>;
@@ -305,7 +311,9 @@ export type RequiredProperty<Type> = {
305
311
  /**
306
312
  * A schema for validating objects
307
313
  */
308
- export type Schema = Record<string, keyof Values | (keyof Values)[] | Property>;
314
+ export type Schema = {
315
+ [key: string]: Property | ValueKey | ValueKey[];
316
+ };
309
317
  /**
310
318
  * A schematic for validating objects
311
319
  */
@@ -324,26 +332,29 @@ export type TypedSchema<Model extends Typed> = Simplify<{
324
332
  } & {
325
333
  [Key in OptionalKeysOf<Model>]: OptionalProperty<Model[Key]>;
326
334
  }>;
335
+ export type ValueKey = keyof Values;
327
336
  export type Values = {
328
337
  array: unknown[];
329
338
  bigint: bigint;
330
339
  boolean: boolean;
331
340
  date: Date;
341
+ "date-like": number | string | Date;
332
342
  function: Function;
333
343
  null: null;
334
344
  number: number;
345
+ numerical: bigint | number;
335
346
  object: object;
336
347
  string: string;
337
348
  symbol: symbol;
338
349
  undefined: undefined;
339
350
  };
340
- /**
341
- * Create a schematic from a typed schema
342
- */
343
- export declare function schematic<Model extends Typed>(schema: TypedSchema<Model>): Schematic<Model>;
344
351
  /**
345
352
  * Create a schematic from a schema
346
353
  */
347
354
  export declare function schematic<Model extends Schema>(schema: Model): Schematic<Inferred<Model>>;
355
+ /**
356
+ * Create a schematic from a typed schema
357
+ */
358
+ export declare function schematic<Model extends Typed>(schema: TypedSchema<Model>): Schematic<Model>;
348
359
 
349
360
  export {};
package/types/index.d.ts CHANGED
@@ -1,75 +1,2 @@
1
- import type { OptionalKeysOf, RequiredKeysOf, Simplify, UnionToTuple } from 'type-fest';
2
- type GetKey<Value> = {
3
- [Key in keyof Values]: Value extends Values[Key] ? Key : never;
4
- }[keyof Values];
5
- type GetTypes<Value extends unknown[]> = Value extends [infer Single] ? Single : Value;
6
- type GetType<Value> = GetTypes<UnionToTuple<GetKey<Value>>>;
7
- type InferProperty<Value> = Value extends Property ? Value['type'] extends keyof Values ? Values[Value['type']] : Value['type'] extends (keyof Values)[] ? Values[Value['type'][number]] : never : never;
8
- type InferValue<Value> = Value extends keyof Values ? Values[Value] : Value extends (keyof Values)[] ? Values[Value[number]] : never;
9
- type Inferred<Model extends Schema> = {
10
- [Key in InferredRequiredProperties<Model>]: Model[Key] extends Property ? InferProperty<Model[Key]> : InferValue<Model[Key]>;
11
- } & {
12
- [Key in InferredOptionalProperties<Model>]?: Model[Key] extends Property ? InferProperty<Model[Key]> : never;
13
- };
14
- type InferredOptionalProperties<Model extends Schema> = {
15
- [Key in keyof Model]: Model[Key] extends Property ? Model[Key]['required'] extends false ? Key : never : never;
16
- }[keyof Model];
17
- type InferredRequiredProperties<Model extends Schema> = {
18
- [Key in keyof Model]: Model[Key] extends Property ? Model[Key]['required'] extends false ? never : Key : Key;
19
- }[keyof Model];
20
- type OptionalProperty<Type> = {
21
- required: false;
22
- type: GetType<Type>;
23
- };
24
- type Property = {
25
- required?: boolean;
26
- type: keyof Values | (keyof Values)[];
27
- };
28
- type RequiredProperty<Type> = {
29
- required: true;
30
- type: GetType<Type>;
31
- };
32
- /**
33
- * A schema for validating objects
34
- */
35
- export type Schema = Record<string, keyof Values | (keyof Values)[] | Property>;
36
- /**
37
- * A schematic for validating objects
38
- */
39
- export type Schematic<Model> = {
40
- /**
41
- * Does the value match the schema?
42
- */
43
- is(value: unknown): value is Model;
44
- };
45
- type Typed = Record<string, unknown>;
46
- /**
47
- * A typed schema for validating objects
48
- */
49
- export type TypedSchema<Model extends Typed> = Simplify<{
50
- [Key in RequiredKeysOf<Model>]: GetType<Model[Key]> | RequiredProperty<Model[Key]>;
51
- } & {
52
- [Key in OptionalKeysOf<Model>]: OptionalProperty<Model[Key]>;
53
- }>;
54
- type Values = {
55
- array: unknown[];
56
- bigint: bigint;
57
- boolean: boolean;
58
- date: Date;
59
- function: Function;
60
- null: null;
61
- number: number;
62
- object: object;
63
- string: string;
64
- symbol: symbol;
65
- undefined: undefined;
66
- };
67
- /**
68
- * Create a schematic from a typed schema
69
- */
70
- export declare function schematic<Model extends Typed>(schema: TypedSchema<Model>): Schematic<Model>;
71
- /**
72
- * Create a schematic from a schema
73
- */
74
- export declare function schematic<Model extends Schema>(schema: Model): Schematic<Inferred<Model>>;
75
- export {};
1
+ export type { Schema, Schematic, TypedSchema } from './model';
2
+ export * from './schematic';
package/types/is.d.cts ADDED
@@ -0,0 +1,15 @@
1
+ // Generated by dts-bundle-generator v9.5.1
2
+
3
+ /**
4
+ * A schematic for validating objects
5
+ */
6
+ export type Schematic<Model> = {
7
+ /**
8
+ * Does the value match the schema?
9
+ */
10
+ is(value: unknown): value is Model;
11
+ };
12
+ export declare function isDateLike(value: unknown): value is Date;
13
+ export declare function isSchematic(value: unknown): value is Schematic<never>;
14
+
15
+ export {};
package/types/is.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ import type { Schematic } from './model';
2
+ export declare function isDateLike(value: unknown): value is Date;
3
+ export declare function isSchematic(value: unknown): value is Schematic<never>;
@@ -0,0 +1,365 @@
1
+ // Generated by dts-bundle-generator v9.5.1
2
+
3
+ /**
4
+ Convert a union type to an intersection type using [distributive conditional types](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#distributive-conditional-types).
5
+
6
+ Inspired by [this Stack Overflow answer](https://stackoverflow.com/a/50375286/2172153).
7
+
8
+ @example
9
+ ```
10
+ import type {UnionToIntersection} from 'type-fest';
11
+
12
+ type Union = {the(): void} | {great(arg: string): void} | {escape: boolean};
13
+
14
+ type Intersection = UnionToIntersection<Union>;
15
+ //=> {the(): void; great(arg: string): void; escape: boolean};
16
+ ```
17
+
18
+ A more applicable example which could make its way into your library code follows.
19
+
20
+ @example
21
+ ```
22
+ import type {UnionToIntersection} from 'type-fest';
23
+
24
+ class CommandOne {
25
+ commands: {
26
+ a1: () => undefined,
27
+ b1: () => undefined,
28
+ }
29
+ }
30
+
31
+ class CommandTwo {
32
+ commands: {
33
+ a2: (argA: string) => undefined,
34
+ b2: (argB: string) => undefined,
35
+ }
36
+ }
37
+
38
+ const union = [new CommandOne(), new CommandTwo()].map(instance => instance.commands);
39
+ type Union = typeof union;
40
+ //=> {a1(): void; b1(): void} | {a2(argA: string): void; b2(argB: string): void}
41
+
42
+ type Intersection = UnionToIntersection<Union>;
43
+ //=> {a1(): void; b1(): void; a2(argA: string): void; b2(argB: string): void}
44
+ ```
45
+
46
+ @category Type
47
+ */
48
+ export type UnionToIntersection<Union> = (
49
+ // `extends unknown` is always going to be the case and is used to convert the
50
+ // `Union` into a [distributive conditional
51
+ // type](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#distributive-conditional-types).
52
+ Union extends unknown ? (distributedUnion: Union) => void : never) extends ((mergedIntersection: infer Intersection) => void) ? Intersection & Union : never;
53
+ /**
54
+ Extract all optional keys from the given type.
55
+
56
+ This is useful when you want to create a new type that contains different type values for the optional keys only.
57
+
58
+ @example
59
+ ```
60
+ import type {OptionalKeysOf, Except} from 'type-fest';
61
+
62
+ interface User {
63
+ name: string;
64
+ surname: string;
65
+
66
+ luckyNumber?: number;
67
+ }
68
+
69
+ const REMOVE_FIELD = Symbol('remove field symbol');
70
+ type UpdateOperation<Entity extends object> = Except<Partial<Entity>, OptionalKeysOf<Entity>> & {
71
+ [Key in OptionalKeysOf<Entity>]?: Entity[Key] | typeof REMOVE_FIELD;
72
+ };
73
+
74
+ const update1: UpdateOperation<User> = {
75
+ name: 'Alice'
76
+ };
77
+
78
+ const update2: UpdateOperation<User> = {
79
+ name: 'Bob',
80
+ luckyNumber: REMOVE_FIELD
81
+ };
82
+ ```
83
+
84
+ @category Utilities
85
+ */
86
+ export type OptionalKeysOf<BaseType extends object> = BaseType extends unknown // For distributing `BaseType`
87
+ ? (keyof {
88
+ [Key in keyof BaseType as BaseType extends Record<Key, BaseType[Key]> ? never : Key]: never;
89
+ }) & (keyof BaseType) // Intersect with `keyof BaseType` to ensure result of `OptionalKeysOf<BaseType>` is always assignable to `keyof BaseType`
90
+ : never; // Should never happen
91
+ /**
92
+ Extract all required keys from the given type.
93
+
94
+ This is useful when you want to create a new type that contains different type values for the required keys only or use the list of keys for validation purposes, etc...
95
+
96
+ @example
97
+ ```
98
+ import type {RequiredKeysOf} from 'type-fest';
99
+
100
+ declare function createValidation<Entity extends object, Key extends RequiredKeysOf<Entity> = RequiredKeysOf<Entity>>(field: Key, validator: (value: Entity[Key]) => boolean): ValidatorFn;
101
+
102
+ interface User {
103
+ name: string;
104
+ surname: string;
105
+
106
+ luckyNumber?: number;
107
+ }
108
+
109
+ const validator1 = createValidation<User>('name', value => value.length < 25);
110
+ const validator2 = createValidation<User>('surname', value => value.length < 25);
111
+ ```
112
+
113
+ @category Utilities
114
+ */
115
+ export type RequiredKeysOf<BaseType extends object> = BaseType extends unknown // For distributing `BaseType`
116
+ ? Exclude<keyof BaseType, OptionalKeysOf<BaseType>> : never; // Should never happen
117
+ /**
118
+ Returns a boolean for whether the given type is `never`.
119
+
120
+ @link https://github.com/microsoft/TypeScript/issues/31751#issuecomment-498526919
121
+ @link https://stackoverflow.com/a/53984913/10292952
122
+ @link https://www.zhenghao.io/posts/ts-never
123
+
124
+ Useful in type utilities, such as checking if something does not occur.
125
+
126
+ @example
127
+ ```
128
+ import type {IsNever, And} from 'type-fest';
129
+
130
+ // https://github.com/andnp/SimplyTyped/blob/master/src/types/strings.ts
131
+ type AreStringsEqual<A extends string, B extends string> =
132
+ And<
133
+ IsNever<Exclude<A, B>> extends true ? true : false,
134
+ IsNever<Exclude<B, A>> extends true ? true : false
135
+ >;
136
+
137
+ type EndIfEqual<I extends string, O extends string> =
138
+ AreStringsEqual<I, O> extends true
139
+ ? never
140
+ : void;
141
+
142
+ function endIfEqual<I extends string, O extends string>(input: I, output: O): EndIfEqual<I, O> {
143
+ if (input === output) {
144
+ process.exit(0);
145
+ }
146
+ }
147
+
148
+ endIfEqual('abc', 'abc');
149
+ //=> never
150
+
151
+ endIfEqual('abc', '123');
152
+ //=> void
153
+ ```
154
+
155
+ @category Type Guard
156
+ @category Utilities
157
+ */
158
+ export type IsNever<T> = [
159
+ T
160
+ ] extends [
161
+ never
162
+ ] ? true : false;
163
+ /**
164
+ Useful to flatten the type output to improve type hints shown in editors. And also to transform an interface into a type to aide with assignability.
165
+
166
+ @example
167
+ ```
168
+ import type {Simplify} from 'type-fest';
169
+
170
+ type PositionProps = {
171
+ top: number;
172
+ left: number;
173
+ };
174
+
175
+ type SizeProps = {
176
+ width: number;
177
+ height: number;
178
+ };
179
+
180
+ // In your editor, hovering over `Props` will show a flattened object with all the properties.
181
+ type Props = Simplify<PositionProps & SizeProps>;
182
+ ```
183
+
184
+ Sometimes it is desired to pass a value as a function argument that has a different type. At first inspection it may seem assignable, and then you discover it is not because the `value`'s type definition was defined as an interface. In the following example, `fn` requires an argument of type `Record<string, unknown>`. If the value is defined as a literal, then it is assignable. And if the `value` is defined as type using the `Simplify` utility the value is assignable. But if the `value` is defined as an interface, it is not assignable because the interface is not sealed and elsewhere a non-string property could be added to the interface.
185
+
186
+ If the type definition must be an interface (perhaps it was defined in a third-party npm package), then the `value` can be defined as `const value: Simplify<SomeInterface> = ...`. Then `value` will be assignable to the `fn` argument. Or the `value` can be cast as `Simplify<SomeInterface>` if you can't re-declare the `value`.
187
+
188
+ @example
189
+ ```
190
+ import type {Simplify} from 'type-fest';
191
+
192
+ interface SomeInterface {
193
+ foo: number;
194
+ bar?: string;
195
+ baz: number | undefined;
196
+ }
197
+
198
+ type SomeType = {
199
+ foo: number;
200
+ bar?: string;
201
+ baz: number | undefined;
202
+ };
203
+
204
+ const literal = {foo: 123, bar: 'hello', baz: 456};
205
+ const someType: SomeType = literal;
206
+ const someInterface: SomeInterface = literal;
207
+
208
+ function fn(object: Record<string, unknown>): void {}
209
+
210
+ fn(literal); // Good: literal object type is sealed
211
+ fn(someType); // Good: type is sealed
212
+ fn(someInterface); // Error: Index signature for type 'string' is missing in type 'someInterface'. Because `interface` can be re-opened
213
+ fn(someInterface as Simplify<SomeInterface>); // Good: transform an `interface` into a `type`
214
+ ```
215
+
216
+ @link https://github.com/microsoft/TypeScript/issues/15300
217
+ @see SimplifyDeep
218
+ @category Object
219
+ */
220
+ export type Simplify<T> = {
221
+ [KeyType in keyof T]: T[KeyType];
222
+ } & {};
223
+ /**
224
+ Returns the last element of a union type.
225
+
226
+ @example
227
+ ```
228
+ type Last = LastOfUnion<1 | 2 | 3>;
229
+ //=> 3
230
+ ```
231
+ */
232
+ export type LastOfUnion<T> = UnionToIntersection<T extends any ? () => T : never> extends () => (infer R) ? R : never;
233
+ /**
234
+ Convert a union type into an unordered tuple type of its elements.
235
+
236
+ "Unordered" means the elements of the tuple are not guaranteed to be in the same order as in the union type. The arrangement can appear random and may change at any time.
237
+
238
+ This can be useful when you have objects with a finite set of keys and want a type defining only the allowed keys, but do not want to repeat yourself.
239
+
240
+ @example
241
+ ```
242
+ import type {UnionToTuple} from 'type-fest';
243
+
244
+ type Numbers = 1 | 2 | 3;
245
+ type NumbersTuple = UnionToTuple<Numbers>;
246
+ //=> [1, 2, 3]
247
+ ```
248
+
249
+ @example
250
+ ```
251
+ import type {UnionToTuple} from 'type-fest';
252
+
253
+ const pets = {
254
+ dog: '🐶',
255
+ cat: '🐱',
256
+ snake: '🐍',
257
+ };
258
+
259
+ type Pet = keyof typeof pets;
260
+ //=> 'dog' | 'cat' | 'snake'
261
+
262
+ const petList = Object.keys(pets) as UnionToTuple<Pet>;
263
+ //=> ['dog', 'cat', 'snake']
264
+ ```
265
+
266
+ @category Array
267
+ */
268
+ export type UnionToTuple<T, L = LastOfUnion<T>> = IsNever<T> extends false ? [
269
+ ...UnionToTuple<Exclude<T, L>>,
270
+ L
271
+ ] : [
272
+ ];
273
+ export type AutoInferExclude = "date-like" | "numerical";
274
+ export type GetKey<Value> = {
275
+ [Key in Exclude<ValueKey, AutoInferExclude>]: Value extends Values[Key] ? Key : never;
276
+ }[Exclude<ValueKey, AutoInferExclude>] extends infer SpecificKey ? SpecificKey extends never ? {
277
+ [Key in AutoInferExclude]: Value extends Values[Key] ? Key : never;
278
+ }[AutoInferExclude] : SpecificKey : never;
279
+ export type GetTypes<Value extends unknown[]> = Value extends [
280
+ infer Type
281
+ ] ? Type : Value;
282
+ export type GetType<Value> = GetTypes<UnionToTuple<GetKey<Value>>>;
283
+ export type InferProperty<Value> = Value extends Property ? InferPropertyType<Value["type"]> : never;
284
+ export type InferPropertyType<Value> = Value extends (infer Type)[] ? InferPropertyTypeValue<Type>[] : InferPropertyTypeValue<Value>;
285
+ export type InferPropertyTypeValue<Value> = Value extends PropertyType ? Value extends Schema ? Inferred<Value> : Value extends Schematic<infer Model> ? Model : Value extends ValueKey ? Values[Value] : Value extends (infer NestedElementType)[] ? InferPropertyTypeValue<NestedElementType>[] : Value : never;
286
+ export type InferValue<Value> = Value extends ValueKey ? Values[Value] : Value extends ValueKey[] ? Values[Value[number]] : never;
287
+ export type Inferred<Model extends Schema> = Simplify<{
288
+ [Key in InferredRequiredProperties<Model>]: Model[Key] extends Property ? InferProperty<Model[Key]> : InferValue<Model[Key]>;
289
+ } & {
290
+ [Key in InferredOptionalProperties<Model>]?: Model[Key] extends Property ? InferProperty<Model[Key]> : never;
291
+ }>;
292
+ export type InferredOptionalProperties<Model extends Schema> = {
293
+ [Key in keyof Model]: Model[Key] extends Property ? Model[Key]["required"] extends false ? Key : never : never;
294
+ }[keyof Model];
295
+ export type InferredRequiredProperties<Model extends Schema> = {
296
+ [Key in keyof Model]: Model[Key] extends Property ? Model[Key]["required"] extends false ? never : Key : Key;
297
+ }[keyof Model];
298
+ export type OptionalProperty<Type> = {
299
+ required: false;
300
+ type: GetType<Type>;
301
+ };
302
+ export type Property = {
303
+ required?: boolean;
304
+ type: PropertyType | PropertyType[];
305
+ };
306
+ export type PropertyType = Schema | Schematic<unknown> | ValueKey;
307
+ export type RequiredProperty<Type> = {
308
+ required: true;
309
+ type: GetType<Type>;
310
+ };
311
+ /**
312
+ * A schema for validating objects
313
+ */
314
+ export type Schema = {
315
+ [key: string]: Property | ValueKey | ValueKey[];
316
+ };
317
+ /**
318
+ * A schematic for validating objects
319
+ */
320
+ export type Schematic<Model> = {
321
+ /**
322
+ * Does the value match the schema?
323
+ */
324
+ is(value: unknown): value is Model;
325
+ };
326
+ export type Typed = Record<string, unknown>;
327
+ /**
328
+ * A typed schema for validating objects
329
+ */
330
+ export type TypedSchema<Model extends Typed> = Simplify<{
331
+ [Key in RequiredKeysOf<Model>]: GetType<Model[Key]> | RequiredProperty<Model[Key]>;
332
+ } & {
333
+ [Key in OptionalKeysOf<Model>]: OptionalProperty<Model[Key]>;
334
+ }>;
335
+ export type ValidatedProperty = {
336
+ required: boolean;
337
+ types: ValidatedPropertyType[];
338
+ };
339
+ export type ValidatedPropertyType = Schematic<unknown> | ValidatedSchema | ValueKey;
340
+ export type ValidatedSchema = {
341
+ keys: string[];
342
+ length: number;
343
+ properties: ValidatedSchemaProperties;
344
+ };
345
+ export type ValidatedSchemaProperties = {
346
+ [key: string]: ValidatedProperty;
347
+ };
348
+ export type ValueKey = keyof Values;
349
+ export type Values = {
350
+ array: unknown[];
351
+ bigint: bigint;
352
+ boolean: boolean;
353
+ date: Date;
354
+ "date-like": number | string | Date;
355
+ function: Function;
356
+ null: null;
357
+ number: number;
358
+ numerical: bigint | number;
359
+ object: object;
360
+ string: string;
361
+ symbol: symbol;
362
+ undefined: undefined;
363
+ };
364
+
365
+ export {};
@@ -0,0 +1,91 @@
1
+ import type { OptionalKeysOf, RequiredKeysOf, Simplify, UnionToTuple } from 'type-fest';
2
+ export type AutoInferExclude = 'date-like' | 'numerical';
3
+ export type GetKey<Value> = {
4
+ [Key in Exclude<ValueKey, AutoInferExclude>]: Value extends Values[Key] ? Key : never;
5
+ }[Exclude<ValueKey, AutoInferExclude>] extends infer SpecificKey ? SpecificKey extends never ? {
6
+ [Key in AutoInferExclude]: Value extends Values[Key] ? Key : never;
7
+ }[AutoInferExclude] : SpecificKey : never;
8
+ export type GetTypes<Value extends unknown[]> = Value extends [infer Type] ? Type : Value;
9
+ export type GetType<Value> = GetTypes<UnionToTuple<GetKey<Value>>>;
10
+ export type InferProperty<Value> = Value extends Property ? InferPropertyType<Value['type']> : never;
11
+ type InferPropertyType<Value> = Value extends (infer Type)[] ? InferPropertyTypeValue<Type>[] : InferPropertyTypeValue<Value>;
12
+ type InferPropertyTypeValue<Value> = Value extends PropertyType ? Value extends Schema ? Inferred<Value> : Value extends Schematic<infer Model> ? Model : Value extends ValueKey ? Values[Value] : Value extends (infer NestedElementType)[] ? InferPropertyTypeValue<NestedElementType>[] : Value : never;
13
+ export type InferValue<Value> = Value extends ValueKey ? Values[Value] : Value extends ValueKey[] ? Values[Value[number]] : never;
14
+ export type Inferred<Model extends Schema> = Simplify<{
15
+ [Key in InferredRequiredProperties<Model>]: Model[Key] extends Property ? InferProperty<Model[Key]> : InferValue<Model[Key]>;
16
+ } & {
17
+ [Key in InferredOptionalProperties<Model>]?: Model[Key] extends Property ? InferProperty<Model[Key]> : never;
18
+ }>;
19
+ export type InferredOptionalProperties<Model extends Schema> = {
20
+ [Key in keyof Model]: Model[Key] extends Property ? Model[Key]['required'] extends false ? Key : never : never;
21
+ }[keyof Model];
22
+ export type InferredRequiredProperties<Model extends Schema> = {
23
+ [Key in keyof Model]: Model[Key] extends Property ? Model[Key]['required'] extends false ? never : Key : Key;
24
+ }[keyof Model];
25
+ export type OptionalProperty<Type> = {
26
+ required: false;
27
+ type: GetType<Type>;
28
+ };
29
+ export type Property = {
30
+ required?: boolean;
31
+ type: PropertyType | PropertyType[];
32
+ };
33
+ type PropertyType = Schema | Schematic<unknown> | ValueKey;
34
+ export type RequiredProperty<Type> = {
35
+ required: true;
36
+ type: GetType<Type>;
37
+ };
38
+ /**
39
+ * A schema for validating objects
40
+ */
41
+ export type Schema = {
42
+ [key: string]: Property | ValueKey | ValueKey[];
43
+ };
44
+ /**
45
+ * A schematic for validating objects
46
+ */
47
+ export type Schematic<Model> = {
48
+ /**
49
+ * Does the value match the schema?
50
+ */
51
+ is(value: unknown): value is Model;
52
+ };
53
+ export type Typed = Record<string, unknown>;
54
+ /**
55
+ * A typed schema for validating objects
56
+ */
57
+ export type TypedSchema<Model extends Typed> = Simplify<{
58
+ [Key in RequiredKeysOf<Model>]: GetType<Model[Key]> | RequiredProperty<Model[Key]>;
59
+ } & {
60
+ [Key in OptionalKeysOf<Model>]: OptionalProperty<Model[Key]>;
61
+ }>;
62
+ export type ValidatedProperty = {
63
+ required: boolean;
64
+ types: ValidatedPropertyType[];
65
+ };
66
+ export type ValidatedPropertyType = Schematic<unknown> | ValidatedSchema | ValueKey;
67
+ export type ValidatedSchema = {
68
+ keys: string[];
69
+ length: number;
70
+ properties: ValidatedSchemaProperties;
71
+ };
72
+ type ValidatedSchemaProperties = {
73
+ [key: string]: ValidatedProperty;
74
+ };
75
+ export type ValueKey = keyof Values;
76
+ export type Values = {
77
+ array: unknown[];
78
+ bigint: bigint;
79
+ boolean: boolean;
80
+ date: Date;
81
+ 'date-like': number | string | Date;
82
+ function: Function;
83
+ null: null;
84
+ number: number;
85
+ numerical: bigint | number;
86
+ object: object;
87
+ string: string;
88
+ symbol: symbol;
89
+ undefined: undefined;
90
+ };
91
+ export {};