@fluidframework/core-interfaces 2.90.0-378676 → 2.91.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 (66) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/api-extractor/api-extractor-lint-internal-exposedUtilityTypes.esm.json +14 -0
  3. package/api-report/core-interfaces.legacy.alpha.api.md +7 -0
  4. package/api-report/core-interfaces.legacy.beta.api.md +7 -0
  5. package/dist/api-extractor/exposedUtilityTypes.d.ts +7 -0
  6. package/dist/api-extractor/exposedUtilityTypes.d.ts.map +1 -0
  7. package/dist/api-extractor/exposedUtilityTypes.js +7 -0
  8. package/dist/api-extractor/exposedUtilityTypes.js.map +1 -0
  9. package/dist/brandedType.d.ts +1 -1
  10. package/dist/brandedType.js.map +1 -1
  11. package/dist/deepReadonly.d.ts +1 -0
  12. package/dist/deepReadonly.d.ts.map +1 -1
  13. package/dist/deepReadonly.js.map +1 -1
  14. package/dist/exposedInternalUtilityTypes.d.ts +5 -5
  15. package/dist/exposedInternalUtilityTypes.d.ts.map +1 -1
  16. package/dist/exposedInternalUtilityTypes.js.map +1 -1
  17. package/dist/exposedUtilityTypes.d.ts +3 -3
  18. package/dist/exposedUtilityTypes.d.ts.map +1 -1
  19. package/dist/exposedUtilityTypes.js.map +1 -1
  20. package/dist/handles.js.map +1 -1
  21. package/dist/internal.d.ts +1 -1
  22. package/dist/internal.d.ts.map +1 -1
  23. package/dist/internal.js.map +1 -1
  24. package/dist/jsonString.d.ts.map +1 -1
  25. package/dist/jsonString.js.map +1 -1
  26. package/dist/legacy.alpha.d.ts +1 -0
  27. package/dist/legacy.d.ts +1 -0
  28. package/dist/shallowReadonly.d.ts +1 -0
  29. package/dist/shallowReadonly.d.ts.map +1 -1
  30. package/dist/shallowReadonly.js.map +1 -1
  31. package/lib/api-extractor/exposedUtilityTypes.d.ts +7 -0
  32. package/lib/api-extractor/exposedUtilityTypes.d.ts.map +1 -0
  33. package/lib/api-extractor/exposedUtilityTypes.js +6 -0
  34. package/lib/api-extractor/exposedUtilityTypes.js.map +1 -0
  35. package/lib/brandedType.d.ts +1 -1
  36. package/lib/brandedType.js.map +1 -1
  37. package/lib/deepReadonly.d.ts +1 -0
  38. package/lib/deepReadonly.d.ts.map +1 -1
  39. package/lib/deepReadonly.js.map +1 -1
  40. package/lib/exposedInternalUtilityTypes.d.ts +5 -5
  41. package/lib/exposedInternalUtilityTypes.d.ts.map +1 -1
  42. package/lib/exposedInternalUtilityTypes.js.map +1 -1
  43. package/lib/exposedUtilityTypes.d.ts +3 -3
  44. package/lib/exposedUtilityTypes.d.ts.map +1 -1
  45. package/lib/exposedUtilityTypes.js.map +1 -1
  46. package/lib/handles.js.map +1 -1
  47. package/lib/internal.d.ts +1 -1
  48. package/lib/internal.d.ts.map +1 -1
  49. package/lib/internal.js.map +1 -1
  50. package/lib/jsonString.d.ts.map +1 -1
  51. package/lib/jsonString.js.map +1 -1
  52. package/lib/legacy.alpha.d.ts +1 -0
  53. package/lib/legacy.d.ts +1 -0
  54. package/lib/shallowReadonly.d.ts +1 -0
  55. package/lib/shallowReadonly.d.ts.map +1 -1
  56. package/lib/shallowReadonly.js.map +1 -1
  57. package/package.json +7 -7
  58. package/src/api-extractor/exposedUtilityTypes.ts +18 -0
  59. package/src/brandedType.ts +1 -1
  60. package/src/deepReadonly.ts +1 -0
  61. package/src/exposedInternalUtilityTypes.ts +541 -518
  62. package/src/exposedUtilityTypes.ts +14 -4
  63. package/src/handles.ts +1 -1
  64. package/src/internal.ts +1 -1
  65. package/src/jsonString.ts +0 -1
  66. package/src/shallowReadonly.ts +1 -0
@@ -134,20 +134,18 @@ export namespace InternalUtilityTypes {
134
134
  *
135
135
  * @system
136
136
  */
137
- export type OptionalNonSymbolKeysOf<
138
- T extends object,
139
- Keys extends keyof T = keyof T,
140
- > = Exclude<
141
- {
142
- [K in Keys]: T extends Record<K, T[K]> ? never : K;
143
- }[Keys],
144
- undefined | symbol
145
- > extends infer Result
146
- ? // Workaround for TypeScript bug/limitation where an alias for a type
147
- // is not considered the same type when used as an index. This restores
148
- // the original `Keys` (`keyof T`) type when there is no filtering.
149
- IfSameType<Keys, Result, Keys, Extract<Result, string | number>>
150
- : never;
137
+ export type OptionalNonSymbolKeysOf<T extends object, Keys extends keyof T = keyof T> =
138
+ Exclude<
139
+ {
140
+ [K in Keys]: T extends Record<K, T[K]> ? never : K;
141
+ }[Keys],
142
+ undefined | symbol
143
+ > extends infer Result
144
+ ? // Workaround for TypeScript bug/limitation where an alias for a type
145
+ // is not considered the same type when used as an index. This restores
146
+ // the original `Keys` (`keyof T`) type when there is no filtering.
147
+ IfSameType<Keys, Result, Keys, Extract<Result, string | number>>
148
+ : never;
151
149
 
152
150
  /**
153
151
  * Returns non-symbol keys for required properties of an object type.
@@ -158,20 +156,18 @@ export namespace InternalUtilityTypes {
158
156
  *
159
157
  * @system
160
158
  */
161
- export type RequiredNonSymbolKeysOf<
162
- T extends object,
163
- Keys extends keyof T = keyof T,
164
- > = Exclude<
165
- {
166
- [K in Keys]: T extends Record<K, T[K]> ? K : never;
167
- }[Keys],
168
- undefined | symbol
169
- > extends infer Result
170
- ? // Workaround for TypeScript bug/limitation where an alias for a type
171
- // is not considered the same type when used as an index. This restores
172
- // the original `Keys` (`keyof T`) type when there is no filtering.
173
- IfSameType<Keys, Result, Keys, Extract<Result, string | number>>
174
- : never;
159
+ export type RequiredNonSymbolKeysOf<T extends object, Keys extends keyof T = keyof T> =
160
+ Exclude<
161
+ {
162
+ [K in Keys]: T extends Record<K, T[K]> ? K : never;
163
+ }[Keys],
164
+ undefined | symbol
165
+ > extends infer Result
166
+ ? // Workaround for TypeScript bug/limitation where an alias for a type
167
+ // is not considered the same type when used as an index. This restores
168
+ // the original `Keys` (`keyof T`) type when there is no filtering.
169
+ IfSameType<Keys, Result, Keys, Extract<Result, string | number>>
170
+ : never;
175
171
 
176
172
  /**
177
173
  * Returns Result.WhenSomethingDeserializable if T is sometimes at least a
@@ -289,58 +285,59 @@ export namespace InternalUtilityTypes {
289
285
  TExactExceptions extends unknown[],
290
286
  TExtendsException,
291
287
  Keys extends keyof T = keyof T,
292
- > = Exclude<
293
- {
294
- [K in Keys]: /* all possible types that aren't already allowed, with the exception of `unknown` */
295
- ExcludeExactlyInTuple<
296
- Exclude<T[K], TExtendsException>,
297
- OmitExactlyFromTuple<TExactExceptions, unknown>
298
- > extends infer PossibleTypeLessAllowed
299
- ? IfSameType<
300
- PossibleTypeLessAllowed,
301
- unknown,
302
- /* value might not be supported => check for indexed key */ IfIndexOrBrandedKey<
303
- K,
304
- /* indexed => allow K */ K,
305
- /* literal => exclude K */ never
306
- >,
307
- /* extract types that might lead to missing property */ Extract<
288
+ > =
289
+ Exclude<
290
+ {
291
+ [K in Keys]: /* all possible types that aren't already allowed, with the exception of `unknown` */
292
+ ExcludeExactlyInTuple<
293
+ Exclude<T[K], TExtendsException>,
294
+ OmitExactlyFromTuple<TExactExceptions, unknown>
295
+ > extends infer PossibleTypeLessAllowed
296
+ ? IfSameType<
308
297
  PossibleTypeLessAllowed,
309
- /* types that might lead to missing property, except `bigint` */
310
- // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
311
- undefined | symbol | Function
312
- > extends never
313
- ? /* all types are supported plus possibly `bigint` => */
314
- /* check for only `bigint` remaining */ IfSameType<
315
- PossibleTypeLessAllowed,
316
- bigint,
317
- /* only `bigint` => nothing supported */ never,
318
- /* exclusively supported types (and maybe `bigint`) or exactly `never` */
319
- /* => check for `never` */ T[K] extends never ? never : K
320
- >
321
- : /* value might not be supported => check for any supported */ TestDeserializabilityOf<
322
- T[K],
323
- OmitExactlyFromTuple<TExactExceptions, unknown>,
324
- TExtendsException,
325
- {
326
- WhenSomethingDeserializable: /* => check for indexed key */ IfIndexOrBrandedKey<
327
- K,
328
- /* indexed => allow K */ K,
329
- /* literal => exclude K */ never
330
- >;
331
- WhenNeverDeserializable: /* => exclude K */ never;
332
- }
333
- >
334
- >
335
- : never;
336
- }[Keys],
337
- undefined | symbol
338
- > extends infer Result
339
- ? // Workaround for TypeScript bug/limitation where an alias for a type
340
- // is not considered the same type when used as an index. This restores
341
- // the original `Keys` (`keyof T`) type when there is no filtering.
342
- IfSameType<Keys, Result, Keys, Extract<Result, string | number>>
343
- : never;
298
+ unknown,
299
+ /* value might not be supported => check for indexed key */ IfIndexOrBrandedKey<
300
+ K,
301
+ /* indexed => allow K */ K,
302
+ /* literal => exclude K */ never
303
+ >,
304
+ /* extract types that might lead to missing property */ Extract<
305
+ PossibleTypeLessAllowed,
306
+ /* types that might lead to missing property, except `bigint` */
307
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
308
+ undefined | symbol | Function
309
+ > extends never
310
+ ? /* all types are supported plus possibly `bigint` => */
311
+ /* check for only `bigint` remaining */ IfSameType<
312
+ PossibleTypeLessAllowed,
313
+ bigint,
314
+ /* only `bigint` => nothing supported */ never,
315
+ /* exclusively supported types (and maybe `bigint`) or exactly `never` */
316
+ /* => check for `never` */ T[K] extends never ? never : K
317
+ >
318
+ : /* value might not be supported => check for any supported */ TestDeserializabilityOf<
319
+ T[K],
320
+ OmitExactlyFromTuple<TExactExceptions, unknown>,
321
+ TExtendsException,
322
+ {
323
+ WhenSomethingDeserializable: /* => check for indexed key */ IfIndexOrBrandedKey<
324
+ K,
325
+ /* indexed => allow K */ K,
326
+ /* literal => exclude K */ never
327
+ >;
328
+ WhenNeverDeserializable: /* => exclude K */ never;
329
+ }
330
+ >
331
+ >
332
+ : never;
333
+ }[Keys],
334
+ undefined | symbol
335
+ > extends infer Result
336
+ ? // Workaround for TypeScript bug/limitation where an alias for a type
337
+ // is not considered the same type when used as an index. This restores
338
+ // the original `Keys` (`keyof T`) type when there is no filtering.
339
+ IfSameType<Keys, Result, Keys, Extract<Result, string | number>>
340
+ : never;
344
341
 
