@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.
- package/CHANGELOG.md +33 -0
- package/README.md +1 -1
- package/api-report/core-interfaces.beta.api.md +17 -5
- package/api-report/core-interfaces.legacy.alpha.api.md +47 -6
- package/api-report/core-interfaces.legacy.beta.api.md +47 -6
- package/api-report/core-interfaces.legacy.public.api.md +17 -5
- package/api-report/core-interfaces.public.api.md +17 -5
- package/dist/brandedType.d.ts +14 -1
- package/dist/brandedType.d.ts.map +1 -1
- package/dist/brandedType.js.map +1 -1
- package/dist/deepReadonly.d.ts +3 -3
- package/dist/deepReadonly.js.map +1 -1
- package/dist/erasedType.d.ts +28 -3
- package/dist/erasedType.d.ts.map +1 -1
- package/dist/erasedType.js +7 -70
- package/dist/erasedType.js.map +1 -1
- package/dist/exposedInternalUtilityTypes.d.ts +3 -3
- package/dist/exposedInternalUtilityTypes.js.map +1 -1
- package/dist/fluidLoadable.d.ts +0 -17
- package/dist/fluidLoadable.d.ts.map +1 -1
- package/dist/fluidLoadable.js +1 -5
- package/dist/fluidLoadable.js.map +1 -1
- package/dist/fluidMap.d.ts +133 -0
- package/dist/fluidMap.d.ts.map +1 -0
- package/dist/fluidMap.js +7 -0
- package/dist/fluidMap.js.map +1 -0
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -2
- package/dist/index.js.map +1 -1
- package/dist/jsonDeserialized.d.ts +2 -2
- package/dist/jsonDeserialized.js.map +1 -1
- package/dist/jsonSerializable.d.ts +2 -2
- package/dist/jsonSerializable.js.map +1 -1
- package/dist/jsonSerializationErrors.d.ts +2 -2
- package/dist/jsonSerializationErrors.js.map +1 -1
- package/dist/jsonType.d.ts +3 -3
- package/dist/jsonType.js.map +1 -1
- package/dist/legacy.alpha.d.ts +7 -2
- package/dist/legacy.d.ts +7 -2
- package/dist/logger.d.ts +38 -4
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +7 -4
- package/dist/logger.js.map +1 -1
- package/dist/opaqueJson.d.ts +2 -2
- package/dist/opaqueJson.js.map +1 -1
- package/dist/public.d.ts +2 -0
- package/eslint.config.mts +1 -1
- package/lib/brandedType.d.ts +14 -1
- package/lib/brandedType.d.ts.map +1 -1
- package/lib/brandedType.js.map +1 -1
- package/lib/deepReadonly.d.ts +3 -3
- package/lib/deepReadonly.js.map +1 -1
- package/lib/erasedType.d.ts +28 -3
- package/lib/erasedType.d.ts.map +1 -1
- package/lib/erasedType.js +6 -68
- package/lib/erasedType.js.map +1 -1
- package/lib/exposedInternalUtilityTypes.d.ts +3 -3
- package/lib/exposedInternalUtilityTypes.js.map +1 -1
- package/lib/fluidLoadable.d.ts +0 -17
- package/lib/fluidLoadable.d.ts.map +1 -1
- package/lib/fluidLoadable.js +0 -4
- package/lib/fluidLoadable.js.map +1 -1
- package/lib/fluidMap.d.ts +133 -0
- package/lib/fluidMap.d.ts.map +1 -0
- package/lib/fluidMap.js +6 -0
- package/lib/fluidMap.js.map +1 -0
- package/lib/index.d.ts +4 -3
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/jsonDeserialized.d.ts +2 -2
- package/lib/jsonDeserialized.js.map +1 -1
- package/lib/jsonSerializable.d.ts +2 -2
- package/lib/jsonSerializable.js.map +1 -1
- package/lib/jsonSerializationErrors.d.ts +2 -2
- package/lib/jsonSerializationErrors.js.map +1 -1
- package/lib/jsonType.d.ts +3 -3
- package/lib/jsonType.js.map +1 -1
- package/lib/legacy.alpha.d.ts +7 -2
- package/lib/legacy.d.ts +7 -2
- package/lib/logger.d.ts +38 -4
- package/lib/logger.d.ts.map +1 -1
- package/lib/logger.js +7 -4
- package/lib/logger.js.map +1 -1
- package/lib/opaqueJson.d.ts +2 -2
- package/lib/opaqueJson.js.map +1 -1
- package/lib/public.d.ts +2 -0
- package/lib/tsdoc-metadata.json +1 -1
- package/package.json +7 -8
- package/src/brandedType.ts +14 -1
- package/src/deepReadonly.ts +3 -3
- package/src/erasedType.ts +31 -10
- package/src/exposedInternalUtilityTypes.ts +3 -3
- package/src/fluidLoadable.ts +0 -21
- package/src/fluidMap.ts +151 -0
- package/src/index.ts +10 -2
- package/src/jsonDeserialized.ts +2 -2
- package/src/jsonSerializable.ts +2 -2
- package/src/jsonSerializationErrors.ts +2 -2
- package/src/jsonType.ts +3 -3
- package/src/logger.ts +52 -7
- 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 ^
|
|
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
|
-
// @
|
|
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
|
-
// @
|
|
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
|
|
package/dist/brandedType.d.ts
CHANGED
|
@@ -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
|
-
* @
|
|
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
|
|
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"}
|
package/dist/brandedType.js.map
CHANGED
|
@@ -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 * @
|
|
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"]}
|
package/dist/deepReadonly.d.ts
CHANGED
|
@@ -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
|
-
* @
|
|
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
|
-
* @
|
|
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
|
-
* @
|
|
47
|
+
* @public
|
|
48
48
|
*/
|
|
49
49
|
export type DeepReadonly<T, Options extends DeepReadonlyOptions = {
|
|
50
50
|
DeepenedGenerics: DeepReadonlySupportedGenericsDefault;
|
package/dist/deepReadonly.js.map
CHANGED
|
@@ -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 * @
|
|
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"]}
|
package/dist/erasedType.d.ts
CHANGED
|
@@ -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
|
|
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`
|
|
75
|
-
*
|
|
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.
|
package/dist/erasedType.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"erasedType.d.ts","sourceRoot":"","sources":["../src/erasedType.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH
|
|
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"}
|
package/dist/erasedType.js
CHANGED
|
@@ -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 =
|
|
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.
|