@fluidframework/core-interfaces 2.92.0 → 2.100.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 (103) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/README.md +1 -1
  3. package/api-report/core-interfaces.beta.api.md +17 -5
  4. package/api-report/core-interfaces.legacy.alpha.api.md +47 -6
  5. package/api-report/core-interfaces.legacy.beta.api.md +47 -6
  6. package/api-report/core-interfaces.legacy.public.api.md +17 -5
  7. package/api-report/core-interfaces.public.api.md +17 -5
  8. package/dist/brandedType.d.ts +14 -1
  9. package/dist/brandedType.d.ts.map +1 -1
  10. package/dist/brandedType.js.map +1 -1
  11. package/dist/deepReadonly.d.ts +3 -3
  12. package/dist/deepReadonly.js.map +1 -1
  13. package/dist/erasedType.d.ts +28 -3
  14. package/dist/erasedType.d.ts.map +1 -1
  15. package/dist/erasedType.js +7 -70
  16. package/dist/erasedType.js.map +1 -1
  17. package/dist/exposedInternalUtilityTypes.d.ts +3 -3
  18. package/dist/exposedInternalUtilityTypes.js.map +1 -1
  19. package/dist/fluidLoadable.d.ts +0 -17
  20. package/dist/fluidLoadable.d.ts.map +1 -1
  21. package/dist/fluidLoadable.js +1 -5
  22. package/dist/fluidLoadable.js.map +1 -1
  23. package/dist/fluidMap.d.ts +133 -0
  24. package/dist/fluidMap.d.ts.map +1 -0
  25. package/dist/fluidMap.js +7 -0
  26. package/dist/fluidMap.js.map +1 -0
  27. package/dist/index.d.ts +4 -3
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +1 -2
  30. package/dist/index.js.map +1 -1
  31. package/dist/jsonDeserialized.d.ts +2 -2
  32. package/dist/jsonDeserialized.js.map +1 -1
  33. package/dist/jsonSerializable.d.ts +2 -2
  34. package/dist/jsonSerializable.js.map +1 -1
  35. package/dist/jsonSerializationErrors.d.ts +2 -2
  36. package/dist/jsonSerializationErrors.js.map +1 -1
  37. package/dist/jsonType.d.ts +3 -3
  38. package/dist/jsonType.js.map +1 -1
  39. package/dist/legacy.alpha.d.ts +7 -2
  40. package/dist/legacy.d.ts +7 -2
  41. package/dist/logger.d.ts +38 -4
  42. package/dist/logger.d.ts.map +1 -1
  43. package/dist/logger.js +7 -4
  44. package/dist/logger.js.map +1 -1
  45. package/dist/opaqueJson.d.ts +2 -2
  46. package/dist/opaqueJson.js.map +1 -1
  47. package/dist/public.d.ts +2 -0
  48. package/eslint.config.mts +1 -1
  49. package/lib/brandedType.d.ts +14 -1
  50. package/lib/brandedType.d.ts.map +1 -1
  51. package/lib/brandedType.js.map +1 -1
  52. package/lib/deepReadonly.d.ts +3 -3
  53. package/lib/deepReadonly.js.map +1 -1
  54. package/lib/erasedType.d.ts +28 -3
  55. package/lib/erasedType.d.ts.map +1 -1
  56. package/lib/erasedType.js +6 -68
  57. package/lib/erasedType.js.map +1 -1
  58. package/lib/exposedInternalUtilityTypes.d.ts +3 -3
  59. package/lib/exposedInternalUtilityTypes.js.map +1 -1
  60. package/lib/fluidLoadable.d.ts +0 -17
  61. package/lib/fluidLoadable.d.ts.map +1 -1
  62. package/lib/fluidLoadable.js +0 -4
  63. package/lib/fluidLoadable.js.map +1 -1
  64. package/lib/fluidMap.d.ts +133 -0
  65. package/lib/fluidMap.d.ts.map +1 -0
  66. package/lib/fluidMap.js +6 -0
  67. package/lib/fluidMap.js.map +1 -0
  68. package/lib/index.d.ts +4 -3
  69. package/lib/index.d.ts.map +1 -1
  70. package/lib/index.js +1 -1
  71. package/lib/index.js.map +1 -1
  72. package/lib/jsonDeserialized.d.ts +2 -2
  73. package/lib/jsonDeserialized.js.map +1 -1
  74. package/lib/jsonSerializable.d.ts +2 -2
  75. package/lib/jsonSerializable.js.map +1 -1
  76. package/lib/jsonSerializationErrors.d.ts +2 -2
  77. package/lib/jsonSerializationErrors.js.map +1 -1
  78. package/lib/jsonType.d.ts +3 -3
  79. package/lib/jsonType.js.map +1 -1
  80. package/lib/legacy.alpha.d.ts +7 -2
  81. package/lib/legacy.d.ts +7 -2
  82. package/lib/logger.d.ts +38 -4
  83. package/lib/logger.d.ts.map +1 -1
  84. package/lib/logger.js +7 -4
  85. package/lib/logger.js.map +1 -1
  86. package/lib/opaqueJson.d.ts +2 -2
  87. package/lib/opaqueJson.js.map +1 -1
  88. package/lib/public.d.ts +2 -0
  89. package/lib/tsdoc-metadata.json +1 -1
  90. package/package.json +7 -8
  91. package/src/brandedType.ts +14 -1
  92. package/src/deepReadonly.ts +3 -3
  93. package/src/erasedType.ts +31 -10
  94. package/src/exposedInternalUtilityTypes.ts +3 -3
  95. package/src/fluidLoadable.ts +0 -21
  96. package/src/fluidMap.ts +151 -0
  97. package/src/index.ts +10 -2
  98. package/src/jsonDeserialized.ts +2 -2
  99. package/src/jsonSerializable.ts +2 -2
  100. package/src/jsonSerializationErrors.ts +2 -2
  101. package/src/jsonType.ts +3 -3
  102. package/src/logger.ts +52 -7
  103. package/src/opaqueJson.ts +2 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,38 @@
1
1
  # @fluidframework/core-interfaces
2
2
 