345
342
  /**
346
343
  * Returns non-symbol, literal keys for partially supported properties of an object type.
@@ -357,43 +354,49 @@ export namespace InternalUtilityTypes {
357
354
  TExactExceptions extends unknown[],
358
355
  TExtendsException,
359
356
  Keys extends keyof T = keyof T,
360
- > = Exclude<
361
- {
362
- [K in Keys]: IfIndexOrBrandedKey<
363
- K,
364
- /* indexed => exclude K */ never,
365
- /* literal => ... */
366
- /* all possible types that aren't already allowed, with the exception of `unknown` */
367
- ExcludeExactlyInTuple<
368
- Exclude<T[K], TExtendsException>,
369
- OmitExactlyFromTuple<TExactExceptions, unknown>
370
- > extends infer PossibleTypeLessAllowed
371
- ? Extract<
372
- IfSameType<PossibleTypeLessAllowed, unknown, undefined, PossibleTypeLessAllowed>,
373
- /* types that might lead to missing property */
374
- // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
375
- undefined | symbol | Function
376
- > extends never
377
- ? /* exclusively supported types or exactly `never` */ never
378
- : /* at least some unsupported type => check for any supported */ TestDeserializabilityOf<
379
- T[K],
380
- OmitExactlyFromTuple<TExactExceptions, unknown>,
381
- TExtendsException,
382
- {
383
- WhenSomethingDeserializable: K;
384
- WhenNeverDeserializable: never;
385
- }
386
- >
387
- : never
388
- >;
389
- }[Keys],
390
- undefined | symbol
391
- > extends infer Result
392
- ? // Workaround for TypeScript bug/limitation where an alias for a type
393
- // is not considered the same type when used as an index. This restores
394
- // the original `Keys` (`keyof T`) type when there is no filtering.
395
- IfSameType<Keys, Result, Keys, Extract<Result, string | number>>
396
- : never;
357
+ > =
358
+ Exclude<
359
+ {
360
+ [K in Keys]: IfIndexOrBrandedKey<
361
+ K,
362
+ /* indexed => exclude K */ never,
363
+ /* literal => ... */
364
+ /* all possible types that aren't already allowed, with the exception of `unknown` */
365
+ ExcludeExactlyInTuple<
366
+ Exclude<T[K], TExtendsException>,
367
+ OmitExactlyFromTuple<TExactExceptions, unknown>
368
+ > extends infer PossibleTypeLessAllowed
369
+ ? Extract<
370
+ IfSameType<
371
+ PossibleTypeLessAllowed,
372
+ unknown,
373
+ undefined,
374
+ PossibleTypeLessAllowed
375
+ >,
376
+ /* types that might lead to missing property */
377
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
378
+ undefined | symbol | Function
379
+ > extends never
380
+ ? /* exclusively supported types or exactly `never` */ never
381
+ : /* at least some unsupported type => check for any supported */ TestDeserializabilityOf<
382
+ T[K],
383
+ OmitExactlyFromTuple<TExactExceptions, unknown>,
384
+ TExtendsException,
385
+ {
386
+ WhenSomethingDeserializable: K;
387
+ WhenNeverDeserializable: never;
388
+ }
389
+ >
390
+ : never
391
+ >;
392
+ }[Keys],
393
+ undefined | symbol
394
+ > extends infer Result
395
+ ? // Workaround for TypeScript bug/limitation where an alias for a type
396
+ // is not considered the same type when used as an index. This restores
397
+ // the original `Keys` (`keyof T`) type when there is no filtering.
398
+ IfSameType<Keys, Result, Keys, Extract<Result, string | number>>
399
+ : never;
397
400
 
