@sinclair/typebox 0.26.1 → 0.26.3

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.
@@ -165,10 +165,10 @@ var TypeCompiler;
165
165
  return typeof value === 'string';
166
166
  }
167
167
  // -------------------------------------------------------------------
168
- // Overrides
168
+ // Polices
169
169
  // -------------------------------------------------------------------
170
- function IsNumberCheck(value) {
171
- return !index_2.TypeSystem.AllowNaN ? `(typeof ${value} === 'number' && Number.isFinite(${value}))` : `typeof ${value} === 'number'`;
170
+ function IsExactOptionalProperty(value, key, expression) {
171
+ return index_2.TypeSystem.ExactOptionalPropertyTypes ? `('${key}' in ${value} ? ${expression} : true)` : `(${value}.${key} !== undefined ? ${expression} : true)`;
172
172
  }
173
173
  function IsObjectCheck(value) {
174
174
  return !index_2.TypeSystem.AllowArrayObjects ? `(typeof ${value} === 'object' && ${value} !== null && !Array.isArray(${value}))` : `(typeof ${value} === 'object' && ${value} !== null)`;
@@ -178,6 +178,9 @@ var TypeCompiler;
178
178
  ? `(typeof ${value} === 'object' && ${value} !== null && !Array.isArray(${value}) && !(${value} instanceof Date) && !(${value} instanceof Uint8Array))`
179
179
  : `(typeof ${value} === 'object' && ${value} !== null && !(${value} instanceof Date) && !(${value} instanceof Uint8Array))`;
180
180
  }
181
+ function IsNumberCheck(value) {
182
+ return !index_2.TypeSystem.AllowNaN ? `(typeof ${value} === 'number' && Number.isFinite(${value}))` : `typeof ${value} === 'number'`;
183
+ }
181
184
  function IsVoidCheck(value) {
182
185
  return index_2.TypeSystem.AllowVoidNull ? `(${value} === undefined || ${value} === null)` : `${value} === undefined`;
183
186
  }
@@ -302,32 +305,32 @@ var TypeCompiler;
302
305
  yield `Object.getOwnPropertyNames(${value}).length >= ${schema.minProperties}`;
303
306
  if (IsNumber(schema.maxProperties))
304
307
  yield `Object.getOwnPropertyNames(${value}).length <= ${schema.maxProperties}`;
305
- const schemaKeys = globalThis.Object.getOwnPropertyNames(schema.properties);
306
- for (const schemaKey of schemaKeys) {
307
- const memberExpression = MemberExpression.Encode(value, schemaKey);
308
- const property = schema.properties[schemaKey];
309
- if (schema.required && schema.required.includes(schemaKey)) {
308
+ const knownKeys = globalThis.Object.getOwnPropertyNames(schema.properties);
309
+ for (const knownKey of knownKeys) {
310
+ const memberExpression = MemberExpression.Encode(value, knownKey);
311
+ const property = schema.properties[knownKey];
312
+ if (schema.required && schema.required.includes(knownKey)) {
310
313
  yield* Visit(property, references, memberExpression);
311
314
  if (Types.ExtendsUndefined.Check(property))
312
- yield `('${schemaKey}' in ${value})`;
315
+ yield `('${knownKey}' in ${value})`;
313
316
  }
314
317
  else {
315
318
  const expression = CreateExpression(property, references, memberExpression);
316
- yield `('${schemaKey}' in ${value} ? ${expression} : true)`;
319
+ yield IsExactOptionalProperty(value, knownKey, expression);
317
320
  }
318
321
  }
319
322
  if (schema.additionalProperties === false) {
320
- if (schema.required && schema.required.length === schemaKeys.length) {
321
- yield `Object.getOwnPropertyNames(${value}).length === ${schemaKeys.length}`;
323
+ if (schema.required && schema.required.length === knownKeys.length) {
324
+ yield `Object.getOwnPropertyNames(${value}).length === ${knownKeys.length}`;
322
325
  }
323
326
  else {
324
- const keys = `[${schemaKeys.map((key) => `'${key}'`).join(', ')}]`;
327
+ const keys = `[${knownKeys.map((key) => `'${key}'`).join(', ')}]`;
325
328
  yield `Object.getOwnPropertyNames(${value}).every(key => ${keys}.includes(key))`;
326
329
  }
327
330
  }
328
331
  if (typeof schema.additionalProperties === 'object') {
329
332
  const expression = CreateExpression(schema.additionalProperties, references, 'value[key]');
330
- const keys = `[${schemaKeys.map((key) => `'${key}'`).join(', ')}]`;
333
+ const keys = `[${knownKeys.map((key) => `'${key}'`).join(', ')}]`;
331
334
  yield `(Object.getOwnPropertyNames(${value}).every(key => ${keys}.includes(key) || ${expression}))`;
332
335
  }
333
336
  }
package/errors/errors.js CHANGED
@@ -136,6 +136,24 @@ var ValueErrors;
136
136
  // ----------------------------------------------------------------------
137
137
  // Guards
138
138
  // ----------------------------------------------------------------------
139
+ function IsBigInt(value) {
140
+ return typeof value === 'bigint';
141
+ }
142
+ function IsInteger(value) {
143
+ return globalThis.Number.isInteger(value);
144
+ }
145
+ function IsString(value) {
146
+ return typeof value === 'string';
147
+ }
148
+ function IsDefined(value) {
149
+ return value !== undefined;
150
+ }
151
+ // ----------------------------------------------------------------------
152
+ // Policies
153
+ // ----------------------------------------------------------------------
154
+ function IsExactOptionalProperty(value, key) {
155
+ return index_1.TypeSystem.ExactOptionalPropertyTypes ? key in value : value[key] !== undefined;
156
+ }
139
157
  function IsObject(value) {
140
158
  const result = typeof value === 'object' && value !== null;
141
159
  return index_1.TypeSystem.AllowArrayObjects ? result : result && !globalThis.Array.isArray(value);
@@ -143,26 +161,14 @@ var ValueErrors;
143
161
  function IsRecordObject(value) {
144
162
  return IsObject(value) && !(value instanceof globalThis.Date) && !(value instanceof globalThis.Uint8Array);
145
163
  }
146
- function IsBigInt(value) {
147
- return typeof value === 'bigint';
148
- }
149
164
  function IsNumber(value) {
150
165
  const result = typeof value === 'number';
151
166
  return index_1.TypeSystem.AllowNaN ? result : result && globalThis.Number.isFinite(value);
152
167
  }
153
- function IsInteger(value) {
154
- return globalThis.Number.isInteger(value);
155
- }
156
- function IsString(value) {
157
- return typeof value === 'string';
158
- }
159
168
  function IsVoid(value) {
160
169
  const result = value === undefined;
161
170
  return index_1.TypeSystem.AllowVoidNull ? result || value === null : result;
162
171
  }
163
- function IsDefined(value) {
164
- return value !== undefined;
165
- }
166
172
  // ----------------------------------------------------------------------
167
173
  // Types
168
174
  // ----------------------------------------------------------------------
@@ -361,7 +367,7 @@ var ValueErrors;
361
367
  }
362
368
  }
363
369
  else {
364
- if (knownKey in value) {
370
+ if (IsExactOptionalProperty(value, knownKey)) {
365
371
  yield* Visit(property, references, `${path}/${knownKey}`, value[knownKey]);
366
372
  }
367
373
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sinclair/typebox",
3
- "version": "0.26.1",
3
+ "version": "0.26.3",
4
4
  "description": "JSONSchema Type Builder with Static Type Resolution for TypeScript",
5
5
  "keywords": [
6
6
  "typescript",
package/readme.md CHANGED
@@ -229,13 +229,13 @@ The following table lists the Standard TypeBox types. These types are fully comp
229
229
  │ │ │ │
230
230
  ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
231
231
  │ const T = Type.Null() │ type T = null │ const T = { │
232
- │ │ │ type: 'null'
232
+ │ │ │ type: 'null'
233
233
  │ │ │ } │
234
234
  │ │ │ │
235
235
  ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
236
236
  │ const T = Type.Literal(42) │ type T = 42 │ const T = { │
237
- │ │ │ const: 42,
238
- │ │ │ type: 'number'
237
+ │ │ │ const: 42,
238
+ │ │ │ type: 'number'
239
239
  │ │ │ } │
240
240
  │ │ │ │
241
241
  ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
@@ -325,20 +325,17 @@ The following table lists the Standard TypeBox types. These types are fully comp
325
325
  │ │ │ } │
326
326
  │ │ │ │
327
327
  ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
328
- │ const T = Type.Composite([ │ type T = { │ const T = { │
329
- │ Type.Object({ │ x: number | string │ type: 'object', │
330
- │ x: Type.Number() │ y: number properties: {
331
- │ }), │ } x: {
332
- │ Type.Object({ │ anyOf: [
333
- x: Type.String() │ │ { type: 'number' },
334
- y: Type.Number() │ { type: 'string' }
335
- }) ]
336
- ]) }, │
337
- │ │ │ y: { │
338
- │ │ │ type: 'number' │
328
+ │ const T = Type.Composite([ │ type I = { │ const T = { │
329
+ │ Type.Object({ │ x: number │ type: 'object', │
330
+ │ x: Type.Number() │ } & { required: ['x', 'y'],
331
+ │ }), │ y: number properties: {
332
+ │ Type.Object({ │ } x: {
333
+ y: Type.Number() │ │ type: 'number'
334
+ }) │ type T = { │ },
335
+ ]) │ [K in keyof I]: I[K] y: { │
336
+ } type: 'number'
339
337
  │ │ │ } │
340
- │ │ │ },
341
- │ │ │ required: ['x', 'y'] │
338
+ │ │ │ }
342
339
  │ │ │ } │
343
340
  │ │ │ │
344
341
  ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
@@ -7,6 +7,8 @@ export declare class TypeSystemDuplicateFormat extends Error {
7
7
  }
8
8
  /** Creates user defined types and formats and provides overrides for value checking behaviours */
9
9
  export declare namespace TypeSystem {
10
+ /** Sets whether TypeBox should assert optional properties using the TypeScript `exactOptionalPropertyTypes` assertion policy. The default is `false` */
11
+ let ExactOptionalPropertyTypes: boolean;
10
12
  /** Sets whether arrays should be treated as a kind of objects. The default is `false` */
11
13
  let AllowArrayObjects: boolean;
12
14
  /** Sets whether `NaN` or `Infinity` should be treated as valid numeric values. The default is `false` */
package/system/system.js CHANGED
@@ -44,12 +44,20 @@ exports.TypeSystemDuplicateFormat = TypeSystemDuplicateFormat;
44
44
  /** Creates user defined types and formats and provides overrides for value checking behaviours */
45
45
  var TypeSystem;
46
46
  (function (TypeSystem) {
47
+ // ------------------------------------------------------------------------
48
+ // Assertion Policies
49
+ // ------------------------------------------------------------------------
50
+ /** Sets whether TypeBox should assert optional properties using the TypeScript `exactOptionalPropertyTypes` assertion policy. The default is `false` */
51
+ TypeSystem.ExactOptionalPropertyTypes = false;
47
52
  /** Sets whether arrays should be treated as a kind of objects. The default is `false` */
48
53
  TypeSystem.AllowArrayObjects = false;
49
54
  /** Sets whether `NaN` or `Infinity` should be treated as valid numeric values. The default is `false` */
50
55
  TypeSystem.AllowNaN = false;
51
56
  /** Sets whether `null` should validate for void types. The default is `false` */
52
57
  TypeSystem.AllowVoidNull = false;
58
+ // ------------------------------------------------------------------------
59
+ // String Formats and Types
60
+ // ------------------------------------------------------------------------
53
61
  /** Creates a new type */
54
62
  function Type(kind, check) {
55
63
  if (Types.TypeRegistry.Has(kind))
package/typebox.d.ts CHANGED
@@ -83,16 +83,18 @@ export interface TBoolean extends TSchema {
83
83
  }
84
84
  export type TConstructorParameters<T extends TConstructor<TSchema[], TSchema>> = TTuple<T['parameters']>;
85
85
  export type TInstanceType<T extends TConstructor<TSchema[], TSchema>> = T['returns'];
86
- export type TCompositeUnion<Left extends TSchema, Right extends TSchema> = Ensure<TUnion<[Left, Right]>>;
87
- export type TCompositeUnionLeft<T extends TObject, Acc extends TProperties> = {
88
- [K in keyof T['properties']]: K extends keyof Acc ? TCompositeUnion<T['properties'][K], Acc[K]> : T['properties'][K];
86
+ export type TCompositeEvaluateArray<T extends readonly TSchema[], P extends unknown[]> = {
87
+ [K in keyof T]: T[K] extends TSchema ? Static<T[K], P> : never;
89
88
  };
90
- export type TCompositeUnionRight<T extends TObject, Acc extends TProperties> = {
91
- [K in keyof Acc]: K extends keyof T['properties'] ? TCompositeUnion<T['properties'][K], Acc[K]> : Acc[K];
89
+ export type TCompositeArray<T extends readonly TObject[]> = {
90
+ [K in keyof T]: T[K] extends TObject<infer P> ? P : {};
92
91
  };
93
- export type TCompositeUnionObject<T extends TObject, Acc extends TProperties> = Evaluate<TCompositeUnionLeft<T, Acc> & TCompositeUnionRight<T, Acc>>;
94
- export type TCompositeProperties<T extends TObject[], Acc extends TProperties> = T extends [...infer L, infer R] ? TCompositeProperties<Assert<L, TObject[]>, TCompositeUnionObject<Assert<R, TObject>, Acc>> : T extends [] ? Acc : never;
95
- export type TComposite<T extends TObject[] = TObject[]> = Ensure<TObject<TCompositeProperties<T, {}>>>;
92
+ export type TCompositeProperties<I extends unknown, T extends readonly any[]> = Evaluate<T extends [infer A, ...infer B] ? TCompositeProperties<I & A, B> : I extends object ? I : {}>;
93
+ export interface TComposite<T extends TObject[] = TObject[]> extends TObject {
94
+ [Hint]: 'Composite';
95
+ static: Evaluate<TCompositeProperties<unknown, TCompositeEvaluateArray<T, this['params']>>>;
96
+ properties: TCompositeProperties<unknown, TCompositeArray<T>>;
97
+ }
96
98
  export type TConstructorParameterArray<T extends readonly TSchema[], P extends unknown[]> = [...{
97
99
  [K in keyof T]: Static<Assert<T[K], TSchema>, P>;
98
100
  }];
@@ -169,7 +171,7 @@ export type TKeyOfTuple<T extends TSchema> = {
169
171
  } extends infer U ? UnionToTuple<Exclude<{
170
172
  [K in keyof U]: U[K];
171
173
  }[keyof U], undefined>> : never;
172
- export type TKeyOf<T extends TSchema = TSchema> = (T extends TIntersect ? TKeyOfTuple<T> : T extends TUnion ? TKeyOfTuple<T> : T extends TObject ? TKeyOfTuple<T> : [
174
+ export type TKeyOf<T extends TSchema = TSchema> = (T extends TComposite ? TKeyOfTuple<T> : T extends TIntersect ? TKeyOfTuple<T> : T extends TUnion ? TKeyOfTuple<T> : T extends TObject ? TKeyOfTuple<T> : [
173
175
  ]) extends infer R ? TUnionResult<Assert<R, TSchema[]>> : never;
174
176
  export type TLiteralValue = string | number | boolean;
175
177
  export interface TLiteral<T extends TLiteralValue = TLiteralValue> extends TSchema {
@@ -180,13 +182,7 @@ export interface TLiteral<T extends TLiteralValue = TLiteralValue> extends TSche
180
182
  export interface TNever extends TSchema {
181
183
  [Kind]: 'Never';
182
184
  static: never;
183
- allOf: [{
184
- type: 'boolean';
185
- const: false;
186
- }, {
187
- type: 'boolean';
188
- const: true;
189
- }];
185
+ not: {};
190
186
  }
191
187
  export type TNotStatic<_ extends TSchema = TSchema, T extends TSchema = TSchema> = Static<T>;
192
188
  export interface TNot<Not extends TSchema = TSchema, T extends TSchema = TSchema> extends TSchema {
@@ -241,22 +237,25 @@ export type TOmitArray<T extends TSchema[], K extends keyof any> = Assert<{
241
237
  [K2 in keyof T]: TOmit<Assert<T[K2], TSchema>, K>;
242
238
  }, TSchema[]>;
243
239
  export type TOmitProperties<T extends TProperties, K extends keyof any> = Evaluate<Assert<Omit<T, K>, TProperties>>;
244
- export type TOmit<T extends TSchema, K extends keyof any> = T extends TIntersect<infer S> ? TIntersect<TOmitArray<S, K>> : T extends TUnion<infer S> ? TUnion<TOmitArray<S, K>> : T extends TObject<infer S> ? TObject<TOmitProperties<S, K>> : T;
240
+ export type TOmit<T extends TSchema, K extends keyof any> = T extends TComposite<infer S> ? TComposite<TOmitArray<S, K>> : T extends TIntersect<infer S> ? TIntersect<TOmitArray<S, K>> : T extends TUnion<infer S> ? TUnion<TOmitArray<S, K>> : T extends TObject<infer S> ? TObject<TOmitProperties<S, K>> : T;
245
241
  export type TParameters<T extends TFunction> = TTuple<T['parameters']>;
242
+ export type TPartialObjectArray<T extends TObject[]> = Assert<{
243
+ [K in keyof T]: TPartial<Assert<T[K], TObject>>;
244
+ }, TObject[]>;
246
245
  export type TPartialArray<T extends TSchema[]> = Assert<{
247
246
  [K in keyof T]: TPartial<Assert<T[K], TSchema>>;
248
247
  }, TSchema[]>;
249
248
  export type TPartialProperties<T extends TProperties> = Evaluate<Assert<{
250
249
  [K in keyof T]: T[K] extends TReadonlyOptional<infer U> ? TReadonlyOptional<U> : T[K] extends TReadonly<infer U> ? TReadonlyOptional<U> : T[K] extends TOptional<infer U> ? TOptional<U> : TOptional<T[K]>;
251
250
  }, TProperties>>;
252
- export type TPartial<T extends TSchema> = T extends TIntersect<infer S> ? TIntersect<TPartialArray<S>> : T extends TUnion<infer S> ? TUnion<TPartialArray<S>> : T extends TObject<infer S> ? TObject<TPartialProperties<S>> : T;
251
+ export type TPartial<T extends TSchema> = T extends TComposite<infer S> ? TComposite<TPartialArray<S>> : T extends TIntersect<infer S> ? TIntersect<TPartialArray<S>> : T extends TUnion<infer S> ? TUnion<TPartialArray<S>> : T extends TObject<infer S> ? TObject<TPartialProperties<S>> : T;
253
252
  export type TPickArray<T extends TSchema[], K extends keyof any> = {
254
253
  [K2 in keyof T]: TPick<Assert<T[K2], TSchema>, K>;
255
254
  };
256
255
  export type TPickProperties<T extends TProperties, K extends keyof any> = Pick<T, Assert<Extract<K, keyof T>, keyof T>> extends infer R ? ({
257
256
  [K in keyof R]: Assert<R[K], TSchema> extends TSchema ? R[K] : never;
258
257
  }) : never;
259
- export type TPick<T extends TSchema, K extends keyof any> = T extends TIntersect<infer S> ? TIntersect<TPickArray<S, K>> : T extends TUnion<infer S> ? TUnion<TPickArray<S, K>> : T extends TObject<infer S> ? TObject<TPickProperties<S, K>> : T;
258
+ export type TPick<T extends TSchema, K extends keyof any> = T extends TComposite<infer S> ? TComposite<TPickArray<S, K>> : T extends TIntersect<infer S> ? TIntersect<TPickArray<S, K>> : T extends TUnion<infer S> ? TUnion<TPickArray<S, K>> : T extends TObject<infer S> ? TObject<TPickProperties<S, K>> : T;
260
259
  export type TPromiseStatic<T extends TSchema, P extends unknown[]> = Promise<Static<T, P>>;
261
260
  export interface TPromise<T extends TSchema = TSchema> extends TSchema {
262
261
  [Kind]: 'Promise';
@@ -304,7 +303,7 @@ export type TRequiredArray<T extends TSchema[]> = Assert<{
304
303
  export type TRequiredProperties<T extends TProperties> = Evaluate<Assert<{
305
304
  [K in keyof T]: T[K] extends TReadonlyOptional<infer U> ? TReadonly<U> : T[K] extends TReadonly<infer U> ? TReadonly<U> : T[K] extends TOptional<infer U> ? U : T[K];
306
305
  }, TProperties>>;
307
- export type TRequired<T extends TSchema> = T extends TIntersect<infer S> ? TIntersect<TRequiredArray<S>> : T extends TUnion<infer S> ? TUnion<TRequiredArray<S>> : T extends TObject<infer S> ? TObject<TRequiredProperties<S>> : T;
306
+ export type TRequired<T extends TSchema> = T extends TComposite<infer S> ? TComposite<TRequiredArray<S>> : T extends TIntersect<infer S> ? TIntersect<TRequiredArray<S>> : T extends TUnion<infer S> ? TUnion<TRequiredArray<S>> : T extends TObject<infer S> ? TObject<TRequiredProperties<S>> : T;
308
307
  export type StringFormatOption = 'date-time' | 'time' | 'date' | 'email' | 'idn-email' | 'hostname' | 'idn-hostname' | 'ipv4' | 'ipv6' | 'uri' | 'uri-reference' | 'iri' | 'uuid' | 'iri-reference' | 'uri-template' | 'json-pointer' | 'relative-json-pointer' | 'regex';
309
308
  export interface StringOptions<Format extends string> extends SchemaOptions {
310
309
  minLength?: number;
@@ -531,8 +530,8 @@ export declare class StandardTypeBuilder extends TypeBuilder {
531
530
  Array<T extends TSchema>(items: T, options?: ArrayOptions): TArray<T>;
532
531
  /** `[Standard]` Creates a Boolean type */
533
532
  Boolean(options?: SchemaOptions): TBoolean;
534
- /** `[Standard]` Creates a Composite object type that will union any overlapping properties of the given object array */
535
- Composite<T extends TObject[]>(schemas: [...T], options?: ObjectOptions): TComposite<T>;
533
+ /** `[Standard]` Creates a Composite object type. */
534
+ Composite<T extends TObject[]>(objects: [...T], options?: ObjectOptions): TComposite<T>;
536
535
  /** `[Standard]` Creates a Enum type */
537
536
  Enum<T extends Record<string, string | number>>(item: T, options?: SchemaOptions): TEnum<T>;
538
537
  /** `[Standard]` A conditional type expression that will return the true type if the left type extends the right */
package/typebox.js CHANGED
@@ -1465,15 +1465,48 @@ class StandardTypeBuilder extends TypeBuilder {
1465
1465
  Boolean(options = {}) {
1466
1466
  return this.Create({ ...options, [exports.Kind]: 'Boolean', type: 'boolean' });
1467
1467
  }
1468
- /** `[Standard]` Creates a Composite object type that will union any overlapping properties of the given object array */
1469
- Composite(schemas, options) {
1468
+ /** `[Standard]` Creates a Composite object type. */
1469
+ Composite(objects, options) {
1470
+ const isOptionalAll = (objects, key) => objects.every((object) => !(key in object.properties) || IsOptional(object.properties[key]));
1471
+ const IsOptional = (schema) => TypeGuard.TOptional(schema) || TypeGuard.TReadonlyOptional(schema);
1472
+ const [required, optional] = [new Set(), new Set()];
1473
+ for (const object of objects) {
1474
+ for (const key of globalThis.Object.getOwnPropertyNames(object.properties)) {
1475
+ if (isOptionalAll(objects, key))
1476
+ optional.add(key);
1477
+ }
1478
+ }
1479
+ for (const object of objects) {
1480
+ for (const key of globalThis.Object.getOwnPropertyNames(object.properties)) {
1481
+ if (!optional.has(key))
1482
+ required.add(key);
1483
+ }
1484
+ }
1470
1485
  const properties = {};
1471
- for (const object of schemas) {
1472
- for (const [key, property] of globalThis.Object.entries(object.properties)) {
1473
- properties[key] = key in properties ? this.Union([properties[key], property]) : TypeClone.Clone(property, {});
1486
+ for (const object of objects) {
1487
+ for (const [key, schema] of Object.entries(object.properties)) {
1488
+ const property = TypeClone.Clone(schema, {});
1489
+ if (!optional.has(key))
1490
+ delete property[exports.Modifier];
1491
+ if (key in properties) {
1492
+ const left = TypeExtends.Extends(properties[key], property) !== TypeExtendsResult.False;
1493
+ const right = TypeExtends.Extends(property, properties[key]) !== TypeExtendsResult.False;
1494
+ if (!left && !right)
1495
+ properties[key] = exports.Type.Never();
1496
+ if (!left && right)
1497
+ properties[key] = property;
1498
+ }
1499
+ else {
1500
+ properties[key] = property;
1501
+ }
1474
1502
  }
1475
1503
  }
1476
- return this.Object(properties, options);
1504
+ if (required.size > 0) {
1505
+ return this.Create({ ...options, [exports.Kind]: 'Object', [exports.Hint]: 'Composite', type: 'object', properties, required: [...required] });
1506
+ }
1507
+ else {
1508
+ return this.Create({ ...options, [exports.Kind]: 'Object', [exports.Hint]: 'Composite', type: 'object', properties });
1509
+ }
1477
1510
  }
1478
1511
  /** `[Standard]` Creates a Enum type */
1479
1512
  Enum(item, options = {}) {
package/value/check.js CHANGED
@@ -53,6 +53,24 @@ var ValueCheck;
53
53
  // ----------------------------------------------------------------------
54
54
  // Guards
55
55
  // ----------------------------------------------------------------------
56
+ function IsBigInt(value) {
57
+ return typeof value === 'bigint';
58
+ }
59
+ function IsInteger(value) {
60
+ return globalThis.Number.isInteger(value);
61
+ }
62
+ function IsString(value) {
63
+ return typeof value === 'string';
64
+ }
65
+ function IsDefined(value) {
66
+ return value !== undefined;
67
+ }
68
+ // ----------------------------------------------------------------------
69
+ // Policies
70
+ // ----------------------------------------------------------------------
71
+ function IsExactOptionalProperty(value, key) {
72
+ return index_1.TypeSystem.ExactOptionalPropertyTypes ? key in value : value[key] !== undefined;
73
+ }
56
74
  function IsObject(value) {
57
75
  const result = typeof value === 'object' && value !== null;
58
76
  return index_1.TypeSystem.AllowArrayObjects ? result : result && !globalThis.Array.isArray(value);
@@ -60,26 +78,14 @@ var ValueCheck;
60
78
  function IsRecordObject(value) {
61
79
  return IsObject(value) && !(value instanceof globalThis.Date) && !(value instanceof globalThis.Uint8Array);
62
80
  }
63
- function IsBigInt(value) {
64
- return typeof value === 'bigint';
65
- }
66
81
  function IsNumber(value) {
67
82
  const result = typeof value === 'number';
68
83
  return index_1.TypeSystem.AllowNaN ? result : result && globalThis.Number.isFinite(value);
69
84
  }
70
- function IsInteger(value) {
71
- return globalThis.Number.isInteger(value);
72
- }
73
- function IsString(value) {
74
- return typeof value === 'string';
75
- }
76
85
  function IsVoid(value) {
77
86
  const result = value === undefined;
78
87
  return index_1.TypeSystem.AllowVoidNull ? result || value === null : result;
79
88
  }
80
- function IsDefined(value) {
81
- return value !== undefined;
82
- }
83
89
  // ----------------------------------------------------------------------
84
90
  // Types
85
91
  // ----------------------------------------------------------------------
@@ -255,7 +261,7 @@ var ValueCheck;
255
261
  }
256
262
  }
257
263
  else {
258
- if (knownKey in value && !Visit(property, references, value[knownKey])) {
264
+ if (IsExactOptionalProperty(value, knownKey) && !Visit(property, references, value[knownKey])) {
259
265
  return false;
260
266
  }
261
267
  }