@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/dist/public.d.ts
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
export {
|
|
12
12
|
// #region @public APIs
|
|
13
|
+
BrandedType,
|
|
13
14
|
ConfigTypes,
|
|
14
15
|
ErasedType,
|
|
15
16
|
ExtendEventProvider,
|
|
@@ -38,6 +39,7 @@ export {
|
|
|
38
39
|
Listenable,
|
|
39
40
|
Listeners,
|
|
40
41
|
LogLevel,
|
|
42
|
+
LogLevelConst,
|
|
41
43
|
Off,
|
|
42
44
|
ReplaceIEventThisPlaceHolder,
|
|
43
45
|
Tagged,
|
package/eslint.config.mts
CHANGED
package/lib/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
|
/**
|
package/lib/brandedType.d.ts.map
CHANGED
|
@@ -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/lib/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/lib/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/lib/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/lib/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/lib/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/lib/erasedType.js
CHANGED
|
@@ -2,85 +2,23 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
/**
|
|
6
|
-
* Erased type which can be used to expose a opaque/erased version of a type without referencing the actual type.
|
|
7
|
-
* @remarks
|
|
8
|
-
* This similar to the {@link https://en.wikipedia.org/wiki/Type_erasure | type erasure} pattern,
|
|
9
|
-
* but for erasing types at the package boundary.
|
|
10
|
-
*
|
|
11
|
-
* This can be used to implement the TypeScript typing for the {@link https://en.wikipedia.org/wiki/Handle_(computing) | handle} pattern,
|
|
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
|
-
* This should not be confused with the more specific IFluidHandle which is also named after this design pattern.
|
|
14
|
-
*
|
|
15
|
-
* Recommended usage is to use `interface` instead of `type` so tooling (such as tsc and refactoring tools)
|
|
16
|
-
* uses the type name instead of expanding it.
|
|
17
|
-
*
|
|
18
|
-
* @example
|
|
19
|
-
* ```typescript
|
|
20
|
-
* // public sealed type
|
|
21
|
-
* export interface ErasedMyType extends ErasedType<"myPackage.MyType"> {}
|
|
22
|
-
* // internal type
|
|
23
|
-
* export interface MyType {
|
|
24
|
-
* example: number;
|
|
25
|
-
* }
|
|
26
|
-
* // Usage
|
|
27
|
-
* function extract(input: ErasedMyType): MyType {
|
|
28
|
-
* return input as unknown as MyType;
|
|
29
|
-
* }
|
|
30
|
-
* function erase(input: MyType): ErasedMyType {
|
|
31
|
-
* return input as unknown as ErasedMyType;
|
|
32
|
-
* }
|
|
33
|
-
* ```
|
|
34
|
-
*
|
|
35
|
-
* Do not use this class with `instanceof`: this will always be false at runtime,
|
|
36
|
-
* but the compiler may think it's true in some cases.
|
|
37
|
-
* @privateRemarks
|
|
38
|
-
* For this pattern to work well it needs to be difficult for a user of the erased type to
|
|
39
|
-
* implicitly use something other than a instance received from the package as an instance of the erased type in type safe code.
|
|
40
|
-
*
|
|
41
|
-
* This means that this type must not be able to be implicitly converted to from any strong type (not `any` or `never`),
|
|
42
|
-
* and no amount of auto complete or auto-implement refactoring will produce something that can be used as an erased type.
|
|
43
|
-
* This is accomplished by:
|
|
44
|
-
*
|
|
45
|
-
* 1. requiring that values of this type be an instance of this class.
|
|
46
|
-
* Typescript does not enforce this requirement for class: only for classes with protected or private members, so such member is included.
|
|
47
|
-
*
|
|
48
|
-
* 2. making this class impossible to get an instance of.
|
|
49
|
-
* This is done by having a private constructor.
|
|
50
|
-
*
|
|
51
|
-
* 3. ensuring different erased types also using this library can not be implicitly converted between each-other.
|
|
52
|
-
* This is done by using the "Name" type parameter.
|
|
53
|
-
* Note that just having the type parameter is not enough since the presence of type parameters has no impact on implicit conversion in TypeScript:
|
|
54
|
-
* only the usages of the type parameter matter.
|
|
55
|
-
*
|
|
56
|
-
* @sealed
|
|
57
|
-
* @public
|
|
58
|
-
*/
|
|
59
|
-
export class ErasedType {
|
|
60
|
-
/**
|
|
61
|
-
* This class should never exist at runtime, so make it un-constructable.
|
|
62
|
-
*/
|
|
63
|
-
constructor() { }
|
|
64
|
-
/**
|
|
65
|
-
* Since this class is a compile time only type brand, `instanceof` will never work with it.
|
|
66
|
-
* This `Symbol.hasInstance` implementation ensures that `instanceof` will error if used,
|
|
67
|
-
* and in TypeScript 5.3 and newer will produce a compile time error if used.
|
|
68
|
-
*/
|
|
69
|
-
static [Symbol.hasInstance](value) {
|
|
70
|
-
throw new Error("ErasedType is a compile time type brand not a real class that can be used with `instanceof` at runtime.");
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
5
|
/**
|
|
74
6
|
* Used to mark a `@sealed` interface in a strongly typed way to prevent external implementations.
|
|
7
|
+
*
|
|
75
8
|
* @remarks
|
|
76
9
|
* This is an alternative to {@link ErasedType} which is more ergonomic to implement in the case where the implementation can extend `ErasedTypeImplementation`.
|
|
77
10
|
*
|
|
78
11
|
* Users of interfaces extending this should never refer to anything about this class:
|
|
79
12
|
* migrating the type branding to another mechanism, like {@link ErasedType} should be considered a non-breaking change.
|
|
13
|
+
*
|
|
14
|
+
* @see {@link ErasedType} for version compatibility notes.
|
|
15
|
+
*
|
|
80
16
|
* @privateRemarks
|
|
81
17
|
* Implement interfaces which extend this by sub-classing {@link ErasedTypeImplementation}.
|
|
82
18
|
*
|
|
83
19
|
* This class should only be a `type` package export, preventing users from extending it directly.
|
|
20
|
+
* But since {@link ErasedTypeImplementation} does extend it, an implementation
|
|
21
|
+
* of the constructor must be provided, unlike {@link ErasedType}.
|
|
84
22
|
*
|
|
85
23
|
* 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.
|
|
86
24
|
* Any finer grained restrictions can be done as documentation, but not type enforced.
|
package/lib/erasedType.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"erasedType.js","sourceRoot":"","sources":["../src/erasedType.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AACH,MAAM,OAAgB,UAAU;IAU/B;;OAEG;IACH,gBAAuB,CAAC;IAExB;;;;OAIG;IACI,MAAM,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,KAAY;QAC9C,MAAM,IAAI,KAAK,CACd,yGAAyG,CACzG,CAAC;IACH,CAAC;CACD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,OAAgB,cAAc;IAUnC;;;;;;OAMG;IACH,gBAAyB,CAAC;CAC1B;AAED;;;;;;;;;GASG;AACH,MAAM,OAAgB,wBAEpB,SAAQ,cAA4E;IAKrF;QACC,KAAK,EAAE,CAAC;IACT,CAAC;IAED;;OAEG;IACI,MAAM,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAEjC,KAAc;QAEd,OAAO,CACN,OAAO,KAAK,KAAK,QAAQ;YACzB,KAAK,KAAK,IAAI;YACd,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAC1D,CAAC;IACH,CAAC;IAED;;;;;;;;;OASG;IACI,MAAM,CAAC,MAAM,CAEnB,KAAkD;QAElD,IAAI,CAAC,wBAAwB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,KAAe,CAAC,EAAE,CAAC;YAC/E,MAAM,IAAI,SAAS,CAAC,iCAAiC,CAAC,CAAC;QACxD,CAAC;IACF,CAAC;IAED;;;;OAIG;IACI,MAAM;QACZ,OAAO,IAAI,CAAC;IACb,CAAC;CACD","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/**\n * Erased type which can be used to expose a opaque/erased version of a type without referencing the actual type.\n * @remarks\n * This similar to the {@link https://en.wikipedia.org/wiki/Type_erasure | type erasure} pattern,\n * but for erasing types at the package boundary.\n *\n * This can be used to implement the TypeScript typing for the {@link https://en.wikipedia.org/wiki/Handle_(computing) | handle} pattern,\n * 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.\n * This should not be confused with the more specific IFluidHandle which is also named after this design pattern.\n *\n * Recommended usage is to use `interface` instead of `type` so tooling (such as tsc and refactoring tools)\n * uses the type name instead of expanding it.\n *\n * @example\n * ```typescript\n * // public sealed type\n * export interface ErasedMyType extends ErasedType<\"myPackage.MyType\"> {}\n * // internal type\n * export interface MyType {\n * \texample: number;\n * }\n * // Usage\n * function extract(input: ErasedMyType): MyType {\n * \treturn input as unknown as MyType;\n * }\n * function erase(input: MyType): ErasedMyType {\n * \treturn input as unknown as ErasedMyType;\n * }\n * ```\n *\n * Do not use this class with `instanceof`: this will always be false at runtime,\n * but the compiler may think it's true in some cases.\n * @privateRemarks\n * For this pattern to work well it needs to be difficult for a user of the erased type to\n * implicitly use something other than a instance received from the package as an instance of the erased type in type safe code.\n *\n * This means that this type must not be able to be implicitly converted to from any strong type (not `any` or `never`),\n * and no amount of auto complete or auto-implement refactoring will produce something that can be used as an erased type.\n * This is accomplished by:\n *\n * 1. requiring that values of this type be an instance of this class.\n * Typescript does not enforce this requirement for class: only for classes with protected or private members, so such member is included.\n *\n * 2. making this class impossible to get an instance of.\n * This is done by having a private constructor.\n *\n * 3. ensuring different erased types also using this library can not be implicitly converted between each-other.\n * This is done by using the \"Name\" type parameter.\n * Note that just having the type parameter is not enough since the presence of type parameters has no impact on implicit conversion in TypeScript:\n * only the usages of the type parameter matter.\n *\n * @sealed\n * @public\n */\nexport abstract class ErasedType<out Name = unknown> {\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 * @privateRemarks\n\t * `Name` is used as the return type of a method rather than a a simple readonly member as this allows types with two brands to be intersected without getting `never`.\n\t * The method takes in never to help emphasize that its not callable.\n\t */\n\tprotected abstract brand(dummy: never): Name;\n\n\t/**\n\t * This class should never exist at runtime, so make it un-constructable.\n\t */\n\tprivate constructor() {}\n\n\t/**\n\t * Since this class is a compile time only type brand, `instanceof` will never work with it.\n\t * This `Symbol.hasInstance` implementation ensures that `instanceof` will error if used,\n\t * and in TypeScript 5.3 and newer will produce a compile time error if used.\n\t */\n\tpublic static [Symbol.hasInstance](value: never): value is never {\n\t\tthrow new Error(\n\t\t\t\"ErasedType is a compile time type brand not a real class that can be used with `instanceof` at runtime.\",\n\t\t);\n\t}\n}\n\n/**\n * Used to mark a `@sealed` interface in a strongly typed way to prevent external implementations.\n * @remarks\n * This is an alternative to {@link ErasedType} which is more ergonomic to implement in the case where the implementation can extend `ErasedTypeImplementation`.\n *\n * Users of interfaces extending this should never refer to anything about this class:\n * migrating the type branding to another mechanism, like {@link ErasedType} should be considered a non-breaking change.\n * @privateRemarks\n * Implement interfaces which extend this by sub-classing {@link ErasedTypeImplementation}.\n *\n * This class should only be a `type` package export, preventing users from extending it directly.\n *\n * 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.\n * Any finer grained restrictions can be done as documentation, but not type enforced.\n * @sealed\n * @beta\n * @system\n */\nexport abstract class ErasedBaseType<out Name = unknown> {\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 * @privateRemarks\n\t * `Name` is used as the return type of a method rather than a a simple readonly member as this allows types with two brands to be intersected without getting `never`.\n\t * The method takes in never to help emphasize that its not callable.\n\t */\n\tprotected abstract brand(dummy: never): Name;\n\n\t/**\n\t * This class should never exist at runtime, so make it un-constructable.\n\t * @privateRemarks\n\t * From an API perspective, private would be preferred here.\n\t * However protected is almost as good since this class is not package exported,\n\t * and it allows ErasedTypeImplementation to extend this class.\n\t */\n\tprotected constructor() {}\n}\n\n/**\n * An implementation of an {@link ErasedBaseType}.\n * For a given erased type interface, there should be exactly one implementation of it, and it must be defined by the same code which defined the interface.\n *\n * @typeParam TInterface - The erased type interface this class implements.\n * @remarks\n * {@link ErasedBaseType} is package exported only as a type, not a value, so the only way to subclass it is via this class.\n * This limitation help enforce the pattern that there is only one implementation of a given erased type interface.\n * @internal\n */\nexport abstract class ErasedTypeImplementation<\n\tTInterface extends ErasedBaseType,\n> extends ErasedBaseType<TInterface extends ErasedBaseType<infer Name> ? Name : never> {\n\tprotected readonly brand!: (\n\t\tdummy: never,\n\t) => TInterface extends ErasedBaseType<infer Name> ? Name : never;\n\n\tprotected constructor() {\n\t\tsuper();\n\t}\n\n\t/**\n\t * {@link https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates|Type predicate} for narrowing the internal implementation type via `instanceof`.\n\t */\n\tpublic static [Symbol.hasInstance]<TThis extends { prototype: object }>(\n\t\tthis: TThis,\n\t\tvalue: unknown,\n\t): value is InstanceTypeRelaxed<TThis> {\n\t\treturn (\n\t\t\ttypeof value === \"object\" &&\n\t\t\tvalue !== null &&\n\t\t\tObject.prototype.isPrototypeOf.call(this.prototype, value)\n\t\t);\n\t}\n\n\t/**\n\t * {@link https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#assertion-functions|Type assertion} which narrows from ErasedBaseType to the internal implementation type.\n\t * @remarks\n\t * This does a checked conversion, throwing a `TypeError` if invalid.\n\t *\n\t * It would be safer if this narrowed from `TInterface`, but that is not possible since type parameters can not be accessed in static methods.\n\t * Replacing `ErasedTypeImplementation` with a generic function which returns a non-generic class could be used to work around this limitation if desired.\n\t *\n\t * Derived classes can provide their own customized narrowing function with a more specific types if desired.\n\t */\n\tpublic static narrow<TThis extends { prototype: object }>(\n\t\tthis: TThis,\n\t\tvalue: ErasedBaseType | InstanceTypeRelaxed<TThis>,\n\t): asserts value is InstanceTypeRelaxed<TThis> {\n\t\tif (!ErasedTypeImplementation[Symbol.hasInstance].call(this, value as object)) {\n\t\t\tthrow new TypeError(\"Invalid ErasedBaseType instance\");\n\t\t}\n\t}\n\n\t/**\n\t * Upcasts the instance to the erased interface type.\n\t * @remarks\n\t * This is mainly useful when inferring the interface type is required.\n\t */\n\tpublic upCast<TThis extends TInterface>(this: TThis): TInterface {\n\t\treturn this;\n\t}\n}\n\n/**\n * The same as the built-in InstanceType, but works on classes with private constructors.\n * @privateRemarks\n * This is based on the trick in {@link https://stackoverflow.com/a/74657881}.\n * @internal\n */\nexport type InstanceTypeRelaxed<TClass> = InstanceType<(new () => never) & TClass>;\n"]}
|
|
1
|
+
{"version":3,"file":"erasedType.js","sourceRoot":"","sources":["../src/erasedType.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAkGH;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,OAAgB,cAAc;IAUnC;;;;;;OAMG;IACH,gBAAyB,CAAC;CAC1B;AAED;;;;;;;;;GASG;AACH,MAAM,OAAgB,wBAEpB,SAAQ,cAA4E;IAKrF;QACC,KAAK,EAAE,CAAC;IACT,CAAC;IAED;;OAEG;IACI,MAAM,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAEjC,KAAc;QAEd,OAAO,CACN,OAAO,KAAK,KAAK,QAAQ;YACzB,KAAK,KAAK,IAAI;YACd,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAC1D,CAAC;IACH,CAAC;IAED;;;;;;;;;OASG;IACI,MAAM,CAAC,MAAM,CAEnB,KAAkD;QAElD,IAAI,CAAC,wBAAwB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,KAAe,CAAC,EAAE,CAAC;YAC/E,MAAM,IAAI,SAAS,CAAC,iCAAiC,CAAC,CAAC;QACxD,CAAC;IACF,CAAC;IAED;;;;OAIG;IACI,MAAM;QACZ,OAAO,IAAI,CAAC;IACb,CAAC;CACD","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/**\n * Erased type which can be used to expose a opaque/erased version of a type without referencing the actual type.\n * @remarks\n * This similar to the {@link https://en.wikipedia.org/wiki/Type_erasure | type erasure} pattern,\n * but for erasing types at the package boundary.\n *\n * This can be used to implement the TypeScript typing for the {@link https://en.wikipedia.org/wiki/Handle_(computing) | handle} pattern,\n * 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.\n * This should not be confused with the more specific IFluidHandle which is also named after this design pattern.\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 ErasedType 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 * Recommended usage is to use `interface` instead of `type` so tooling (such as tsc and refactoring tools)\n * uses the type name instead of expanding it.\n *\n * @example\n * package.json:\n * ```json\n * \"dependencies\": {\n * \"@fluidframework/erased-type-v1\": \"npm:@fluidframework/core-interfaces@~2.0.0\"\n * }\n * ```\n * source.ts:\n * ```typescript\n * import { ErasedType as ErasedTypeV1 } from \"@fluidframework/erased-type-v1\";\n * // public sealed type\n * export interface ErasedMyType extends ErasedTypeV1<\"myPackage.MyType\"> {}\n * // internal type\n * export interface MyType {\n * \texample: number;\n * }\n * // Usage\n * function extract(input: ErasedMyType): MyType {\n * \treturn input as unknown as MyType;\n * }\n * function erase(input: MyType): ErasedMyType {\n * \treturn input as unknown as ErasedMyType;\n * }\n * ```\n *\n * Do not use this class with `instanceof`: this will always be false at runtime,\n * but the compiler may think it's true in some cases.\n *\n * @privateRemarks\n * For this pattern to work well it needs to be difficult for a user of the erased type to\n * implicitly use something other than a instance received from the package as an instance of the erased type in type safe code.\n *\n * This means that this type must not be able to be implicitly converted to from any strong type (not `any` or `never`),\n * and no amount of auto complete or auto-implement refactoring will produce something that can be used as an erased type.\n * This is accomplished by:\n *\n * 1. requiring that values of this type be an instance of this class.\n * Typescript does not enforce this requirement for class: only for classes with protected or private members, so such member is included.\n *\n * 2. making this class impossible to get an instance of.\n * This is done by having a private constructor.\n *\n * 3. ensuring different erased types also using this library can not be implicitly converted between each-other.\n * This is done by using the \"Name\" type parameter.\n * Note that just having the type parameter is not enough since the presence of type parameters has no impact on implicit conversion in TypeScript:\n * only the usages of the type parameter matter.\n *\n * @sealed\n * @public\n */\nexport declare abstract class ErasedType<out Name = unknown> {\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 * @privateRemarks\n\t * `Name` is used as the return type of a method rather than a a simple readonly member as this allows types with two brands to be intersected without getting `never`.\n\t * The method takes in never to help emphasize that its not callable.\n\t */\n\tprotected abstract brand(dummy: never): Name;\n\n\t/**\n\t * This class should never exist at runtime, so make it un-constructable.\n\t */\n\tprivate constructor();\n\n\t/**\n\t * Since this class is a compile time only type brand, `instanceof` will never work with it.\n\t * This `Symbol.hasInstance` declaration (no definition) ensures that `instanceof` will\n\t * produce `ReferenceError` if used at runtime. And in TypeScript 5.3 and newer will produce\n\t * a compile time error if used.\n\t */\n\tpublic static [Symbol.hasInstance](value: never): value is never;\n}\n\n/**\n * Used to mark a `@sealed` interface in a strongly typed way to prevent external implementations.\n *\n * @remarks\n * This is an alternative to {@link ErasedType} which is more ergonomic to implement in the case where the implementation can extend `ErasedTypeImplementation`.\n *\n * Users of interfaces extending this should never refer to anything about this class:\n * migrating the type branding to another mechanism, like {@link ErasedType} should be considered a non-breaking change.\n *\n * @see {@link ErasedType} for version compatibility notes.\n *\n * @privateRemarks\n * Implement interfaces which extend this by sub-classing {@link ErasedTypeImplementation}.\n *\n * This class should only be a `type` package export, preventing users from extending it directly.\n * But since {@link ErasedTypeImplementation} does extend it, an implementation\n * of the constructor must be provided, unlike {@link ErasedType}.\n *\n * 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.\n * Any finer grained restrictions can be done as documentation, but not type enforced.\n * @sealed\n * @beta\n * @system\n */\nexport abstract class ErasedBaseType<out Name = unknown> {\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 * @privateRemarks\n\t * `Name` is used as the return type of a method rather than a a simple readonly member as this allows types with two brands to be intersected without getting `never`.\n\t * The method takes in never to help emphasize that its not callable.\n\t */\n\tprotected abstract brand(dummy: never): Name;\n\n\t/**\n\t * This class should never exist at runtime, so make it un-constructable.\n\t * @privateRemarks\n\t * From an API perspective, private would be preferred here.\n\t * However protected is almost as good since this class is not package exported,\n\t * and it allows ErasedTypeImplementation to extend this class.\n\t */\n\tprotected constructor() {}\n}\n\n/**\n * An implementation of an {@link ErasedBaseType}.\n * For a given erased type interface, there should be exactly one implementation of it, and it must be defined by the same code which defined the interface.\n *\n * @typeParam TInterface - The erased type interface this class implements.\n * @remarks\n * {@link ErasedBaseType} is package exported only as a type, not a value, so the only way to subclass it is via this class.\n * This limitation help enforce the pattern that there is only one implementation of a given erased type interface.\n * @internal\n */\nexport abstract class ErasedTypeImplementation<\n\tTInterface extends ErasedBaseType,\n> extends ErasedBaseType<TInterface extends ErasedBaseType<infer Name> ? Name : never> {\n\tprotected readonly brand!: (\n\t\tdummy: never,\n\t) => TInterface extends ErasedBaseType<infer Name> ? Name : never;\n\n\tprotected constructor() {\n\t\tsuper();\n\t}\n\n\t/**\n\t * {@link https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates|Type predicate} for narrowing the internal implementation type via `instanceof`.\n\t */\n\tpublic static [Symbol.hasInstance]<TThis extends { prototype: object }>(\n\t\tthis: TThis,\n\t\tvalue: unknown,\n\t): value is InstanceTypeRelaxed<TThis> {\n\t\treturn (\n\t\t\ttypeof value === \"object\" &&\n\t\t\tvalue !== null &&\n\t\t\tObject.prototype.isPrototypeOf.call(this.prototype, value)\n\t\t);\n\t}\n\n\t/**\n\t * {@link https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#assertion-functions|Type assertion} which narrows from ErasedBaseType to the internal implementation type.\n\t * @remarks\n\t * This does a checked conversion, throwing a `TypeError` if invalid.\n\t *\n\t * It would be safer if this narrowed from `TInterface`, but that is not possible since type parameters can not be accessed in static methods.\n\t * Replacing `ErasedTypeImplementation` with a generic function which returns a non-generic class could be used to work around this limitation if desired.\n\t *\n\t * Derived classes can provide their own customized narrowing function with a more specific types if desired.\n\t */\n\tpublic static narrow<TThis extends { prototype: object }>(\n\t\tthis: TThis,\n\t\tvalue: ErasedBaseType | InstanceTypeRelaxed<TThis>,\n\t): asserts value is InstanceTypeRelaxed<TThis> {\n\t\tif (!ErasedTypeImplementation[Symbol.hasInstance].call(this, value as object)) {\n\t\t\tthrow new TypeError(\"Invalid ErasedBaseType instance\");\n\t\t}\n\t}\n\n\t/**\n\t * Upcasts the instance to the erased interface type.\n\t * @remarks\n\t * This is mainly useful when inferring the interface type is required.\n\t */\n\tpublic upCast<TThis extends TInterface>(this: TThis): TInterface {\n\t\treturn this;\n\t}\n}\n\n/**\n * The same as the built-in InstanceType, but works on classes with private constructors.\n * @privateRemarks\n * This is based on the trick in {@link https://stackoverflow.com/a/74657881}.\n * @internal\n */\nexport type InstanceTypeRelaxed<TClass> = InstanceType<(new () => never) & TClass>;\n"]}
|
|
@@ -19,7 +19,7 @@ declare const RecursionMarkerSymbol: unique symbol;
|
|
|
19
19
|
* @privateRemarks
|
|
20
20
|
* WeakRef should be added when lib is updated to ES2021 or later.
|
|
21
21
|
*
|
|
22
|
-
* @
|
|
22
|
+
* @public
|
|
23
23
|
*/
|
|
24
24
|
export type ReadonlySupportedGenerics = IFluidHandle | Map<unknown, unknown> | Promise<unknown> | Set<unknown> | WeakMap<object, unknown> | WeakSet<object>;
|
|
25
25
|
/**
|
|
@@ -31,7 +31,7 @@ export type ReadonlySupportedGenerics = IFluidHandle | Map<unknown, unknown> | P
|
|
|
31
31
|
* depth limit when a recursive type is found. Use of `0` will stop applying
|
|
32
32
|
* `DeepReadonly` at the first point recursion is detected.
|
|
33
33
|
*
|
|
34
|
-
* @
|
|
34
|
+
* @public
|
|
35
35
|
* @system
|
|
36
36
|
*/
|
|
37
37
|
export type DeepReadonlyRecursionLimit = "NoLimit" | 0 | `+${string}`;
|
|
@@ -51,7 +51,7 @@ export type DeepReadonlyRecursionLimit = "NoLimit" | 0 | `+${string}`;
|
|
|
51
51
|
* exported anyway. All in namespace are left exported to avoid api-extractor
|
|
52
52
|
* potentially failing to validate other modules correctly.
|
|
53
53
|
*
|
|
54
|
-
* @
|
|
54
|
+
* @public
|
|
55
55
|
* @system
|
|
56
56
|
*/
|
|
57
57
|
export declare namespace InternalUtilityTypes {
|