398
401
  /**
399
402
  * Filters a type `T` for `undefined` that is not viable in an array (or tuple) that
@@ -408,32 +411,33 @@ export namespace InternalUtilityTypes {
408
411
  Controls extends FilterControls,
409
412
  TAncestorTypes extends unknown[],
410
413
  TBlessed,
411
- > = /* Some initial filtering must be provided before a test for undefined. */
412
- /* These tests are expected to match those in JsonSerializableImpl. */
413
- /* test for 'any' */ boolean extends (T extends never ? true : false)
414
- ? /* 'any' => */ TBlessed
415
- : /* test for 'unknown' */ unknown extends T
416
- ? /* 'unknown' => */ TBlessed
417
- : /* test for exact recursion */ IfExactTypeInTuple<
418
- T,
419
- TAncestorTypes,
420
- /* recursion; stop here => */ T,
421
- /* test for JSON primitive types or given alternative */ T extends
422
- | null
423
- | boolean
424
- | number
425
- | string
426
- | Controls["AllowExtensionOf"]
427
- ? /* primitive types or alternative => */ T
428
- : /* test for exact alternative */ IfExactTypeInTuple<
429
- T,
430
- Controls["AllowExactly"],
431
- T,
432
- /* test for undefined possibility */ undefined extends T
433
- ? /* undefined | ... => */ SerializationErrorPerUndefinedArrayElement
434
- : TBlessed
435
- >
436
- >;
414
+ > =
415
+ /* Some initial filtering must be provided before a test for undefined. */
416
+ /* These tests are expected to match those in JsonSerializableImpl. */
417
+ /* test for 'any' */ boolean extends (T extends never ? true : false)
418
+ ? /* 'any' => */ TBlessed
419
+ : /* test for 'unknown' */ unknown extends T
420
+ ? /* 'unknown' => */ TBlessed
421
+ : /* test for exact recursion */ IfExactTypeInTuple<
422
+ T,
423
+ TAncestorTypes,
424
+ /* recursion; stop here => */ T,
425
+ /* test for JSON primitive types or given alternative */ T extends
426
+ | null
427
+ | boolean
428
+ | number
429
+ | string
430
+ | Controls["AllowExtensionOf"]
431
+ ? /* primitive types or alternative => */ T
432
+ : /* test for exact alternative */ IfExactTypeInTuple<
433
+ T,
434
+ Controls["AllowExactly"],
435
+ T,
436
+ /* test for undefined possibility */ undefined extends T
437
+ ? /* undefined | ... => */ SerializationErrorPerUndefinedArrayElement
438
+ : TBlessed
439
+ >
440
+ >;
437
441
 
438
442
  /**
439
443
  * Filters a type `T` for types that become null through JSON serialization.
@@ -444,34 +448,35 @@ export namespace InternalUtilityTypes {
444
448
  T,
445
449
  Controls extends DeserializedFilterControls,
446
450
  TBlessed,
447
- > = /* Some initial filtering must be provided before a test for undefined, symbol, or function. */
448
- /* These tests are expected to match those in JsonDeserializedImpl. */
449
- /* test for 'any' */ boolean extends (T extends never ? true : false)
450
- ? /* 'any' => */ TBlessed
451
- : /* test for 'unknown' */ unknown extends T
452
- ? /* 'unknown' => */ TBlessed
453
- : /* test for JSON primitive types or general alternative */ T extends
454
- | null
455
- | boolean
456
- | number
457
- | string
458
- | Controls["AllowExtensionOf"]
459
- ? /* primitive or replaced types => */ T
460
- : /* test for exact alternative */ IfExactTypeInTuple<
461
- T,
462
- [...Controls["AllowExactly"], Controls["RecursionMarkerAllowed"]],
463
- /* exactly replaced => */ T,
464
- /* test for known types that become null */ T extends undefined | symbol
465
- ? /* => */ null
466
- : // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
467
- T extends Function
468
- ? ExtractFunctionFromIntersection<T> extends {
469
- classification: "exactly Function";
470
- }
471
- ? null
472
- : null | TBlessed
473
- : TBlessed
474
- >;
451
+ > =
452
+ /* Some initial filtering must be provided before a test for undefined, symbol, or function. */
453
+ /* These tests are expected to match those in JsonDeserializedImpl. */
454
+ /* test for 'any' */ boolean extends (T extends never ? true : false)
455
+ ? /* 'any' => */ TBlessed
456
+ : /* test for 'unknown' */ unknown extends T
457
+ ? /* 'unknown' => */ TBlessed
458
+ : /* test for JSON primitive types or general alternative */ T extends
459
+ | null
460
+ | boolean
461
+ | number
462
+ | string
463
+ | Controls["AllowExtensionOf"]
464
+ ? /* primitive or replaced types => */ T
465
+ : /* test for exact alternative */ IfExactTypeInTuple<
466
+ T,
467
+ [...Controls["AllowExactly"], Controls["RecursionMarkerAllowed"]],
468
+ /* exactly replaced => */ T,
469
+ /* test for known types that become null */ T extends undefined | symbol
470
+ ? /* => */ null
471
+ : // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
472
+ T extends Function
473
+ ? ExtractFunctionFromIntersection<T> extends {
474
+ classification: "exactly Function";
475
+ }
476
+ ? null
477
+ : null | TBlessed
478
+ : TBlessed
479
+ >;
475
480
 
476
481
  /**
477
482
  * Checks for a type that is simple class of number and string indexed types to numbers and strings.
@@ -515,11 +520,8 @@ export namespace InternalUtilityTypes {
515
520
  *
516
521
  * @system
517
522
  */