3
+ ## 2.100.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Node 22 is now the minimum supported Node.js version ([#27116](https://github.com/microsoft/FluidFramework/pull/27116)) [e8214d29663](https://github.com/microsoft/FluidFramework/commit/e8214d29663f5ee98d737daed82506a25d8de8d0)
8
+
9
+ All Fluid Framework client packages now require Node.js 22 or later. This aligns with the standing Node upgrade policy as Node 20 reaches end-of-life on April 30, 2026.
10
+
11
+ ## 2.93.0
12
+
13
+ ### Minor Changes
14
+
15
+ - Add Fluid-controlled map and iterator interfaces ([#26951](https://github.com/microsoft/FluidFramework/pull/26951)) [4735742f15](https://github.com/microsoft/FluidFramework/commit/4735742f15718419e974ead1d5e2e809863d3723)
16
+
17
+ `TreeIndex` now extends `FluidReadonlyMap` instead of the built-in `ReadonlyMap`, and `TreeMapNodeAlpha` which extends `FluidReadonlyMap` instead of the built-in `ReadonlyMap` has been added.
18
+ This works to uncouple Fluid's public API surface to the TypeScript standard library's map types, preventing future breakage when those types change.
19
+
20
+ - Promote tree index APIs from alpha to beta ([#26993](https://github.com/microsoft/FluidFramework/pull/26993)) [37f2f17c118](https://github.com/microsoft/FluidFramework/commit/37f2f17c118baea142b0e842f5b262255d8bb12c)
21
+
22
+ The following APIs have been promoted from `@alpha` to `@beta`:
23
+ - `TreeIndex`
24
+ - `TreeIndexKey`
25
+ - `TreeIndexNodes`
26
+ - `createTreeIndex`
27
+ - `IdentifierIndex`
28
+ - `createIdentifierIndex`
29
+
30
+ Additionally, the following `@fluidframework/core-interfaces` types have been promoted from `@alpha` to `@beta`:
31
+ - `FluidReadonlyMap`
32
+ - `FluidIterable`
33
+ - `FluidIterableIterator`
34
+ - `FluidMap`
35
+
3
36
  ## 2.92.0
4
37
 
5
38
  Dependency updates only.
package/README.md CHANGED
@@ -59,7 +59,7 @@ When making such a request please include if the configuration already works (an
59
59
 
60
60
  ### Supported Runtimes
61
61
 
62
- - NodeJs ^20.10.0 except that we will drop support for it [when NodeJs 20 loses its upstream support on 2026-04-30](https://github.com/nodejs/release#release-schedule), and will support a newer LTS version of NodeJS (22) at least 1 year before 20 is end-of-life. This same policy applies to NodeJS 22 when it is end of life (2027-04-30).
62
+ - NodeJs ^22.22.2 except that we will drop support for it [when NodeJs 22 loses its upstream support on 2027-04-30](https://github.com/nodejs/release#release-schedule), and will support a newer LTS version of NodeJS at least 1 year before 22 is end-of-life.
63
63
  - Running Fluid in a Node.js environment with the `--no-experimental-fetch` flag is not supported.
64
64
  - Modern browsers supporting the es2022 standard library: in response to asks we can add explicit support for using babel to polyfill to target specific standards or runtimes (meaning we can avoid/remove use of things that don't polyfill robustly, but otherwise target modern standards).
65
65
 
@@ -4,6 +4,13 @@
4
4
 
5
5
  ```ts
6
6
 
7
+ // @public
8
+ export class BrandedType<out Brand> {
9
+ static [Symbol.hasInstance](value: never): value is never;
10
+ protected constructor();
11
+ protected readonly brand: (dummy: never) => Brand;
12
+ }
13
+
7
14
  // @public
8
15
  export type ConfigTypes = string | number | boolean | number[] | string[] | boolean[] | undefined;
9
16
 
@@ -319,15 +326,20 @@ export type Listeners<T extends object> = {
319
326
  };
320
327
 
321
328
  // @public
322
- export const LogLevel: {
323
- readonly verbose: 10;
324
- readonly default: 20;
325
- readonly error: 30;
326
- };
329
+ export const LogLevel: LogLevelConst;
327
330
 
328
331
  // @public
329
332
  export type LogLevel = (typeof LogLevel)[keyof typeof LogLevel];
330
333
 
334
+ // @public
335
+ export interface LogLevelConst {
336
+ readonly default: 20;
337
+ readonly error: 30;
338
+ readonly essential: 30;
339
+ readonly info: 20;
340
+ readonly verbose: 10;
341
+ }
342
+
331
343
  // @public
332
344
  export type Off = () => void;
333
345
 
@@ -4,7 +4,7 @@
4
4
 
5
5
  ```ts
6
6
 
7
- // @beta
7
+ // @public
8
8
  export class BrandedType<out Brand> {
9
9
  static [Symbol.hasInstance](value: never): value is never;
10
10
  protected constructor();
@@ -58,6 +58,29 @@ export type FluidErrorTypesAlpha = (typeof FluidErrorTypesAlpha)[keyof typeof Fl
58
58
  // @public
59
59
  export const fluidHandleSymbol: unique symbol;
60
60
 
61
+ // @beta @sealed
62
+ export interface FluidIterable<T> {
63
+ [Symbol.iterator](): FluidIterableIterator<T>;
64
+ }
65
+
66
+ // @beta @sealed
67
+ export interface FluidIterableIterator<T> extends FluidIterable<T> {
68
+ next(): {
69
+ value: T;
70
+ done?: false;
71
+ } | {
72
+ value: any;
73
+ done: true;
74
+ };
75
+ }
76
+
77
+ // @beta @sealed
78
+ export interface FluidMap<K, V> extends FluidReadonlyMap<K, V> {
79
+ delete(key: K): void;
80
+ forEach(callbackfn: (value: V, key: K, map: FluidMap<K, V>) => void, thisArg?: any): void;
81
+ set(key: K, value: V): void;
82
+ }
83
+
61
84
  // @public
62
85
  export type FluidObject<T = unknown> = {
63
86
  [P in FluidObjectProviderKeys<T>]?: T[P];
@@ -69,6 +92,19 @@ export type FluidObjectKeys<T> = keyof FluidObject<T>;
69
92
  // @public
70
93
  export type FluidObjectProviderKeys<T, TProp extends keyof T = keyof T> = string extends TProp ? never : number extends TProp ? never : TProp extends keyof Required<T>[TProp] ? Required<T>[TProp] extends Required<Required<T>[TProp]>[TProp] ? TProp : never : never;
71
94
 
95
+ // @beta @sealed
96
+ export interface FluidReadonlyMap<K, V> {
97
+ [Symbol.iterator](): FluidIterableIterator<[K, V]>;
98
+ readonly [Symbol.toStringTag]: string;
99
+ entries(): FluidIterableIterator<[K, V]>;
100
+ forEach(callbackfn: (value: V, key: K, map: FluidReadonlyMap<K, V>) => void, thisArg?: any): void;
101
+ get(key: K): V | undefined;
102
+ has(key: K): boolean;
103
+ keys(): FluidIterableIterator<K>;
104
+ readonly size: number;
105
+ values(): FluidIterableIterator<V>;
106
+ }
107
+
72
108
  // @public
73
109
  export interface IConfigProviderBase {
74
110
  getRawConfig(name: string): ConfigTypes;
@@ -435,15 +471,20 @@ export type Listeners<T extends object> = {
435
471
  };
436
472
 
437
473
  // @public
438
- export const LogLevel: {
439
- readonly verbose: 10;
440
- readonly default: 20;
441
- readonly error: 30;
442
- };
474
+ export const LogLevel: LogLevelConst;
443
475
 
444
476
  // @public
445
477
  export type LogLevel = (typeof LogLevel)[keyof typeof LogLevel];
446
478
 
479
+ // @public
480
+ export interface LogLevelConst {
481
+ readonly default: 20;
482
+ readonly error: 30;
483
+ readonly essential: 30;
484
+ readonly info: 20;
485
+ readonly verbose: 10;
486
+ }
487
+
447
488
  // @public
448
489
  export type Off = () => void;
449
490
 
@@ -4,7 +4,7 @@
4
4
 
5
5
  ```ts
6
6
 
7
- // @beta
7
+ // @public
8
8
  export class BrandedType<out Brand> {
9
9
  static [Symbol.hasInstance](value: never): value is never;
10
10
  protected constructor();
@@ -45,6 +45,29 @@ export type FluidErrorTypes = (typeof FluidErrorTypes)[keyof typeof FluidErrorTy
45
45
  // @public
46
46
  export const fluidHandleSymbol: unique symbol;
47
47
 
48
+ // @beta @sealed
49
+ export interface FluidIterable<T> {
50
+ [Symbol.iterator](): FluidIterableIterator<T>;
51
+ }
52
+
53
+ // @beta @sealed
54
+ export interface FluidIterableIterator<T> extends FluidIterable<T> {
55
+ next(): {
56
+ value: T;
57
+ done?: false;
58
+ } | {
59
+ value: any;
60
+ done: true;
61
+ };
62
+ }
63
+
64
+ // @beta @sealed
65
+ export interface FluidMap<K, V> extends FluidReadonlyMap<K, V> {
66
+ delete(key: K): void;
67
+ forEach(callbackfn: (value: V, key: K, map: FluidMap<K, V>) => void, thisArg?: any): void;
68
+ set(key: K, value: V): void;
69
+ }
70
+
48
71
  // @public
49
72
  export type FluidObject<T = unknown> = {
50
73
  [P in FluidObjectProviderKeys<T>]?: T[P];
@@ -56,6 +79,19 @@ export type FluidObjectKeys<T> = keyof FluidObject<T>;
56
79
  // @public
57
80
  export type FluidObjectProviderKeys<T, TProp extends keyof T = keyof T> = string extends TProp ? never : number extends TProp ? never : TProp extends keyof Required<T>[TProp] ? Required<T>[TProp] extends Required<Required<T>[TProp]>[TProp] ? TProp : never : never;
58
81
 
82
+ // @beta @sealed
83
+ export interface FluidReadonlyMap<K, V> {
84
+ [Symbol.iterator](): FluidIterableIterator<[K, V]>;
85
+ readonly [Symbol.toStringTag]: string;
86
+ entries(): FluidIterableIterator<[K, V]>;
87
+ forEach(callbackfn: (value: V, key: K, map: FluidReadonlyMap<K, V>) => void, thisArg?: any): void;
88
+ get(key: K): V | undefined;
89
+ has(key: K): boolean;
90
+ keys(): FluidIterableIterator<K>;
91
+ readonly size: number;
92
+ values(): FluidIterableIterator<V>;
93
+ }
94
+
59
95
  // @public
60
96
  export interface IConfigProviderBase {
61
97
  getRawConfig(name: string): ConfigTypes;
@@ -422,15 +458,20 @@ export type Listeners<T extends object> = {
422
458
  };
423
459
 
424
460
  // @public
425
- export const LogLevel: {
426
- readonly verbose: 10;
427
- readonly default: 20;
428
- readonly error: 30;
429
- };
461
+ export const LogLevel: LogLevelConst;
430
462
 
431
463
  // @public
432
464
  export type LogLevel = (typeof LogLevel)[keyof typeof LogLevel];
433
465
 
466
+ // @public
467
+ export interface LogLevelConst {
468
+ readonly default: 20;
469
+ readonly error: 30;
470
+ readonly essential: 30;
471
+ readonly info: 20;
472
+ readonly verbose: 10;
473
+ }
474
+
434
475
  // @public
435
476
  export type Off = () => void;
436
477
 
@@ -4,6 +4,13 @@
4
4
 
5
5
  ```ts
6
6
 
7
+ // @public
8
+ export class BrandedType<out Brand> {
9
+ static [Symbol.hasInstance](value: never): value is never;
10
+ protected constructor();
11
+ protected readonly brand: (dummy: never) => Brand;
12
+ }
13
+
7
14
  // @public
8
15
  export type ConfigTypes = string | number | boolean | number[] | string[] | boolean[] | undefined;
9
16
 
@@ -319,15 +326,20 @@ export type Listeners<T extends object> = {
319
326
  };
320
327
 
321
328
  // @public
322
- export const LogLevel: {
323
- readonly verbose: 10;
324
- readonly default: 20;
325
- readonly error: 30;
326
- };
329
+ export const LogLevel: LogLevelConst;
327
330
 
328
331
  // @public
329
332
  export type LogLevel = (typeof LogLevel)[keyof typeof LogLevel];
330
333
 
334
+ // @public
335
+ export interface LogLevelConst {
336
+ readonly default: 20;
337
+ readonly error: 30;
338
+ readonly essential: 30;
339
+ readonly info: 20;
340
+ readonly verbose: 10;
341
+ }
342
+
331
343
  // @public
332
344
  export type Off = () => void;
333
345
 
@@ -4,6 +4,13 @@
4
4
 
5
5
  ```ts
6
6
 
7
+ // @public
8
+ export class BrandedType<out Brand> {
9
+ static [Symbol.hasInstance](value: never): value is never;
10
+ protected constructor();
11
+ protected readonly brand: (dummy: never) => Brand;
12
+ }
13
+
7
14
  // @public
8
15
  export type ConfigTypes = string | number | boolean | number[] | string[] | boolean[] | undefined;
9
16
 
@@ -319,15 +326,20 @@ export type Listeners<T extends object> = {
319
326
  };
320
327
 
321
328
  // @public
322
- export const LogLevel: {
323
- readonly verbose: 10;
324
- readonly default: 20;
325
- readonly error: 30;
326
- };
329
+ export const LogLevel: LogLevelConst;
327
330
 
328
331
  // @public
329
332
  export type LogLevel = (typeof LogLevel)[keyof typeof LogLevel];
330
333
 
334
+ // @public
335
+ export interface LogLevelConst {
336
+ readonly default: 20;
337
+ readonly error: 30;
338
+ readonly essential: 30;
339
+ readonly info: 20;
340
+ readonly verbose: 10;
341
+ }
342
+
331
343
  // @public
332
344
  export type Off = () => void;
333
345
 
@@ -35,6 +35,19 @@
35
35
  *
36
36
  * This class should never exist at runtime, so it is only declared.
37
37
  *
38
+ * As this is a class and not just an interface, to match derived types, the
39
+ * declarations for any two derivatives must come from the same source - the
40
+ * same package version. If a type must cross package boundaries, as may be the
41
+ * case for cross layer types, the derived type should pick a specific version
42
+ * of core-interfaces to import BrandedType from. Exact versions are best, but
43
+ * as security best practice, use ~ specification. Consumers are expected to
44
+ * use a package manager that will produce consistency over minor patches.
45
+ * A change in version should be considered a breaking change.
46
+ *
47
+ * In the preferred derived class pattern, the derived class is subject to the
48
+ * same identity rules and might benefit from being in a type-only `-definitions`
49
+ * package. See {@link ErasedType} example comments for version stable patterns.
50
+ *
38
51
  * @example
39
52
  * Definition of two branded types with different variance:
40
53
  * ```typescript
@@ -68,7 +81,7 @@
68
81
  * }
69
82
  * ```
70
83
  *
71
- * @beta
84
+ * @public
72
85
  */
73
86
  export declare class BrandedType<out Brand> {
74
87
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"brandedType.d.ts","sourceRoot":"","sources":["../src/brandedType.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmEG;AACH,MAAM,CAAC,OAAO,OAAO,WAAW,CAAC,GAAG,CAAC,KAAK;IACzC;;;;;;;;;OASG;IACH,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,KAAK,CAAC;IAElD,SAAS;IAET;;;;;OAKG;WACW,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,IAAI,KAAK;CAChE"}
1
+ {"version":3,"file":"brandedType.d.ts","sourceRoot":"","sources":["../src/brandedType.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgFG;AACH,MAAM,CAAC,OAAO,OAAO,WAAW,CAAC,GAAG,CAAC,KAAK;IACzC;;;;;;;;;OASG;IACH,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,KAAK,CAAC;IAElD,SAAS;IAET;;;;;OAKG;WACW,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,IAAI,KAAK;CAChE"}
@@ -1 +1 @@
1
- {"version":3,"file":"brandedType.js","sourceRoot":"","sources":["../src/brandedType.ts"],"names":[],"mappings":";AAAA;;;GAGG","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/**\n * Base branded type which can be used to annotate other type.\n *\n * @remarks\n * `BrandedType` is covariant over its type parameter, which could be leveraged\n * for any generic type, but the preferred pattern is to specify variance\n * explicitly in a derived class making that clear and guaranteeing branding is\n * unique. It is convenient to have the derived class be the generic given to\n * `BrandedType`.\n *\n * ### Direct use [simple]\n *\n * Use `T & BrandedType<\"BrandName\">` to create a type conforming to `T` and\n * also branded with name \"BrandName\".\n *\n * ### Derived class use [preferred]\n *\n * Derive another class declaration and ideally add additional\n * protected properties to distinguish the type. (Private properties would\n * {@link https://github.com/microsoft/TypeScript/issues/20979#issuecomment-361432516|lose their type when exported}\n * and public properties would allow structural typing and show up on the branded\n * values.)\n *\n * Then use `T & MyBrandedType<U>` to create a type conforming to `T` and\n * also branded with the derived brand.\n *\n * ### Runtime\n *\n * Since branded types are not real value types, they will always need to be\n * created using `as` syntax and often `as unknown` first.\n *\n * This class should never exist at runtime, so it is only declared.\n *\n * @example\n * Definition of two branded types with different variance:\n * ```typescript\n * // A brand that is covariant over given T\n * declare class CovariantBrand<T> extends BrandedType<CovariantBrand<unknown>> {\n * // Does not allow unrelated or less derived CovariantBrand-ed types to be\n * // assigned. CovariantBrand<string> is not assignable to CovariantBrand<\"literal\">.\n * protected readonly CovariantBrand: T;\n * private constructor();\n * }\n * // A brand that is contravariant over given T\n * declare class ContravariantBrand<T> extends BrandedType<ContravariantBrand<unknown>> {\n * // Does not allow unrelated or more derived ContravariantBrand-ed types to be\n * // assigned. ContravariantBrand<\"literal\"> is not assignable to ContravariantBrand<string>.\n * protected readonly ContravariantBrand: (_: T) => void;\n * private constructor();\n * }\n * ```\n *\n * Applying a brand to a type through type-guard:\n * ```typescript\n * function numberIs5(n: number): n is number & CovariantBrand<5> {\n * return n === 5;\n * }\n * function onlyAccept4_5_or_6(_n: number & CovariantBrand<4 | 5 | 6>): void {}\n *\n * function example(n: number) {\n * if (numberIs5(n)) {\n * onlyAccept4_5_or_6(n); // OK: CovariantBrand<5> is assignable to CovariantBrand<4 | 5 | 6>;\n * }\n * }\n * ```\n *\n * @beta\n */\nexport declare class BrandedType<out Brand> {\n\t/**\n\t * Compile time only marker to make type checking more strict.\n\t * This method will not exist at runtime and accessing it is invalid.\n\t *\n\t * @privateRemarks\n\t * `Brand` is used as the return type of a method rather than a simple\n\t * readonly property as this allows types with two brands to be\n\t * intersected without getting `never`.\n\t * The method takes in `never` to help emphasize that it's not callable.\n\t */\n\tprotected readonly brand: (dummy: never) => Brand;\n\n\tprotected constructor();\n\n\t/**\n\t * Since this class is a compile time only type brand, `instanceof` will\n\t * never work with it. * This `Symbol.hasInstance` implementation ensures\n\t * that `instanceof` will error if used, and in TypeScript 5.3 and newer\n\t * will produce a compile time error if used.\n\t */\n\tpublic static [Symbol.hasInstance](value: never): value is never;\n}\n"]}
1
+ {"version":3,"file":"brandedType.js","sourceRoot":"","sources":["../src/brandedType.ts"],"names":[],"mappings":";AAAA;;;GAGG","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/**\n * Base branded type which can be used to annotate other type.\n *\n * @remarks\n * `BrandedType` is covariant over its type parameter, which could be leveraged\n * for any generic type, but the preferred pattern is to specify variance\n * explicitly in a derived class making that clear and guaranteeing branding is\n * unique. It is convenient to have the derived class be the generic given to\n * `BrandedType`.\n *\n * ### Direct use [simple]\n *\n * Use `T & BrandedType<\"BrandName\">` to create a type conforming to `T` and\n * also branded with name \"BrandName\".\n *\n * ### Derived class use [preferred]\n *\n * Derive another class declaration and ideally add additional\n * protected properties to distinguish the type. (Private properties would\n * {@link https://github.com/microsoft/TypeScript/issues/20979#issuecomment-361432516|lose their type when exported}\n * and public properties would allow structural typing and show up on the branded\n * values.)\n *\n * Then use `T & MyBrandedType<U>` to create a type conforming to `T` and\n * also branded with the derived brand.\n *\n * ### Runtime\n *\n * Since branded types are not real value types, they will always need to be\n * created using `as` syntax and often `as unknown` first.\n *\n * This class should never exist at runtime, so it is only declared.\n *\n * As this is a class and not just an interface, to match derived types, the\n * declarations for any two derivatives must come from the same source - the\n * same package version. If a type must cross package boundaries, as may be the\n * case for cross layer types, the derived type should pick a specific version\n * of core-interfaces to import BrandedType from. Exact versions are best, but\n * as security best practice, use ~ specification. Consumers are expected to\n * use a package manager that will produce consistency over minor patches.\n * A change in version should be considered a breaking change.\n *\n * In the preferred derived class pattern, the derived class is subject to the\n * same identity rules and might benefit from being in a type-only `-definitions`\n * package. See {@link ErasedType} example comments for version stable patterns.\n *\n * @example\n * Definition of two branded types with different variance:\n * ```typescript\n * // A brand that is covariant over given T\n * declare class CovariantBrand<T> extends BrandedType<CovariantBrand<unknown>> {\n * // Does not allow unrelated or less derived CovariantBrand-ed types to be\n * // assigned. CovariantBrand<string> is not assignable to CovariantBrand<\"literal\">.\n * protected readonly CovariantBrand: T;\n * private constructor();\n * }\n * // A brand that is contravariant over given T\n * declare class ContravariantBrand<T> extends BrandedType<ContravariantBrand<unknown>> {\n * // Does not allow unrelated or more derived ContravariantBrand-ed types to be\n * // assigned. ContravariantBrand<\"literal\"> is not assignable to ContravariantBrand<string>.\n * protected readonly ContravariantBrand: (_: T) => void;\n * private constructor();\n * }\n * ```\n *\n * Applying a brand to a type through type-guard:\n * ```typescript\n * function numberIs5(n: number): n is number & CovariantBrand<5> {\n * return n === 5;\n * }\n * function onlyAccept4_5_or_6(_n: number & CovariantBrand<4 | 5 | 6>): void {}\n *\n * function example(n: number) {\n * if (numberIs5(n)) {\n * onlyAccept4_5_or_6(n); // OK: CovariantBrand<5> is assignable to CovariantBrand<4 | 5 | 6>;\n * }\n * }\n * ```\n *\n * @public\n */\nexport declare class BrandedType<out Brand> {\n\t/**\n\t * Compile time only marker to make type checking more strict.\n\t * This method will not exist at runtime and accessing it is invalid.\n\t *\n\t * @privateRemarks\n\t * `Brand` is used as the return type of a method rather than a simple\n\t * readonly property as this allows types with two brands to be\n\t * intersected without getting `never`.\n\t * The method takes in `never` to help emphasize that it's not callable.\n\t */\n\tprotected readonly brand: (dummy: never) => Brand;\n\n\tprotected constructor();\n\n\t/**\n\t * Since this class is a compile time only type brand, `instanceof` will\n\t * never work with it. * This `Symbol.hasInstance` implementation ensures\n\t * that `instanceof` will error if used, and in TypeScript 5.3 and newer\n\t * will produce a compile time error if used.\n\t */\n\tpublic static [Symbol.hasInstance](value: never): value is never;\n}\n"]}
@@ -10,14 +10,14 @@ import type { DeepReadonlyRecursionLimit, InternalUtilityTypes, ReadonlySupporte
10
10
  * @privateRemarks
11
11
  * WeakRef should be added when lib is updated to ES2021 or later.
12
12
  *
13
- * @beta
13
+ * @public
14
14
  * @system
15
15
  */
16
16
  export type DeepReadonlySupportedGenericsDefault = Map<unknown, unknown> | Promise<unknown> | Set<unknown> | WeakMap<object, unknown> | WeakSet<object>;
17
17
  /**
18
18
  * Options for {@link DeepReadonly}.
19
19
  *
20
- * @beta
20
+ * @public
21
21
  */
22
22
  export interface DeepReadonlyOptions {
23
23
  /**
@@ -44,7 +44,7 @@ export interface DeepReadonlyOptions {
44
44
  * {@link DeepReadonlySupportedGenericsDefault} for generics that have
45
45
  * immutability applied to generic type by default.
46
46
  *
47
- * @beta
47
+ * @public
48
48
  */
49
49
  export type DeepReadonly<T, Options extends DeepReadonlyOptions = {
50
50
  DeepenedGenerics: DeepReadonlySupportedGenericsDefault;
@@ -1 +1 @@
1
- {"version":3,"file":"deepReadonly.js","sourceRoot":"","sources":["../src/deepReadonly.ts"],"names":[],"mappings":";AAAA;;;GAGG","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type {\n\tDeepReadonlyRecursionLimit,\n\tInternalUtilityTypes,\n\tReadonlySupportedGenerics,\n} from \"./exposedInternalUtilityTypes.js\";\n\n/**\n * Default set of generic that {@link DeepReadonly} will apply deep immutability\n * to generic types.\n *\n * @privateRemarks\n * WeakRef should be added when lib is updated to ES2021 or later.\n *\n * @beta\n * @system\n */\nexport type DeepReadonlySupportedGenericsDefault =\n\t| Map<unknown, unknown>\n\t| Promise<unknown>\n\t| Set<unknown>\n\t| WeakMap<object, unknown>\n\t| WeakSet<object>;\n\n/**\n * Options for {@link DeepReadonly}.\n *\n * @beta\n */\nexport interface DeepReadonlyOptions {\n\t/**\n\t * Union of Built-in and IFluidHandle whose generics will also be made deeply immutable.\n\t *\n\t * The default value is `Map` | `Promise` | `Set` | `WeakMap` | `WeakSet`.\n\t */\n\tDeepenedGenerics?: ReadonlySupportedGenerics;\n\n\t/**\n\t * Limit on processing recursive types.\n\t *\n\t * The default value is `\"NoLimit\"`.\n\t */\n\tRecurseLimit?: DeepReadonlyRecursionLimit;\n}\n\n/**\n * Transforms type to a fully and deeply immutable type, with limitations.\n *\n * @remarks\n * This utility type is similar to a recursive `Readonly<T>`, but also\n * applies immutability to common generic types like `Map` and `Set`.\n *\n * Optionally, immutability can be applied to supported generics types. See\n * {@link DeepReadonlySupportedGenericsDefault} for generics that have\n * immutability applied to generic type by default.\n *\n * @beta\n */\nexport type DeepReadonly<\n\tT,\n\tOptions extends DeepReadonlyOptions = {\n\t\tDeepenedGenerics: DeepReadonlySupportedGenericsDefault;\n\t\tRecurseLimit: \"NoLimit\";\n\t},\n> = InternalUtilityTypes.DeepReadonlyImpl<\n\tT,\n\tOptions extends { DeepenedGenerics: unknown }\n\t\t? Options[\"DeepenedGenerics\"]\n\t\t: DeepReadonlySupportedGenericsDefault,\n\tOptions extends { RecurseLimit: DeepReadonlyRecursionLimit }\n\t\t? Options[\"RecurseLimit\"]\n\t\t: \"NoLimit\"\n>;\n"]}
1
+ {"version":3,"file":"deepReadonly.js","sourceRoot":"","sources":["../src/deepReadonly.ts"],"names":[],"mappings":";AAAA;;;GAGG","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type {\n\tDeepReadonlyRecursionLimit,\n\tInternalUtilityTypes,\n\tReadonlySupportedGenerics,\n} from \"./exposedInternalUtilityTypes.js\";\n\n/**\n * Default set of generic that {@link DeepReadonly} will apply deep immutability\n * to generic types.\n *\n * @privateRemarks\n * WeakRef should be added when lib is updated to ES2021 or later.\n *\n * @public\n * @system\n */\nexport type DeepReadonlySupportedGenericsDefault =\n\t| Map<unknown, unknown>\n\t| Promise<unknown>\n\t| Set<unknown>\n\t| WeakMap<object, unknown>\n\t| WeakSet<object>;\n\n/**\n * Options for {@link DeepReadonly}.\n *\n * @public\n */\nexport interface DeepReadonlyOptions {\n\t/**\n\t * Union of Built-in and IFluidHandle whose generics will also be made deeply immutable.\n\t *\n\t * The default value is `Map` | `Promise` | `Set` | `WeakMap` | `WeakSet`.\n\t */\n\tDeepenedGenerics?: ReadonlySupportedGenerics;\n\n\t/**\n\t * Limit on processing recursive types.\n\t *\n\t * The default value is `\"NoLimit\"`.\n\t */\n\tRecurseLimit?: DeepReadonlyRecursionLimit;\n}\n\n/**\n * Transforms type to a fully and deeply immutable type, with limitations.\n *\n * @remarks\n * This utility type is similar to a recursive `Readonly<T>`, but also\n * applies immutability to common generic types like `Map` and `Set`.\n *\n * Optionally, immutability can be applied to supported generics types. See\n * {@link DeepReadonlySupportedGenericsDefault} for generics that have\n * immutability applied to generic type by default.\n *\n * @public\n */\nexport type DeepReadonly<\n\tT,\n\tOptions extends DeepReadonlyOptions = {\n\t\tDeepenedGenerics: DeepReadonlySupportedGenericsDefault;\n\t\tRecurseLimit: \"NoLimit\";\n\t},\n> = InternalUtilityTypes.DeepReadonlyImpl<\n\tT,\n\tOptions extends { DeepenedGenerics: unknown }\n\t\t? Options[\"DeepenedGenerics\"]\n\t\t: DeepReadonlySupportedGenericsDefault,\n\tOptions extends { RecurseLimit: DeepReadonlyRecursionLimit }\n\t\t? Options[\"RecurseLimit\"]\n\t\t: \"NoLimit\"\n>;\n"]}
@@ -12,13 +12,30 @@
12
12
  * allowing code outside of a package to have a reference/handle to something in the package in a type safe way without the package having to publicly export the types of the object.
13
13
  * This should not be confused with the more specific IFluidHandle which is also named after this design pattern.
14
14
  *
15
+ * As this is a class and not just an interface, to match derived types, the
16
+ * declarations for any two derivatives must come from the same source - the
17
+ * same package version. If a type must cross package boundaries, as may be the
18
+ * case for cross layer types, the derived type should pick a specific version
19
+ * of core-interfaces to import ErasedType from. Exact versions are best, but
20
+ * as security best practice, use ~ specification. Consumers are expected to
21
+ * use a package manager that will produce consistency over minor patches.
22
+ * A change in version should be considered a breaking change.
23
+ *
15
24
  * Recommended usage is to use `interface` instead of `type` so tooling (such as tsc and refactoring tools)
16
25
  * uses the type name instead of expanding it.
17
26
  *
18
27
  * @example
28
+ * package.json:
29
+ * ```json
30
+ * "dependencies": {
31
+ * "@fluidframework/erased-type-v1": "npm:@fluidframework/core-interfaces@~2.0.0"
32
+ * }
33
+ * ```
34
+ * source.ts:
19
35
  * ```typescript
36
+ * import { ErasedType as ErasedTypeV1 } from "@fluidframework/erased-type-v1";
20
37
  * // public sealed type
21
- * export interface ErasedMyType extends ErasedType<"myPackage.MyType"> {}
38
+ * export interface ErasedMyType extends ErasedTypeV1<"myPackage.MyType"> {}
22
39
  * // internal type
23
40
  * export interface MyType {
24
41
  * example: number;
@@ -34,6 +51,7 @@
34
51
  *
35
52
  * Do not use this class with `instanceof`: this will always be false at runtime,
36
53
  * but the compiler may think it's true in some cases.
54
+ *
37
55
  * @privateRemarks
38
56
  * For this pattern to work well it needs to be difficult for a user of the erased type to
39
57
  * implicitly use something other than a instance received from the package as an instance of the erased type in type safe code.
@@ -71,22 +89,29 @@ export declare abstract class ErasedType<out Name = unknown> {
71
89
  private constructor();
72
90
  /**
73
91
  * Since this class is a compile time only type brand, `instanceof` will never work with it.
74
- * This `Symbol.hasInstance` implementation ensures that `instanceof` will error if used,
75
- * and in TypeScript 5.3 and newer will produce a compile time error if used.
92
+ * This `Symbol.hasInstance` declaration (no definition) ensures that `instanceof` will
93
+ * produce `ReferenceError` if used at runtime. And in TypeScript 5.3 and newer will produce
94
+ * a compile time error if used.
76
95
  */
77
96
  static [Symbol.hasInstance](value: never): value is never;
78
97
  }
79
98
  /**
80
99
  * Used to mark a `@sealed` interface in a strongly typed way to prevent external implementations.
100
+ *
81
101
  * @remarks
82
102
  * This is an alternative to {@link ErasedType} which is more ergonomic to implement in the case where the implementation can extend `ErasedTypeImplementation`.
83
103
  *
84
104
  * Users of interfaces extending this should never refer to anything about this class:
85
105
  * migrating the type branding to another mechanism, like {@link ErasedType} should be considered a non-breaking change.
106
+ *
107
+ * @see {@link ErasedType} for version compatibility notes.
108
+ *
86
109
  * @privateRemarks
87
110
  * Implement interfaces which extend this by sub-classing {@link ErasedTypeImplementation}.
88
111
  *
89
112
  * This class should only be a `type` package export, preventing users from extending it directly.
113
+ * But since {@link ErasedTypeImplementation} does extend it, an implementation
114
+ * of the constructor must be provided, unlike {@link ErasedType}.
90
115
  *
91
116
  * Since {@link ErasedTypeImplementation} is exported as `@internal`, this restricts implementations of the sealed interfaces to users of `@internal` APIs, which should be anything within this release group.
92
117
  * Any finer grained restrictions can be done as documentation, but not type enforced.
@@ -1 +1 @@
1
- {"version":3,"file":"erasedType.d.ts","sourceRoot":"","sources":["../src/erasedType.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AACH,8BAAsB,UAAU,CAAC,GAAG,CAAC,IAAI,GAAG,OAAO;IAClD;;;;;;OAMG;IACH,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAE5C;;OAEG;IACH,OAAO;IAEP;;;;OAIG;WACW,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,IAAI,KAAK;CAKhE;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,8BAAsB,cAAc,CAAC,GAAG,CAAC,IAAI,GAAG,OAAO;IACtD;;;;;;OAMG;IACH,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAE5C;;;;;;OAMG;IACH,SAAS;CACT;AAED;;;;;;;;;GASG;AACH,8BAAsB,wBAAwB,CAC7C,UAAU,SAAS,cAAc,CAChC,SAAQ,cAAc,CAAC,UAAU,SAAS,cAAc,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,GAAG,KAAK,CAAC;IACrF,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAG,CAC1B,KAAK,EAAE,KAAK,KACR,UAAU,SAAS,cAAc,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,GAAG,KAAK,CAAC;IAElE,SAAS;IAIT;;OAEG;WACW,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,KAAK,SAAS;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,EACrE,IAAI,EAAE,KAAK,EACX,KAAK,EAAE,OAAO,GACZ,KAAK,IAAI,mBAAmB,CAAC,KAAK,CAAC;IAQtC;;;;;;;;;OASG;WACW,MAAM,CAAC,KAAK,SAAS;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,EACvD,IAAI,EAAE,KAAK,EACX,KAAK,EAAE,cAAc,GAAG,mBAAmB,CAAC,KAAK,CAAC,GAChD,OAAO,CAAC,KAAK,IAAI,mBAAmB,CAAC,KAAK,CAAC;IAM9C;;;;OAIG;IACI,MAAM,CAAC,KAAK,SAAS,UAAU,EAAE,IAAI,EAAE,KAAK,GAAG,UAAU;CAGhE;AAED;;;;;GAKG;AACH,MAAM,MAAM,mBAAmB,CAAC,MAAM,IAAI,YAAY,CAAC,CAAC,UAAU,KAAK,CAAC,GAAG,MAAM,CAAC,CAAC"}
1
+ {"version":3,"file":"erasedType.d.ts","sourceRoot":"","sources":["../src/erasedType.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuEG;AACH,MAAM,CAAC,OAAO,CAAC,QAAQ,OAAO,UAAU,CAAC,GAAG,CAAC,IAAI,GAAG,OAAO;IAC1D;;;;;;OAMG;IACH,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAE5C;;OAEG;IACH,OAAO;IAEP;;;;;OAKG;WACW,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,IAAI,KAAK;CAChE;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,8BAAsB,cAAc,CAAC,GAAG,CAAC,IAAI,GAAG,OAAO;IACtD;;;;;;OAMG;IACH,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAE5C;;;;;;OAMG;IACH,SAAS;CACT;AAED;;;;;;;;;GASG;AACH,8BAAsB,wBAAwB,CAC7C,UAAU,SAAS,cAAc,CAChC,SAAQ,cAAc,CAAC,UAAU,SAAS,cAAc,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,GAAG,KAAK,CAAC;IACrF,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAG,CAC1B,KAAK,EAAE,KAAK,KACR,UAAU,SAAS,cAAc,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,GAAG,KAAK,CAAC;IAElE,SAAS;IAIT;;OAEG;WACW,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,KAAK,SAAS;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,EACrE,IAAI,EAAE,KAAK,EACX,KAAK,EAAE,OAAO,GACZ,KAAK,IAAI,mBAAmB,CAAC,KAAK,CAAC;IAQtC;;;;;;;;;OASG;WACW,MAAM,CAAC,KAAK,SAAS;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,EACvD,IAAI,EAAE,KAAK,EACX,KAAK,EAAE,cAAc,GAAG,mBAAmB,CAAC,KAAK,CAAC,GAChD,OAAO,CAAC,KAAK,IAAI,mBAAmB,CAAC,KAAK,CAAC;IAM9C;;;;OAIG;IACI,MAAM,CAAC,KAAK,SAAS,UAAU,EAAE,IAAI,EAAE,KAAK,GAAG,UAAU;CAGhE;AAED;;;;;GAKG;AACH,MAAM,MAAM,mBAAmB,CAAC,MAAM,IAAI,YAAY,CAAC,CAAC,UAAU,KAAK,CAAC,GAAG,MAAM,CAAC,CAAC"}
@@ -4,87 +4,24 @@
4
4
  * Licensed under the MIT License.
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.ErasedTypeImplementation = exports.ErasedBaseType = exports.ErasedType = void 0;
8
- /**
9
- * Erased type which can be used to expose a opaque/erased version of a type without referencing the actual type.
10
- * @remarks
11
- * This similar to the {@link https://en.wikipedia.org/wiki/Type_erasure | type erasure} pattern,
12
- * but for erasing types at the package boundary.
13
- *
14
- * This can be used to implement the TypeScript typing for the {@link https://en.wikipedia.org/wiki/Handle_(computing) | handle} pattern,
15
- * allowing code outside of a package to have a reference/handle to something in the package in a type safe way without the package having to publicly export the types of the object.
16
- * This should not be confused with the more specific IFluidHandle which is also named after this design pattern.
17
- *
18
- * Recommended usage is to use `interface` instead of `type` so tooling (such as tsc and refactoring tools)
19
- * uses the type name instead of expanding it.
20
- *
21
- * @example
22
- * ```typescript
23
- * // public sealed type
24
- * export interface ErasedMyType extends ErasedType<"myPackage.MyType"> {}
25
- * // internal type
26
- * export interface MyType {
27
- * example: number;
28
- * }
29
- * // Usage
30
- * function extract(input: ErasedMyType): MyType {
31
- * return input as unknown as MyType;
32
- * }
33
- * function erase(input: MyType): ErasedMyType {
34
- * return input as unknown as ErasedMyType;
35
- * }
36
- * ```
37
- *
38
- * Do not use this class with `instanceof`: this will always be false at runtime,
39
- * but the compiler may think it's true in some cases.
40
- * @privateRemarks
41
- * For this pattern to work well it needs to be difficult for a user of the erased type to
42
- * implicitly use something other than a instance received from the package as an instance of the erased type in type safe code.
43
- *
44
- * This means that this type must not be able to be implicitly converted to from any strong type (not `any` or `never`),
45
- * and no amount of auto complete or auto-implement refactoring will produce something that can be used as an erased type.
46
- * This is accomplished by:
47
- *
48
- * 1. requiring that values of this type be an instance of this class.
49
- * Typescript does not enforce this requirement for class: only for classes with protected or private members, so such member is included.
50
- *
51
- * 2. making this class impossible to get an instance of.
52
- * This is done by having a private constructor.
53
- *
54
- * 3. ensuring different erased types also using this library can not be implicitly converted between each-other.
55
- * This is done by using the "Name" type parameter.
56
- * Note that just having the type parameter is not enough since the presence of type parameters has no impact on implicit conversion in TypeScript:
57
- * only the usages of the type parameter matter.
58
- *
59
- * @sealed
60
- * @public
61
- */
62
- class ErasedType {
63
- /**
64
- * This class should never exist at runtime, so make it un-constructable.
65
- */
66
- constructor() { }
67
- /**
68
- * Since this class is a compile time only type brand, `instanceof` will never work with it.
69
- * This `Symbol.hasInstance` implementation ensures that `instanceof` will error if used,
70
- * and in TypeScript 5.3 and newer will produce a compile time error if used.
71
- */
72
- static [Symbol.hasInstance](value) {
73
- throw new Error("ErasedType is a compile time type brand not a real class that can be used with `instanceof` at runtime.");
74
- }
75
- }
76
- exports.ErasedType = ErasedType;
7
+ exports.ErasedTypeImplementation = exports.ErasedBaseType = void 0;
77
8
  /**
78
9
  * Used to mark a `@sealed` interface in a strongly typed way to prevent external implementations.
10
+ *
79
11
  * @remarks
80
12
  * This is an alternative to {@link ErasedType} which is more ergonomic to implement in the case where the implementation can extend `ErasedTypeImplementation`.
81
13
  *
82
14
  * Users of interfaces extending this should never refer to anything about this class:
83
15
  * migrating the type branding to another mechanism, like {@link ErasedType} should be considered a non-breaking change.
16
+ *
17
+ * @see {@link ErasedType} for version compatibility notes.
18
+ *
84
19
  * @privateRemarks
85
20
  * Implement interfaces which extend this by sub-classing {@link ErasedTypeImplementation}.
86
21
  *
87
22
  * This class should only be a `type` package export, preventing users from extending it directly.
23
+ * But since {@link ErasedTypeImplementation} does extend it, an implementation
24
+ * of the constructor must be provided, unlike {@link ErasedType}.
88
25
  *
89
26
  * Since {@link ErasedTypeImplementation} is exported as `@internal`, this restricts implementations of the sealed interfaces to users of `@internal` APIs, which should be anything within this release group.
90
27
  * Any finer grained restrictions can be done as documentation, but not type enforced.