518
- export type IfSameType<X, Y, IfSame = unknown, IfDifferent = never> = (<T>() => T extends X
519
- ? 1
520
- : 2) extends <T>() => T extends Y ? 1 : 2
521
- ? IfSame
522
- : IfDifferent;
523
+ export type IfSameType<X, Y, IfSame = unknown, IfDifferent = never> =
524
+ (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 ? IfSame : IfDifferent;
523
525
 
524
526
  /**
525
527
  * Test for type equality with tuple of other types.
@@ -551,7 +553,7 @@ export namespace InternalUtilityTypes {
551
553
  * @typeParam IfNoMatch - Type to return if no match is found.
552
554
  *
553
555
  * @remarks
554
- * In a recursive context, use {@link InternalUtilityTypes.IfExactTypeInTuple} to manage ancestry.
556
+ * In a recursive context, use {@link InternalCoreInterfacesUtilityTypes.IfExactTypeInTuple} to manage ancestry.
555
557
  *
556
558
  * @privateRemarks
557
559
  * Perhaps it is a Typescript defect but a simple check that `T` is `never`
@@ -701,17 +703,15 @@ export namespace InternalUtilityTypes {
701
703
  *
702
704
  * @system
703
705
  */
704
- export type FilterPreservingFunction<
705
- Original extends object,
706
- Filtered,
707
- > = ExtractFunctionFromIntersection<Original> extends {
708
- classification: infer TClassification;
709
- function: infer TFunction;
710
- }
711
- ? TClassification extends "exactly Function"
712
- ? TFunction
713
- : TFunction & Filtered
714
- : never;
706
+ export type FilterPreservingFunction<Original extends object, Filtered> =
707
+ ExtractFunctionFromIntersection<Original> extends {
708
+ classification: infer TClassification;
709
+ function: infer TFunction;
710
+ }
711
+ ? TClassification extends "exactly Function"
712
+ ? TFunction
713
+ : TFunction & Filtered
714
+ : never;
715
715
 
716
716
  /**
717
717
  * Replaces any instance where a type T recurses into itself or a portion of
@@ -745,36 +745,37 @@ export namespace InternalUtilityTypes {
745
745
  Controls extends FilterControls,
746
746
  TAncestorTypes extends unknown[] = [],
747
747
  TNextAncestor = T,
748
- > = /* test for recursion */
749
- IfExactTypeInTuple<T, TAncestorTypes, true, "no match"> extends true
750
- ? /* recursion => use replacement */ TRecursionMarker
751
- : /* force union separation hereafter */ T extends infer _
752
- ? /* test for recursion among union elements */
753
- IfExactTypeInTuple<T, TAncestorTypes, true, "no match"> extends true
754
- ? TRecursionMarker
755
- : /* test for general allowance */ T extends Controls["AllowExtensionOf"]
756
- ? /* allowed extension type => */ T
757
- : /* test for exact allowance */ IfExactTypeInTuple<
758
- T,
759
- Controls["AllowExactly"],
760
- true,
761
- "no match"
762
- > extends true
763
- ? /* exact allowed type => */ T
764
- : T extends object
765
- ? FilterPreservingFunction<
748
+ > =
749
+ /* test for recursion */
750
+ IfExactTypeInTuple<T, TAncestorTypes, true, "no match"> extends true
751
+ ? /* recursion => use replacement */ TRecursionMarker
752
+ : /* force union separation hereafter */ T extends infer _
753
+ ? /* test for recursion among union elements */
754
+ IfExactTypeInTuple<T, TAncestorTypes, true, "no match"> extends true
755
+ ? TRecursionMarker
756
+ : /* test for general allowance */ T extends Controls["AllowExtensionOf"]
757
+ ? /* allowed extension type => */ T
758
+ : /* test for exact allowance */ IfExactTypeInTuple<
766
759
  T,
767
- {
768
- [K in keyof T]: ReplaceRecursionWithMarkerAndPreserveAllowances<
769
- T[K],
770
- TRecursionMarker,
771
- Controls,
772
- [TNextAncestor, ...TAncestorTypes]
773
- >;
774
- }
775
- >
776
- : /* non-object => T as is */ T
777
- : never;
760
+ Controls["AllowExactly"],
761
+ true,
762
+ "no match"
763
+ > extends true
764
+ ? /* exact allowed type => */ T
765
+ : T extends object
766
+ ? FilterPreservingFunction<
767
+ T,
768
+ {
769
+ [K in keyof T]: ReplaceRecursionWithMarkerAndPreserveAllowances<
770
+ T[K],
771
+ TRecursionMarker,
772
+ Controls,
773
+ [TNextAncestor, ...TAncestorTypes]
774
+ >;
775
+ }
776
+ >
777
+ : /* non-object => T as is */ T
778
+ : never;
778
779
 
779
780
  /**
780
781
  * Replaces any instances of "allowed" types and recursion within with `never`.
@@ -792,41 +793,42 @@ export namespace InternalUtilityTypes {
792
793
  Controls extends FilterControls,
793
794
  TAncestorTypes extends unknown[] = [],
794
795
  TNextAncestor = T,
795
- > = /* test for exact recursion first */ IfExactTypeInTuple<
796
- T,
797
- TAncestorTypes,
798
- true,
799
- "no match"
800
- > extends true
801
- ? /* recursion => */ never
802
- : /* test for general allowance (also forces union separation) */ T extends Controls["AllowExtensionOf"]
803
- ? /* allowed extension type => */ never
804
- : /* test for exact allowance */ IfExactTypeInTuple<
805
- T,
806
- Controls["AllowExactly"],
807
- true,
808
- "no match"
809
- > extends true
810
- ? /* exact allowed type => */ never
811
- : /* test for recursion among union elements */ IfExactTypeInTuple<
796
+ > =
797
+ /* test for exact recursion first */ IfExactTypeInTuple<
798
+ T,
799
+ TAncestorTypes,
800
+ true,
801
+ "no match"
802
+ > extends true
803
+ ? /* recursion => */ never
804
+ : /* test for general allowance (also forces union separation) */ T extends Controls["AllowExtensionOf"]
805
+ ? /* allowed extension type => */ never
806
+ : /* test for exact allowance */ IfExactTypeInTuple<
812
807
  T,
813
- TAncestorTypes,
808
+ Controls["AllowExactly"],
814
809
  true,
815
810
  "no match"
816
811
  > extends true
817
- ? /* recursion => */ never
818
- : T extends object
819
- ? FilterPreservingFunction<
812
+ ? /* exact allowed type => */ never
813
+ : /* test for recursion among union elements */ IfExactTypeInTuple<
820
814
  T,
821
- {
822
- [K in keyof T]: ReplaceAllowancesAndRecursionWithNever<
823
- T[K],
824
- Controls,
825
- [TNextAncestor, ...TAncestorTypes]
826
- >;
827
- }
828
- >
829
- : /* non-object => T as is */ T;
815
+ TAncestorTypes,
816
+ true,
817
+ "no match"
818
+ > extends true
819
+ ? /* recursion => */ never
820
+ : T extends object
821
+ ? FilterPreservingFunction<
822
+ T,
823
+ {
824
+ [K in keyof T]: ReplaceAllowancesAndRecursionWithNever<
825
+ T[K],
826
+ Controls,
827
+ [TNextAncestor, ...TAncestorTypes]
828
+ >;
829
+ }
830
+ >
831
+ : /* non-object => T as is */ T;
830
832
 
831
833
  /**
832
834
  * Test for non-public properties (which can only exist on class instance types).
@@ -849,9 +851,8 @@ export namespace InternalUtilityTypes {
849
851
  Controls extends FilterControls,
850
852
  HasNonPublic = never,
851
853
  OnlyPublics = unknown,
852
- > = ReplaceAllowancesAndRecursionWithNever<T, Controls> extends T
853
- ? OnlyPublics
854
- : HasNonPublic;
854
+ > =
855
+ ReplaceAllowancesAndRecursionWithNever<T, Controls> extends T ? OnlyPublics : HasNonPublic;
855
856
 
856
857
  /**
857
858
  * Union of all types in a tuple.
@@ -878,74 +879,75 @@ export namespace InternalUtilityTypes {
878
879
  },
879
880
  TAncestorTypes extends unknown[] = [],
880
881
  TNextAncestor = T,
881
- > = /* Build Controls from Options filling in defaults for any missing properties */
882
- {
883
- AllowExactly: Options extends { AllowExactly: unknown[] } ? Options["AllowExactly"] : [];
884
- AllowExtensionOf: Options extends { AllowExtensionOf: unknown }
885
- ? Options["AllowExtensionOf"]
886
- : never;
887
- // The Substitute type could be extracted to helper type, but is kept explicit here
888
- // to make JsonTypeWith and OpaqueJsonSerializable show explicitly in results for
889
- // users, rather than either the helper type name or a partially unrolled version.
890
- DegenerateSubstitute:
891
- | JsonTypeWith<
892
- | (Options extends { AllowExactly: unknown[] }
893
- ? TupleToUnion<Options["AllowExactly"]>
894
- : never)
895
- | (Options extends { AllowExtensionOf: unknown }
896
- ? Options["AllowExtensionOf"]
897
- : never)
898
- >
899
- | OpaqueJsonSerializable<
900
- unknown,
901
- Options extends { AllowExactly: unknown[] } ? Options["AllowExactly"] : [],
902
- Options extends { AllowExtensionOf: unknown } ? Options["AllowExtensionOf"] : never
903
- >;
904
- } extends infer Controls
905
- ? /* Controls should always satisfy FilterControlsWithSubstitution, but Typescript wants a check */
906
- Controls extends FilterControlsWithSubstitution
907
- ? /* test for 'any' */ boolean extends (T extends never ? true : false)
908
- ? /* 'any' => */ Controls["DegenerateSubstitute"]
909
- : Options extends { IgnoreInaccessibleMembers: "ignore-inaccessible-members" }
910
- ? JsonSerializableFilter<T, Controls, TAncestorTypes, TNextAncestor>
911
- : /* test for non-public properties (class instance type) */
912
- IfNonPublicProperties<
913
- T,
914
- {
915
- AllowExactly: Controls["AllowExactly"];
916
- AllowExtensionOf:
917
- | Controls["AllowExtensionOf"]
918
- // Add in primitives that may be branded to ignore intersection classes
919
- | boolean
920
- | number
921
- | string
922
- // Add in OpaqueJson* types
923
- | AnyOpaqueJsonType;
924
- },
925
- "found non-publics",
926
- "only publics"
927
- > extends "found non-publics"
928
- ? /* hidden props => test if it is array properties that are the problem */ T extends readonly (infer _)[]
929
- ? /* array => */ {
930
- /* use homomorphic mapped type to preserve tuple type */
931
- [K in keyof T]: JsonSerializableImpl<
932
- T[K],
933
- Controls,
934
- [TNextAncestor, ...TAncestorTypes]
935
- >;
936
- }
937
- : /* test for potentially branded primitive (intersection with a supported primitive) */
938
- T extends boolean | number | string
939
- ? /* assume intersection is branding and allow as-is => */ T
940
- : /* not array => error */ SerializationErrorPerNonPublicProperties
941
- : /* no hidden properties => apply filtering => */ JsonSerializableFilter<
942
- T,
943
- Controls,
944
- TAncestorTypes,
945
- TNextAncestor
946
- >
947
- : never /* FilterControlsWithSubstitution assert else; should never be reached */
948
- : never /* unreachable else for infer */;
882
+ > =
883
+ /* Build Controls from Options filling in defaults for any missing properties */
884
+ {
885
+ AllowExactly: Options extends { AllowExactly: unknown[] } ? Options["AllowExactly"] : [];
886
+ AllowExtensionOf: Options extends { AllowExtensionOf: unknown }
887
+ ? Options["AllowExtensionOf"]
888
+ : never;
889
+ // The Substitute type could be extracted to helper type, but is kept explicit here
890
+ // to make JsonTypeWith and OpaqueJsonSerializable show explicitly in results for
891
+ // users, rather than either the helper type name or a partially unrolled version.
892
+ DegenerateSubstitute:
893
+ | JsonTypeWith<
894
+ | (Options extends { AllowExactly: unknown[] }
895
+ ? TupleToUnion<Options["AllowExactly"]>
896
+ : never)
897
+ | (Options extends { AllowExtensionOf: unknown }
898
+ ? Options["AllowExtensionOf"]
899
+ : never)
900
+ >
901
+ | OpaqueJsonSerializable<
902
+ unknown,
903
+ Options extends { AllowExactly: unknown[] } ? Options["AllowExactly"] : [],
904
+ Options extends { AllowExtensionOf: unknown } ? Options["AllowExtensionOf"] : never
905
+ >;
906
+ } extends infer Controls
907
+ ? /* Controls should always satisfy FilterControlsWithSubstitution, but Typescript wants a check */
908
+ Controls extends FilterControlsWithSubstitution
909
+ ? /* test for 'any' */ boolean extends (T extends never ? true : false)
910
+ ? /* 'any' => */ Controls["DegenerateSubstitute"]
911
+ : Options extends { IgnoreInaccessibleMembers: "ignore-inaccessible-members" }
912
+ ? JsonSerializableFilter<T, Controls, TAncestorTypes, TNextAncestor>
913
+ : /* test for non-public properties (class instance type) */
914
+ IfNonPublicProperties<
915
+ T,
916
+ {
917
+ AllowExactly: Controls["AllowExactly"];
918
+ AllowExtensionOf:
919
+ | Controls["AllowExtensionOf"]
920
+ // Add in primitives that may be branded to ignore intersection classes
921
+ | boolean
922
+ | number
923
+ | string
924
+ // Add in OpaqueJson* types
925
+ | AnyOpaqueJsonType;
926
+ },
927
+ "found non-publics",
928
+ "only publics"
929
+ > extends "found non-publics"
930
+ ? /* hidden props => test if it is array properties that are the problem */ T extends readonly (infer _)[]
931
+ ? /* array => */ {
932
+ /* use homomorphic mapped type to preserve tuple type */
933
+ [K in keyof T]: JsonSerializableImpl<
934
+ T[K],
935
+ Controls,
936
+ [TNextAncestor, ...TAncestorTypes]
937
+ >;
938
+ }
939
+ : /* test for potentially branded primitive (intersection with a supported primitive) */
940
+ T extends boolean | number | string
941
+ ? /* assume intersection is branding and allow as-is => */ T
942
+ : /* not array => error */ SerializationErrorPerNonPublicProperties
943
+ : /* no hidden properties => apply filtering => */ JsonSerializableFilter<
944
+ T,
945
+ Controls,
946
+ TAncestorTypes,
947
+ TNextAncestor
948
+ >
949
+ : never /* FilterControlsWithSubstitution assert else; should never be reached */
950
+ : never /* unreachable else for infer */;
949
951
 
950
952
  /**
951
953
  * Handle OpaqueJson* types for {@link JsonSerializable}.
@@ -968,28 +970,41 @@ export namespace InternalUtilityTypes {
968
970
  export type JsonSerializableOpaqueAllowances<
969
971
  T extends AnyOpaqueJsonType,
970
972
  Controls extends FilterControlsWithSubstitution,
971
- > = /* eslint-disable @typescript-eslint/no-explicit-any -- must use `any` for invariant constraint override */
972
- /* infer underlying data type */ T extends
973
- | OpaqueJsonSerializable<infer TData, any, unknown>
974
- | OpaqueJsonDeserialized<infer TData, any, unknown>
975
- ? T extends OpaqueJsonSerializable<TData, any, unknown> &
976
- OpaqueJsonDeserialized<TData, any, unknown>
977
- ? OpaqueJsonSerializable<TData, Controls["AllowExactly"], Controls["AllowExtensionOf"]> &
978
- OpaqueJsonDeserialized<TData, Controls["AllowExactly"], Controls["AllowExtensionOf"]>
979
- : T extends OpaqueJsonSerializable<TData, any, unknown>
980
- ? OpaqueJsonSerializable<TData, Controls["AllowExactly"], Controls["AllowExtensionOf"]>
981
- : T extends OpaqueJsonDeserialized<TData, any, unknown>
982
- ? OpaqueJsonDeserialized<
973
+ > =
974
+ /* eslint-disable @typescript-eslint/no-explicit-any -- must use `any` for invariant constraint override */
975
+ /* infer underlying data type */ T extends
976
+ | OpaqueJsonSerializable<infer TData, any, unknown>
977
+ | OpaqueJsonDeserialized<infer TData, any, unknown>
978
+ ? T extends OpaqueJsonSerializable<TData, any, unknown> &
979
+ OpaqueJsonDeserialized<TData, any, unknown>
980
+ ? OpaqueJsonSerializable<
981
+ TData,
982
+ Controls["AllowExactly"],
983
+ Controls["AllowExtensionOf"]
984
+ > &
985
+ OpaqueJsonDeserialized<
983
986
  TData,
984
987
  Controls["AllowExactly"],
985
988
  Controls["AllowExtensionOf"]
986
989
  >
987
- : "internal error: failed to determine OpaqueJson* type"
988
- : never;
990
+ : T extends OpaqueJsonSerializable<TData, any, unknown>
991
+ ? OpaqueJsonSerializable<
992
+ TData,
993
+ Controls["AllowExactly"],
994
+ Controls["AllowExtensionOf"]
995
+ >
996
+ : T extends OpaqueJsonDeserialized<TData, any, unknown>
997
+ ? OpaqueJsonDeserialized<
998
+ TData,
999
+ Controls["AllowExactly"],
1000
+ Controls["AllowExtensionOf"]
1001
+ >
1002
+ : "internal error: failed to determine OpaqueJson* type"
1003
+ : never;
989
1004
  /* eslint-enable @typescript-eslint/no-explicit-any */
990
1005
 
991
1006
  /**
992
- * Helper for {@link JsonSerializableFilter} to determine if a property may
1007
+ * Helper for {@link InternalCoreInterfacesUtilityTypes.JsonSerializableFilter} to determine if a property may
993
1008
  * be `undefined` and selects from options for result.
994
1009
  * Since `unknown` is a superset of `undefined`, it is given a special case.
995
1010
  * Additionally since index signatures are inherently optional, `unknown` typed
@@ -1153,79 +1168,90 @@ export namespace InternalUtilityTypes {
1153
1168
  T,
1154
1169
  Options extends Partial<FilterControls>,
1155
1170
  TypeUnderRecursion extends boolean = false,
1156
- > = /* Build Controls from Options filling in defaults for any missing properties */
1157
- {
1158
- AllowExactly: Options extends { AllowExactly: unknown[] } ? Options["AllowExactly"] : [];
1159
- AllowExtensionOf: Options extends { AllowExtensionOf: unknown }
1160
- ? Options["AllowExtensionOf"]
1161
- : never;
1162
- // The Substitute types could be extracted to helper type, but are kept explicit here
1163
- // to make JsonTypeWith/NonNullJsonObjectWith show explicitly in results for users, rather
1164
- // than either the helper type name or a partially unrolled version.
1165
- DegenerateSubstitute: JsonTypeWith<
1166
- | (Options extends { AllowExactly: unknown[] }
1167
- ? TupleToUnion<Options["AllowExactly"]>
1168
- : never)
1169
- | (Options extends { AllowExtensionOf: unknown } ? Options["AllowExtensionOf"] : never)
1170
- >;
1171
- DegenerateNonNullObjectSubstitute: NonNullJsonObjectWith<
1172
- | (Options extends { AllowExactly: unknown[] }
1173
- ? TupleToUnion<Options["AllowExactly"]>
1174
- : never)
1175
- | (Options extends { AllowExtensionOf: unknown } ? Options["AllowExtensionOf"] : never)
1176
- >;
1177
- RecursionMarkerAllowed: never;
1178
- } extends infer Controls
1179
- ? /* Controls should always satisfy DeserializedFilterControls, but Typescript wants a check */
1180
- Controls extends DeserializedFilterControls
1181
- ? /* test for 'any' */ boolean extends (T extends never ? true : false)
1182
- ? /* 'any' => */ Controls["DegenerateSubstitute"]
1183
- : /* infer non-recursive version of T */ ReplaceRecursionWithMarkerAndPreserveAllowances<
1184
- T,
1185
- RecursionMarker,
1186
- {
1187
- AllowExactly: Controls["AllowExactly"];
1188
- AllowExtensionOf:
1189
- | Controls["AllowExtensionOf"]
1190
- // Also preserve OpaqueJson* types
1191
- | AnyOpaqueJsonType;
1192
- }
1193
- > extends infer TNoRecursionAndOnlyPublics
1194
- ? /* test for no change from filtered type */ IsSameType<
1195
- TNoRecursionAndOnlyPublics,
1196
- JsonDeserializedFilter<
1197
- TNoRecursionAndOnlyPublics,
1198
- {
1199
- AllowExactly: Controls["AllowExactly"];
1200
- AllowExtensionOf: Controls["AllowExtensionOf"];
1201
- DegenerateSubstitute: Controls["DegenerateSubstitute"];
1202
- DegenerateNonNullObjectSubstitute: Controls["DegenerateNonNullObjectSubstitute"];
1203
- RecursionMarkerAllowed: RecursionMarker;
1204
- }
1205
- >
1206
- > extends true
1207
- ? /* same (no filtering needed) => test for non-public
1208
- properties (class instance type) */
1209
- IfNonPublicProperties<
1171
+ > =
1172
+ /* Build Controls from Options filling in defaults for any missing properties */
1173
+ {
1174
+ AllowExactly: Options extends { AllowExactly: unknown[] } ? Options["AllowExactly"] : [];
1175
+ AllowExtensionOf: Options extends { AllowExtensionOf: unknown }
1176
+ ? Options["AllowExtensionOf"]
1177
+ : never;
1178
+ // The Substitute types could be extracted to helper type, but are kept explicit here
1179
+ // to make JsonTypeWith/NonNullJsonObjectWith show explicitly in results for users, rather
1180
+ // than either the helper type name or a partially unrolled version.
1181
+ DegenerateSubstitute: JsonTypeWith<
1182
+ | (Options extends { AllowExactly: unknown[] }
1183
+ ? TupleToUnion<Options["AllowExactly"]>
1184
+ : never)
1185
+ | (Options extends { AllowExtensionOf: unknown } ? Options["AllowExtensionOf"] : never)
1186
+ >;
1187
+ DegenerateNonNullObjectSubstitute: NonNullJsonObjectWith<
1188
+ | (Options extends { AllowExactly: unknown[] }
1189
+ ? TupleToUnion<Options["AllowExactly"]>
1190
+ : never)
1191
+ | (Options extends { AllowExtensionOf: unknown } ? Options["AllowExtensionOf"] : never)
1192
+ >;
1193
+ RecursionMarkerAllowed: never;
1194
+ } extends infer Controls
1195
+ ? /* Controls should always satisfy DeserializedFilterControls, but Typescript wants a check */
1196
+ Controls extends DeserializedFilterControls
1197
+ ? /* test for 'any' */ boolean extends (T extends never ? true : false)
1198
+ ? /* 'any' => */ Controls["DegenerateSubstitute"]
1199
+ : /* infer non-recursive version of T */ ReplaceRecursionWithMarkerAndPreserveAllowances<
1210
1200
  T,
1211
- // Note: no extra allowance is made here for possible branded
1212
- // primitives as JsonDeserializedFilter will allow them as
1213
- // extensions of the primitives. Should there be a need to
1214
- // explicitly allow them here, see JsonSerializableImpl's use.
1201
+ RecursionMarker,
1215
1202
  {
1216
1203
  AllowExactly: Controls["AllowExactly"];
1217
1204
  AllowExtensionOf:
1218
1205
  | Controls["AllowExtensionOf"]
1219
- // Add in OpaqueJson* types
1206
+ // Also preserve OpaqueJson* types
1220
1207
  | AnyOpaqueJsonType;
1221
- },
1222
- "found non-publics",
1223
- "only publics"
1224
- > extends "found non-publics"
1225
- ? /* hidden props => apply filtering to avoid retaining
1208
+ }
1209
+ > extends infer TNoRecursionAndOnlyPublics
1210
+ ? /* test for no change from filtered type */ IsSameType<
1211
+ TNoRecursionAndOnlyPublics,
1212
+ JsonDeserializedFilter<
1213
+ TNoRecursionAndOnlyPublics,
1214
+ {
1215
+ AllowExactly: Controls["AllowExactly"];
1216
+ AllowExtensionOf: Controls["AllowExtensionOf"];
1217
+ DegenerateSubstitute: Controls["DegenerateSubstitute"];
1218
+ DegenerateNonNullObjectSubstitute: Controls["DegenerateNonNullObjectSubstitute"];
1219
+ RecursionMarkerAllowed: RecursionMarker;
1220
+ }
1221
+ >
1222
+ > extends true
1223
+ ? /* same (no filtering needed) => test for non-public
1224
+ properties (class instance type) */
1225
+ IfNonPublicProperties<
1226
+ T,
1227
+ // Note: no extra allowance is made here for possible branded
1228
+ // primitives as JsonDeserializedFilter will allow them as
1229
+ // extensions of the primitives. Should there be a need to
1230
+ // explicitly allow them here, see JsonSerializableImpl's use.
1231
+ {
1232
+ AllowExactly: Controls["AllowExactly"];
1233
+ AllowExtensionOf:
1234
+ | Controls["AllowExtensionOf"]
1235
+ // Add in OpaqueJson* types
1236
+ | AnyOpaqueJsonType;
1237
+ },
1238
+ "found non-publics",
1239
+ "only publics"
1240
+ > extends "found non-publics"
1241
+ ? /* hidden props => apply filtering to avoid retaining
1226
1242
  exact class except for any classes in allowances =>
1227
1243
  test for known recursion */
1228
- TypeUnderRecursion extends false
1244
+ TypeUnderRecursion extends false
1245
+ ? /* no known recursion => */ JsonDeserializedFilter<T, Controls>
1246
+ : /* known recursion => use OpaqueJsonDeserialized for later processing */
1247
+ OpaqueJsonDeserialized<
1248
+ T,
1249
+ Controls["AllowExactly"],
1250
+ Controls["AllowExtensionOf"]
1251
+ >
1252
+ : /* no hidden properties => deserialized T is just T */
1253
+ T
1254
+ : /* filtering is needed => test for known recursion */ TypeUnderRecursion extends false
1229
1255
  ? /* no known recursion => */ JsonDeserializedFilter<T, Controls>
1230
1256
  : /* known recursion => use OpaqueJsonDeserialized for later processing */
1231
1257
  OpaqueJsonDeserialized<
@@ -1233,22 +1259,12 @@ export namespace InternalUtilityTypes {
1233
1259
  Controls["AllowExactly"],
1234
1260
  Controls["AllowExtensionOf"]
1235
1261
  >
1236
- : /* no hidden properties => deserialized T is just T */
1237
- T
1238
- : /* filtering is needed => test for known recursion */ TypeUnderRecursion extends false
1239
- ? /* no known recursion => */ JsonDeserializedFilter<T, Controls>
1240
- : /* known recursion => use OpaqueJsonDeserialized for later processing */
1241
- OpaqueJsonDeserialized<
1242
- T,
1243
- Controls["AllowExactly"],
1244
- Controls["AllowExtensionOf"]
1245
- >
1246
- : /* unreachable else for infer */ never
1247
- : never /* DeserializedFilterControls assert else; should never be reached */
1248
- : never /* unreachable else for infer */;
1262
+ : /* unreachable else for infer */ never
1263
+ : never /* DeserializedFilterControls assert else; should never be reached */
1264
+ : never /* unreachable else for infer */;
1249
1265
 
1250
1266
  /**
1251
- * Recurses `T` applying {@link InternalUtilityTypes.JsonDeserializedFilter} up until
1267
+ * Recurses `T` applying {@link InternalCoreInterfacesUtilityTypes.JsonDeserializedFilter} up until
1252
1268
  * `T` is found to be a match of an ancestor type. At that point `T` is wrapped in
1253
1269
  * {@link OpaqueJsonDeserialized} to avoid further immediate processing, if
1254
1270
  * modification is needed. Caller will need to unwrap the type to continue processing.
@@ -1265,27 +1281,28 @@ export namespace InternalUtilityTypes {
1265
1281
  T,
1266
1282
  Controls extends DeserializedFilterControls,
1267
1283
  TAncestorTypes extends object[],
1268
- > = IfExactTypeInTuple<T, TAncestorTypes, true, "no match"> extends true
1269
- ? /* recursion found => reprocess that recursive type directly to avoid
1284
+ > =
1285
+ IfExactTypeInTuple<T, TAncestorTypes, true, "no match"> extends true
1286
+ ? /* recursion found => reprocess that recursive type directly to avoid
1270
1287
  any collateral damage from ancestor type that required modification.
1271
1288
  Further recursion will not happen during processing. Either:
1272
1289
  - the type requires modification and the `TypeUnderRecursion=true`
1273
1290
  arg will result in `OpaqueJsonDeserialized<T>` wrapper OR
1274
1291
  - no change is needed from this point and `T` will result. */
1275
- JsonDeserializedImpl<T, Controls, true>
1276
- : T extends object
1277
- ? IfExactTypeInTuple<T, TAncestorTypes, true, "no match"> extends true
1278
- ? JsonDeserializedImpl<T, Controls, true>
1279
- : /* no recursion yet detected => */ JsonDeserializedFilter<
1292
+ JsonDeserializedImpl<T, Controls, true>
1293
+ : T extends object
1294
+ ? IfExactTypeInTuple<T, TAncestorTypes, true, "no match"> extends true
1295
+ ? JsonDeserializedImpl<T, Controls, true>
1296
+ : /* no recursion yet detected => */ JsonDeserializedFilter<
1297
+ T,
1298
+ Controls,
1299
+ [...TAncestorTypes, T]
1300
+ >
1301
+ : /* not an object (no recursion) => */ JsonDeserializedFilter<
1280
1302
  T,
1281
1303
  Controls,
1282
- [...TAncestorTypes, T]
1283
- >
1284
- : /* not an object (no recursion) => */ JsonDeserializedFilter<
1285
- T,
1286
- Controls,
1287
- TAncestorTypes
1288
- >;
1304
+ TAncestorTypes
1305
+ >;
1289
1306
 
1290
1307
  /**
1291
1308
  * Handle OpaqueJson* types for {@link JsonDeserialized}.
@@ -1308,12 +1325,13 @@ export namespace InternalUtilityTypes {
1308
1325
  export type JsonDeserializedOpaqueConversion<
1309
1326
  T extends AnyOpaqueJsonType,
1310
1327
  Controls extends FilterControls,
1311
- > = /* eslint-disable @typescript-eslint/no-explicit-any -- must use `any` for invariant constraint override */
1312
- T extends
1313
- | OpaqueJsonSerializable<infer TData, any, unknown>
1314
- | OpaqueJsonDeserialized<infer TData, any, unknown>
1315
- ? OpaqueJsonDeserialized<TData, Controls["AllowExactly"], Controls["AllowExtensionOf"]>
1316
- : "internal error: failed to determine OpaqueJson* type";
1328
+ > =
1329
+ /* eslint-disable @typescript-eslint/no-explicit-any -- must use `any` for invariant constraint override */
1330
+ T extends
1331
+ | OpaqueJsonSerializable<infer TData, any, unknown>
1332
+ | OpaqueJsonDeserialized<infer TData, any, unknown>
1333
+ ? OpaqueJsonDeserialized<TData, Controls["AllowExactly"], Controls["AllowExtensionOf"]>
1334
+ : "internal error: failed to determine OpaqueJson* type";
1317
1335
  /* eslint-enable @typescript-eslint/no-explicit-any */
1318
1336
 
1319
1337
  /**
@@ -1418,14 +1436,15 @@ export namespace InternalUtilityTypes {
1418
1436
  DeepenedGenerics extends ReadonlySupportedGenerics,
1419
1437
  NoDepthOrRecurseLimit extends "Shallow" | DeepReadonlyRecursionLimit,
1420
1438
  Else,
1421
- > = T extends ReadonlyMap<infer K, infer V>
1422
- ? Map<K, V> extends DeepenedGenerics
1423
- ? ReadonlyMap<
1424
- ReadonlyImpl<K, DeepenedGenerics, NoDepthOrRecurseLimit>,
1425
- ReadonlyImpl<V, DeepenedGenerics, NoDepthOrRecurseLimit>
1426
- >
1427
- : ReadonlyMap<K, V>
1428
- : Else;
1439
+ > =
1440
+ T extends ReadonlyMap<infer K, infer V>
1441
+ ? Map<K, V> extends DeepenedGenerics
1442
+ ? ReadonlyMap<
1443
+ ReadonlyImpl<K, DeepenedGenerics, NoDepthOrRecurseLimit>,
1444
+ ReadonlyImpl<V, DeepenedGenerics, NoDepthOrRecurseLimit>
1445
+ >
1446
+ : ReadonlyMap<K, V>
1447
+ : Else;
1429
1448
 
1430
1449
  /**
1431
1450
  * If `T` is a `Set<TSet>` or `ReadonlySet<TSet>`, returns `ReadonlySet` and,
@@ -1439,11 +1458,12 @@ export namespace InternalUtilityTypes {
1439
1458
  DeepenedGenerics extends ReadonlySupportedGenerics,
1440
1459
  NoDepthOrRecurseLimit extends "Shallow" | DeepReadonlyRecursionLimit,
1441
1460
  Else,
1442
- > = T extends ReadonlySet<infer V>
1443
- ? Set<V> extends DeepenedGenerics
1444
- ? ReadonlySet<ReadonlyImpl<V, DeepenedGenerics, NoDepthOrRecurseLimit>>
1445
- : ReadonlySet<V>
1446
- : Else;
1461
+ > =
1462
+ T extends ReadonlySet<infer V>
1463
+ ? Set<V> extends DeepenedGenerics
1464
+ ? ReadonlySet<ReadonlyImpl<V, DeepenedGenerics, NoDepthOrRecurseLimit>>
1465
+ : ReadonlySet<V>
1466
+ : Else;
1447
1467
 
1448
1468
  /**
1449
1469
  * If `T` is a `IFluidHandle<THandle>` and if `T` extends `DeepenedGenerics`,
@@ -1457,11 +1477,12 @@ export namespace InternalUtilityTypes {
1457
1477
  DeepenedGenerics extends ReadonlySupportedGenerics,
1458
1478
  NoDepthOrRecurseLimit extends "Shallow" | DeepReadonlyRecursionLimit,
1459
1479
  Else,
1460
- > = T extends Readonly<IFluidHandle<infer V>>
1461
- ? IFluidHandle<V> extends DeepenedGenerics
1462
- ? Readonly<IFluidHandle<ReadonlyImpl<V, DeepenedGenerics, NoDepthOrRecurseLimit>>>
1463
- : Readonly<T>
1464
- : Else;
1480
+ > =
1481
+ T extends Readonly<IFluidHandle<infer V>>
1482
+ ? IFluidHandle<V> extends DeepenedGenerics
1483
+ ? Readonly<IFluidHandle<ReadonlyImpl<V, DeepenedGenerics, NoDepthOrRecurseLimit>>>
1484
+ : Readonly<T>
1485
+ : Else;
1465
1486
 
1466
1487
  /**
1467
1488
  * If `T` is a `Promise<TPromise>` and if `T` extends `DeepenedGenerics`,
@@ -1475,11 +1496,12 @@ export namespace InternalUtilityTypes {
1475
1496
  DeepenedGenerics extends ReadonlySupportedGenerics,
1476
1497
  NoDepthOrRecurseLimit extends "Shallow" | DeepReadonlyRecursionLimit,
1477
1498
  Else,
1478
- > = T extends Promise<infer V>
1479
- ? Promise<V> extends DeepenedGenerics
1480
- ? Promise<ReadonlyImpl<V, DeepenedGenerics, NoDepthOrRecurseLimit>>
1481
- : T
1482
- : Else;
1499
+ > =
1500
+ T extends Promise<infer V>
1501
+ ? Promise<V> extends DeepenedGenerics
1502
+ ? Promise<ReadonlyImpl<V, DeepenedGenerics, NoDepthOrRecurseLimit>>
1503
+ : T
1504
+ : Else;
1483
1505
 
1484
1506
  /**
1485
1507
  * If `T` is a `WeakMap<K,V>`, returns immutable `WeakMap` and,
@@ -1493,17 +1515,18 @@ export namespace InternalUtilityTypes {
1493
1515
  DeepenedGenerics extends ReadonlySupportedGenerics,
1494
1516
  NoDepthOrRecurseLimit extends "Shallow" | DeepReadonlyRecursionLimit,
1495
1517
  Else,
1496
- > = T extends Omit<WeakMap<infer K, infer V>, "delete" | "set">
1497
- ? WeakMap<K, V> extends DeepenedGenerics
1498
- ? Omit<
1499
- WeakMap<
1500
- ReadonlyImpl<K, DeepenedGenerics, NoDepthOrRecurseLimit>,
1501
- ReadonlyImpl<V, DeepenedGenerics, NoDepthOrRecurseLimit>
1502
- >,
1503
- "delete" | "set"
1504
- >
1505
- : Omit<WeakMap<K, V>, "delete" | "set">
1506
- : Else;
1518
+ > =
1519
+ T extends Omit<WeakMap<infer K, infer V>, "delete" | "set">
1520
+ ? WeakMap<K, V> extends DeepenedGenerics
1521
+ ? Omit<
1522
+ WeakMap<
1523
+ ReadonlyImpl<K, DeepenedGenerics, NoDepthOrRecurseLimit>,
1524
+ ReadonlyImpl<V, DeepenedGenerics, NoDepthOrRecurseLimit>
1525
+ >,
1526
+ "delete" | "set"
1527
+ >
1528
+ : Omit<WeakMap<K, V>, "delete" | "set">
1529
+ : Else;
1507
1530
 
1508
1531
  /**
1509
1532
  * If `T` is a `WeakSet<TSet>`, returns immutable `WeakSet` and,
@@ -1517,14 +1540,15 @@ export namespace InternalUtilityTypes {
1517
1540
  DeepenedGenerics extends ReadonlySupportedGenerics,
1518
1541
  NoDepthOrRecurseLimit extends "Shallow" | DeepReadonlyRecursionLimit,
1519
1542
  Else,
1520
- > = T extends Omit<WeakSet<infer V>, "add" | "delete">
1521
- ? WeakSet<V> extends DeepenedGenerics
1522
- ? Omit<
1523
- WeakSet<ReadonlyImpl<V, DeepenedGenerics, NoDepthOrRecurseLimit>>,
1524
- "add" | "delete"
1525
- >
1526
- : Omit<WeakSet<V>, "add" | "delete">
1527
- : Else;
1543
+ > =
1544
+ T extends Omit<WeakSet<infer V>, "add" | "delete">
1545
+ ? WeakSet<V> extends DeepenedGenerics
1546
+ ? Omit<
1547
+ WeakSet<ReadonlyImpl<V, DeepenedGenerics, NoDepthOrRecurseLimit>>,
1548
+ "add" | "delete"
1549
+ >
1550
+ : Omit<WeakSet<V>, "add" | "delete">
1551
+ : Else;
1528
1552
 
1529
1553
  /**
1530
1554
  * If `T` is a {@link ReadonlySupportedGenerics}, `T` is returned as
@@ -1577,19 +1601,17 @@ export namespace InternalUtilityTypes {
1577
1601
  *
1578
1602
  * @system
1579
1603
  */
1580
- export type PreserveErasedTypeOrBrandedPrimitive<
1581
- T extends object,
1582
- Else,
1583
- > = /* Test for erased type */ T extends ErasedType<infer _>
1584
- ? /* erased type => keep as-is */ T
1585
- : /* Test for branded primitive */ T extends infer Brand &
1586
- (boolean | number | string | symbol | bigint)
1587
- ? // Should just return T here, but TypeScript appears to produce `never` when doing so.
1588
- // Workaround by inferring the Primitive type and returning intersection with B.
1589
- T extends Brand & infer Primitive
1590
- ? /* [potentially] branded type => "as-is" */ Primitive & Brand
1591
- : /* Should never be reached */ T
1592
- : Else;
1604
+ export type PreserveErasedTypeOrBrandedPrimitive<T extends object, Else> =
1605
+ /* Test for erased type */ T extends ErasedType<infer _>
1606
+ ? /* erased type => keep as-is */ T
1607
+ : /* Test for branded primitive */ T extends infer Brand &
1608
+ (boolean | number | string | symbol | bigint)
1609
+ ? // Should just return T here, but TypeScript appears to produce `never` when doing so.
1610
+ // Workaround by inferring the Primitive type and returning intersection with B.
1611
+ T extends Brand & infer Primitive
1612
+ ? /* [potentially] branded type => "as-is" */ Primitive & Brand
1613
+ : /* Should never be reached */ T
1614
+ : Else;
1593
1615
 
1594
1616
  /**
1595
1617
  * De-multiplexing implementation of {@link DeepReadonly} and {@link ShallowReadonly}
@@ -1724,43 +1746,44 @@ export namespace InternalUtilityTypes {
1724
1746
  T,
1725
1747
  DeepenedGenerics extends ReadonlySupportedGenerics,
1726
1748
  NoDepthOrRecurseLimit extends RecursionLimit,
1727
- > = /* infer non-recursive version of T */ ReplaceRecursionWithMarkerAndPreserveAllowances<
1728
- T,
1729
- RecursionMarker,
1730
- { AllowExactly: []; AllowExtensionOf: never }
1731
- > extends infer TNoRecursionAndOnlyPublics
1732
- ? /* test for no change from altered type (excluding non-publics) */ IsSameType<
1733
- TNoRecursionAndOnlyPublics,
1734
- DeepReadonlyWorker<TNoRecursionAndOnlyPublics, DeepenedGenerics, 0>
1735
- > extends true
1736
- ? /* same (no filtering needed) => test for non-public properties (class instance type) */
1737
- IfNonPublicProperties<
1738
- T,
1739
- // Note: no extra allowance is made here for possible branded
1740
- // primitives as DeepReadonlyWorker will allow them as
1741
- // extensions of the primitives. Should there need a need to
1742
- // explicit allow them here, see JsonSerializableImpl's use.
1743
- { AllowExactly: []; AllowExtensionOf: never },
1744
- "found non-publics",
1745
- "only publics"
1746
- > extends "found non-publics"
1747
- ? /* hidden props => apply filtering => */
1748
- DeepReadonlyWorker<
1749
+ > =
1750
+ /* infer non-recursive version of T */ ReplaceRecursionWithMarkerAndPreserveAllowances<
1751
+ T,
1752
+ RecursionMarker,
1753
+ { AllowExactly: []; AllowExtensionOf: never }
1754
+ > extends infer TNoRecursionAndOnlyPublics
1755
+ ? /* test for no change from altered type (excluding non-publics) */ IsSameType<
1756
+ TNoRecursionAndOnlyPublics,
1757
+ DeepReadonlyWorker<TNoRecursionAndOnlyPublics, DeepenedGenerics, 0>
1758
+ > extends true
1759
+ ? /* same (no filtering needed) => test for non-public properties (class instance type) */
1760
+ IfNonPublicProperties<
1761
+ T,
1762
+ // Note: no extra allowance is made here for possible branded
1763
+ // primitives as DeepReadonlyWorker will allow them as
1764
+ // extensions of the primitives. Should there need a need to
1765
+ // explicit allow them here, see JsonSerializableImpl's use.
1766
+ { AllowExactly: []; AllowExtensionOf: never },
1767
+ "found non-publics",
1768
+ "only publics"
1769
+ > extends "found non-publics"
1770
+ ? /* hidden props => apply filtering => */
1771
+ DeepReadonlyWorker<
1772
+ T,
1773
+ DeepenedGenerics,
1774
+ Extract<NoDepthOrRecurseLimit, RecursionLimit>
1775
+ >
1776
+ : /* no hidden properties => readonly T is just T */
1777
+ T
1778
+ : /* filtering is needed => */ DeepReadonlyWorker<
1749
1779
  T,
1750
1780
  DeepenedGenerics,
1751
1781
  Extract<NoDepthOrRecurseLimit, RecursionLimit>
1752
1782
  >
1753
- : /* no hidden properties => readonly T is just T */
1754
- T
1755
- : /* filtering is needed => */ DeepReadonlyWorker<
1756
- T,
1757
- DeepenedGenerics,
1758
- Extract<NoDepthOrRecurseLimit, RecursionLimit>
1759
- >
1760
- : /* unreachable else for infer */ never;
1783
+ : /* unreachable else for infer */ never;
1761
1784
 
1762
1785
  /**
1763
- * Recurses `T` applying {@link InternalUtilityTypes.DeepReadonlyWorker} up to `RecurseLimit` times.
1786
+ * Recurses `T` applying {@link InternalCoreInterfacesUtilityTypes.DeepReadonlyWorker} up to `RecurseLimit` times.
1764
1787
  *
1765
1788
  * @system
1766
1789
  */
@@ -1783,7 +1806,7 @@ export namespace InternalUtilityTypes {
1783
1806
  : DeepReadonlyWorker<T, DeepenedGenerics, RecurseLimit, TAncestorTypes | T>;
1784
1807
 
1785
1808
  /**
1786
- * Core implementation of {@link InternalUtilityTypes.DeepReadonlyLimitingRecursion}.
1809
+ * Core implementation of {@link InternalCoreInterfacesUtilityTypes.DeepReadonlyLimitingRecursion}.
1787
1810
  *
1788
1811
  * @system
1789
1812
  */