From b0b9c6751116928495c4fd22abed05d8198bb430 Mon Sep 17 00:00:00 2001 From: Alex Villarreal <716334+alexvy86@users.noreply.github.com> Date: Tue, 3 Dec 2024 16:15:42 +0000 Subject: [PATCH 1/8] Update return type of free functions in utils.ts --- packages/dds/map/src/directory.ts | 4 ++-- .../api-report/shared-object-base.legacy.alpha.api.md | 4 ++-- packages/dds/shared-object-base/src/utils.ts | 6 ++---- .../test-end-to-end-tests/src/test/gc/gcTestSummaryUtils.ts | 2 +- .../src/test/gc/gcTombstoneDataStores.spec.ts | 2 +- 5 files changed, 8 insertions(+), 10 deletions(-) diff --git a/packages/dds/map/src/directory.ts b/packages/dds/map/src/directory.ts index c867e3907db6..cc3353123c3c 100644 --- a/packages/dds/map/src/directory.ts +++ b/packages/dds/map/src/directory.ts @@ -784,8 +784,8 @@ export class SharedDirectory const localValue = this.makeLocal( key, currentSubDir.absolutePath, - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument - parseHandles(serializable, this.serializer), + // eslint-disable-next-line import/no-deprecated + parseHandles(serializable, this.serializer) as ISerializableValue, ); currentSubDir.populateStorage(key, localValue); } diff --git a/packages/dds/shared-object-base/api-report/shared-object-base.legacy.alpha.api.md b/packages/dds/shared-object-base/api-report/shared-object-base.legacy.alpha.api.md index de8c9114e47c..d74c370f812e 100644 --- a/packages/dds/shared-object-base/api-report/shared-object-base.legacy.alpha.api.md +++ b/packages/dds/shared-object-base/api-report/shared-object-base.legacy.alpha.api.md @@ -33,10 +33,10 @@ export interface ISharedObjectKind { } // @alpha -export function makeHandlesSerializable(value: unknown, serializer: IFluidSerializer, bind: IFluidHandle): any; +export function makeHandlesSerializable(value: unknown, serializer: IFluidSerializer, bind: IFluidHandle): unknown; // @alpha -export function parseHandles(value: unknown, serializer: IFluidSerializer): any; +export function parseHandles(value: unknown, serializer: IFluidSerializer): unknown; // @alpha export abstract class SharedObject extends SharedObjectCore { diff --git a/packages/dds/shared-object-base/src/utils.ts b/packages/dds/shared-object-base/src/utils.ts index c80ef0d506c1..2ef68500d95b 100644 --- a/packages/dds/shared-object-base/src/utils.ts +++ b/packages/dds/shared-object-base/src/utils.ts @@ -45,8 +45,7 @@ export function makeHandlesSerializable( value: unknown, serializer: IFluidSerializer, bind: IFluidHandle, - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO: AB#26129 use unknown instead of any (legacy breaking) -): any { +): unknown { return serializer.encode(value, bind); } @@ -61,8 +60,7 @@ export function makeHandlesSerializable( * @legacy * @alpha */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO: AB#26129 use unknown instead of any (legacy breaking) -export function parseHandles(value: unknown, serializer: IFluidSerializer): any { +export function parseHandles(value: unknown, serializer: IFluidSerializer): unknown { return serializer.decode(value); } diff --git a/packages/test/test-end-to-end-tests/src/test/gc/gcTestSummaryUtils.ts b/packages/test/test-end-to-end-tests/src/test/gc/gcTestSummaryUtils.ts index 65e58c6c30b1..9eed93d1e39d 100644 --- a/packages/test/test-end-to-end-tests/src/test/gc/gcTestSummaryUtils.ts +++ b/packages/test/test-end-to-end-tests/src/test/gc/gcTestSummaryUtils.ts @@ -171,7 +171,7 @@ export function manufactureHandle( const handle: IFluidHandleInternal = parseHandles( { type: "__fluid_handle__", url }, serializer, - ); + ) as IFluidHandleInternal; return handle; } diff --git a/packages/test/test-end-to-end-tests/src/test/gc/gcTombstoneDataStores.spec.ts b/packages/test/test-end-to-end-tests/src/test/gc/gcTombstoneDataStores.spec.ts index 6191eb9d2f79..3a16b1b72339 100644 --- a/packages/test/test-end-to-end-tests/src/test/gc/gcTombstoneDataStores.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/gc/gcTombstoneDataStores.spec.ts @@ -583,7 +583,7 @@ describeCompat("GC data store tombstone tests", "NoCompat", (getTestObjectProvid const handle: IFluidHandle = parseHandles( { type: "__fluid_handle__", url: unreferencedId }, serializer, - ); + ) as IFluidHandle; // This fails because the DataStore is tombstoned let tombstoneError: ExpectedTombstoneError | undefined; From 391def4e4ddc76f9865026b29e5107c2ce1e9865 Mon Sep 17 00:00:00 2001 From: Alex Villarreal <716334+alexvy86@users.noreply.github.com> Date: Tue, 3 Dec 2024 16:22:59 +0000 Subject: [PATCH 2/8] Replace any with void --- .../api-report/shared-object-base.legacy.alpha.api.md | 4 ++-- packages/dds/shared-object-base/src/sharedObject.ts | 6 ++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/dds/shared-object-base/api-report/shared-object-base.legacy.alpha.api.md b/packages/dds/shared-object-base/api-report/shared-object-base.legacy.alpha.api.md index d74c370f812e..f2ffe8a6a229 100644 --- a/packages/dds/shared-object-base/api-report/shared-object-base.legacy.alpha.api.md +++ b/packages/dds/shared-object-base/api-report/shared-object-base.legacy.alpha.api.md @@ -78,8 +78,8 @@ export abstract class SharedObjectCore(executor: (resolve: (value: T | PromiseLike) => void, reject: (reason?: any) => void) => void): Promise; protected onConnect(): void; - protected abstract onDisconnect(): any; - protected abstract processCore(message: ISequencedDocumentMessage, local: boolean, localOpMetadata: unknown): any; + protected abstract onDisconnect(): void; + protected abstract processCore(message: ISequencedDocumentMessage, local: boolean, localOpMetadata: unknown): void; protected reSubmitCore(content: any, localOpMetadata: unknown): void; protected rollback(content: any, localOpMetadata: unknown): void; // (undocumented) diff --git a/packages/dds/shared-object-base/src/sharedObject.ts b/packages/dds/shared-object-base/src/sharedObject.ts index de02418c1e7c..e11456e80874 100644 --- a/packages/dds/shared-object-base/src/sharedObject.ts +++ b/packages/dds/shared-object-base/src/sharedObject.ts @@ -389,15 +389,13 @@ export abstract class SharedObjectCore< message: ISequencedDocumentMessage, local: boolean, localOpMetadata: unknown, - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO: AB#26129 use void instead of any (legacy breaking) - ): any; + ): void; /** * Called when the object has disconnected from the delta stream. */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO: AB#26129 change return type to void (legacy breaking) - protected abstract onDisconnect(): any; + protected abstract onDisconnect(): void; /** * The serializer to serialize / parse handles. From 4f9f7874853e69b422c97d0878612750312be653 Mon Sep 17 00:00:00 2001 From: Alex Villarreal <716334+alexvy86@users.noreply.github.com> Date: Tue, 3 Dec 2024 16:30:52 +0000 Subject: [PATCH 3/8] Updates in SharedObjectCore --- .../shared-object-base.legacy.alpha.api.md | 10 +++++----- .../dds/shared-object-base/src/sharedObject.ts | 15 +++++---------- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/packages/dds/shared-object-base/api-report/shared-object-base.legacy.alpha.api.md b/packages/dds/shared-object-base/api-report/shared-object-base.legacy.alpha.api.md index f2ffe8a6a229..81565ead57ff 100644 --- a/packages/dds/shared-object-base/api-report/shared-object-base.legacy.alpha.api.md +++ b/packages/dds/shared-object-base/api-report/shared-object-base.legacy.alpha.api.md @@ -53,7 +53,7 @@ export abstract class SharedObject extends EventEmitterWithErrorHandling implements ISharedObject { constructor(id: string, runtime: IFluidDataStoreRuntime, attributes: IChannelAttributes); - protected abstract applyStashedOp(content: any): void; + protected abstract applyStashedOp(content: unknown): void; // (undocumented) readonly attributes: IChannelAttributes; bindToContext(): void; @@ -76,16 +76,16 @@ export abstract class SharedObjectCore; protected abstract loadCore(services: IChannelStorageService): Promise; protected readonly logger: ITelemetryLoggerExt; - protected newAckBasedPromise(executor: (resolve: (value: T | PromiseLike) => void, reject: (reason?: any) => void) => void): Promise; + protected newAckBasedPromise(executor: (resolve: (value: T | PromiseLike) => void, reject: (reason?: unknown) => void) => void): Promise; protected onConnect(): void; protected abstract onDisconnect(): void; protected abstract processCore(message: ISequencedDocumentMessage, local: boolean, localOpMetadata: unknown): void; - protected reSubmitCore(content: any, localOpMetadata: unknown): void; - protected rollback(content: any, localOpMetadata: unknown): void; + protected reSubmitCore(content: unknown, localOpMetadata: unknown): void; + protected rollback(content: unknown, localOpMetadata: unknown): void; // (undocumented) protected runtime: IFluidDataStoreRuntime; protected abstract get serializer(): IFluidSerializer; - protected submitLocalMessage(content: any, localOpMetadata?: unknown): void; + protected submitLocalMessage(content: unknown, localOpMetadata?: unknown): void; abstract summarize(fullTree?: boolean, trackState?: boolean, telemetryContext?: ITelemetryContext): Promise; } diff --git a/packages/dds/shared-object-base/src/sharedObject.ts b/packages/dds/shared-object-base/src/sharedObject.ts index e11456e80874..640e9ffad163 100644 --- a/packages/dds/shared-object-base/src/sharedObject.ts +++ b/packages/dds/shared-object-base/src/sharedObject.ts @@ -410,8 +410,7 @@ export abstract class SharedObjectCore< * and not sent to the server. This will be sent back when this message is received back from the server. This is * also sent if we are asked to resubmit the message. */ - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- TODO: AB#26129 use unknown instead of any (legacy breaking) - protected submitLocalMessage(content: any, localOpMetadata: unknown = undefined): void { + protected submitLocalMessage(content: unknown, localOpMetadata: unknown = undefined): void { this.verifyNotClosed(); if (this.isAttached()) { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion @@ -449,8 +448,7 @@ export abstract class SharedObjectCore< * @param content - The content of the original message. * @param localOpMetadata - The local metadata associated with the original message. */ - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- TODO: AB#26129 use unknown instead of any (legacy breaking) - protected reSubmitCore(content: any, localOpMetadata: unknown): void { + protected reSubmitCore(content: unknown, localOpMetadata: unknown): void { this.submitLocalMessage(content, localOpMetadata); } @@ -463,8 +461,7 @@ export abstract class SharedObjectCore< protected async newAckBasedPromise( executor: ( resolve: (value: T | PromiseLike) => void, - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO: AB#26129 use unknown instead of any (legacy breaking) - reject: (reason?: any) => void, + reject: (reason?: unknown) => void, ) => void, ): Promise { let rejectBecauseDispose: () => void; @@ -617,8 +614,7 @@ export abstract class SharedObjectCore< /** * Revert an op */ - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- TODO: AB#26129 use unknown instead of any (legacy breaking) - protected rollback(content: any, localOpMetadata: unknown): void { + protected rollback(content: unknown, localOpMetadata: unknown): void { throw new Error("rollback not supported"); } @@ -639,8 +635,7 @@ export abstract class SharedObjectCore< * * @param content - Contents of a stashed op. */ - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- TODO: AB#26129 use unknown instead of any (legacy breaking) - protected abstract applyStashedOp(content: any): void; + protected abstract applyStashedOp(content: unknown): void; /** * Emit an event. This function is only intended for use by DDS classes that extend SharedObject/SharedObjectCore, From 7618fd14da3cda2860dcf374c3b96635ccf2b8c6 Mon Sep 17 00:00:00 2001 From: Alex Villarreal <716334+alexvy86@users.noreply.github.com> Date: Tue, 3 Dec 2024 16:42:44 +0000 Subject: [PATCH 4/8] Update IFluidSerializer --- .../packages/property-dds/src/propertyTree.ts | 2 +- experimental/dds/ot/ot/src/ot.ts | 2 +- .../dds/tree/src/SummaryBackCompatibility.ts | 2 +- packages/dds/cell/src/cell.ts | 3 +-- .../src/consensusOrderedCollection.ts | 3 ++- .../shared-object-base.legacy.alpha.api.md | 8 ++++---- packages/dds/shared-object-base/src/serializer.ts | 12 ++++-------- 7 files changed, 14 insertions(+), 18 deletions(-) diff --git a/experimental/PropertyDDS/packages/property-dds/src/propertyTree.ts b/experimental/PropertyDDS/packages/property-dds/src/propertyTree.ts index 7c73e6b83290..da10e48fba88 100644 --- a/experimental/PropertyDDS/packages/property-dds/src/propertyTree.ts +++ b/experimental/PropertyDDS/packages/property-dds/src/propertyTree.ts @@ -615,7 +615,7 @@ export class SharedPropertyTree extends SharedObject { const handleTableChunk = await storage.readBlob("properties"); const utf8 = bufferToString(handleTableChunk, "utf8"); - const snapshot: ISnapshot = this.serializer.parse(utf8); + const snapshot: ISnapshot = this.serializer.parse(utf8) as ISnapshot; this.useMH = snapshot.useMH; try { diff --git a/experimental/dds/ot/ot/src/ot.ts b/experimental/dds/ot/ot/src/ot.ts index ae067c9f9914..8ee38bb686be 100644 --- a/experimental/dds/ot/ot/src/ot.ts +++ b/experimental/dds/ot/ot/src/ot.ts @@ -98,7 +98,7 @@ export abstract class SharedOT extends SharedObject { protected async loadCore(storage: IChannelStorageService): Promise { const blob = await storage.readBlob("header"); const rawContent = bufferToString(blob, "utf8"); - this.global = this.local = this.serializer.parse(rawContent); + this.global = this.local = this.serializer.parse(rawContent) as TState; } protected onDisconnect() {} diff --git a/experimental/dds/tree/src/SummaryBackCompatibility.ts b/experimental/dds/tree/src/SummaryBackCompatibility.ts index 1d74bed4d9d6..520a9af103ab 100644 --- a/experimental/dds/tree/src/SummaryBackCompatibility.ts +++ b/experimental/dds/tree/src/SummaryBackCompatibility.ts @@ -28,7 +28,7 @@ import { export function deserialize(jsonSummary: string, serializer: IFluidSerializer): SharedTreeSummaryBase { let summary: Partial; try { - summary = serializer.parse(jsonSummary); + summary = serializer.parse(jsonSummary) as Partial; } catch { fail('Json syntax error in Summary'); } diff --git a/packages/dds/cell/src/cell.ts b/packages/dds/cell/src/cell.ts index d810d7d48316..903111ca85bc 100644 --- a/packages/dds/cell/src/cell.ts +++ b/packages/dds/cell/src/cell.ts @@ -205,8 +205,7 @@ export class SharedCell protected async loadCore(storage: IChannelStorageService): Promise { const content = await readAndParse(storage, snapshotFileName); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - this.data = this.serializer.decode(content.value); + this.data = this.serializer.decode(content.value) as Serializable; this.attribution = content.attribution; } diff --git a/packages/dds/ordered-collection/src/consensusOrderedCollection.ts b/packages/dds/ordered-collection/src/consensusOrderedCollection.ts index 36ca98ffa4d0..d89e556b3996 100644 --- a/packages/dds/ordered-collection/src/consensusOrderedCollection.ts +++ b/packages/dds/ordered-collection/src/consensusOrderedCollection.ts @@ -270,7 +270,8 @@ export class ConsensusOrderedCollection const blob = await storage.readBlob(snapshotFileNameTracking); const rawContentTracking = bufferToString(blob, "utf8"); const content = this.deserializeValue(rawContentTracking, this.serializer); - this.jobTracking = new Map(content) as JobTrackingInfo; + // TODO: this was using any before, but probably should be using a better type + this.jobTracking = new Map(content as any) as JobTrackingInfo; assert( this.data.size() === 0, diff --git a/packages/dds/shared-object-base/api-report/shared-object-base.legacy.alpha.api.md b/packages/dds/shared-object-base/api-report/shared-object-base.legacy.alpha.api.md index 81565ead57ff..4eab532dc67f 100644 --- a/packages/dds/shared-object-base/api-report/shared-object-base.legacy.alpha.api.md +++ b/packages/dds/shared-object-base/api-report/shared-object-base.legacy.alpha.api.md @@ -6,10 +6,10 @@ // @alpha (undocumented) export interface IFluidSerializer { - decode(input: any): any; - encode(value: any, bind: IFluidHandle): any; - parse(value: string): any; - stringify(value: any, bind: IFluidHandle): string; + decode(input: unknown): unknown; + encode(value: unknown, bind: IFluidHandle): unknown; + parse(value: string): unknown; + stringify(value: unknown, bind: IFluidHandle): string; } // @alpha diff --git a/packages/dds/shared-object-base/src/serializer.ts b/packages/dds/shared-object-base/src/serializer.ts index 7da2b8ade8ae..b68b949dbc8a 100644 --- a/packages/dds/shared-object-base/src/serializer.ts +++ b/packages/dds/shared-object-base/src/serializer.ts @@ -31,8 +31,7 @@ export interface IFluidSerializer { * The original `input` object is not mutated. This method will shallowly clones all objects in the path from * the root to any replaced handles. (If no handles are found, returns the original object.) */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO: AB#26129 use unknown instead of any (legacy breaking) - encode(value: any, bind: IFluidHandle): any; + encode(value: unknown, bind: IFluidHandle): unknown; /** * Given a fully-jsonable object tree that may have encoded handle objects embedded within, will return an @@ -43,21 +42,18 @@ export interface IFluidSerializer { * * The decoded handles are implicitly bound to the handle context of this serializer. */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO: AB#26129 use unknown instead of any (legacy breaking) - decode(input: any): any; + decode(input: unknown): unknown; /** * Stringifies a given value. Converts any IFluidHandle to its stringified equivalent. */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO: AB#26129 use unknown instead of any (legacy breaking) - stringify(value: any, bind: IFluidHandle): string; + stringify(value: unknown, bind: IFluidHandle): string; /** * Parses the given JSON input string and returns the JavaScript object defined by it. Any Fluid * handles will be realized as part of the parse */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO: AB#26129 use unknown instead of any (legacy breaking) - parse(value: string): any; + parse(value: string): unknown; } /** From 4eab5a34a8888112610b6f724cee85be68c937a6 Mon Sep 17 00:00:00 2001 From: Alex Villarreal <716334+alexvy86@users.noreply.github.com> Date: Tue, 3 Dec 2024 16:50:14 +0000 Subject: [PATCH 5/8] Update input types in FluidSerializer --- packages/dds/shared-object-base/src/serializer.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/dds/shared-object-base/src/serializer.ts b/packages/dds/shared-object-base/src/serializer.ts index b68b949dbc8a..ef626557ef4d 100644 --- a/packages/dds/shared-object-base/src/serializer.ts +++ b/packages/dds/shared-object-base/src/serializer.ts @@ -83,14 +83,13 @@ export class FluidSerializer implements IFluidSerializer { * * Any unbound handles encountered are bound to the provided IFluidHandle. */ - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- TODO: AB#26129 ddsFuzzHarness breaks when we update any->unknown - public encode(input: any, bind: IFluidHandleInternal): any { + // eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO: AB#26129 ddsFuzzHarness breaks when we update any->unknown + public encode(input: unknown, bind: IFluidHandleInternal): any { // If the given 'input' cannot contain handles, return it immediately. Otherwise, // return the result of 'recursivelyReplace()'. // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions return !!input && typeof input === "object" - ? // eslint-disable-next-line @typescript-eslint/no-unsafe-argument -- TODO: AB#26129 ddsFuzzHarness breaks when we update any->unknown - this.recursivelyReplace(input, this.encodeValue, bind) + ? this.recursivelyReplace(input, this.encodeValue, bind) : input; } From 3cfd4027f382af778b728f2d438f9979e0958185 Mon Sep 17 00:00:00 2001 From: Alex Villarreal <716334+alexvy86@users.noreply.github.com> Date: Tue, 3 Dec 2024 17:24:52 +0000 Subject: [PATCH 6/8] Update FluidSerializer and ddsFuzzHarness --- packages/dds/shared-object-base/src/serializer.ts | 6 ++---- packages/dds/test-dds-utils/src/ddsFuzzHarness.ts | 7 ++----- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/packages/dds/shared-object-base/src/serializer.ts b/packages/dds/shared-object-base/src/serializer.ts index ef626557ef4d..6844fa93be07 100644 --- a/packages/dds/shared-object-base/src/serializer.ts +++ b/packages/dds/shared-object-base/src/serializer.ts @@ -83,8 +83,7 @@ export class FluidSerializer implements IFluidSerializer { * * Any unbound handles encountered are bound to the provided IFluidHandle. */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO: AB#26129 ddsFuzzHarness breaks when we update any->unknown - public encode(input: unknown, bind: IFluidHandleInternal): any { + public encode(input: unknown, bind: IFluidHandleInternal): unknown { // If the given 'input' cannot contain handles, return it immediately. Otherwise, // return the result of 'recursivelyReplace()'. // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions @@ -102,8 +101,7 @@ export class FluidSerializer implements IFluidSerializer { * * The decoded handles are implicitly bound to the handle context of this serializer. */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO: AB#26129 ddsFuzzHarness breaks when we update any->unknown - public decode(input: unknown): any { + public decode(input: unknown): unknown { // If the given 'input' cannot contain handles, return it immediately. Otherwise, // return the result of 'recursivelyReplace()'. // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions diff --git a/packages/dds/test-dds-utils/src/ddsFuzzHarness.ts b/packages/dds/test-dds-utils/src/ddsFuzzHarness.ts index a49fcfb731b0..4ac3557f0dff 100644 --- a/packages/dds/test-dds-utils/src/ddsFuzzHarness.ts +++ b/packages/dds/test-dds-utils/src/ddsFuzzHarness.ts @@ -1460,14 +1460,11 @@ export async function runTestForSeed< let operationCount = 0; const generator = model.generatorFactory(); const finalState = await performFuzzActionsAsync( - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - async (state) => serializer.encode(await generator(state), bind), + async (state) => serializer.encode(await generator(state), bind) as TOperation, async (state, operation) => { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const decodedHandles = serializer.decode(operation); + const decodedHandles = serializer.decode(operation) as TOperation; options.emitter.emit("operation", decodedHandles); operationCount++; - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument return model.reducer(state, decodedHandles); }, initialState, From 9d440cf7598af7dd736944f0077e22ca1aac665f Mon Sep 17 00:00:00 2001 From: Alex Villarreal <716334+alexvy86@users.noreply.github.com> Date: Fri, 13 Dec 2024 16:11:48 +0000 Subject: [PATCH 7/8] Improve typing --- .../dds/ordered-collection/src/consensusOrderedCollection.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/dds/ordered-collection/src/consensusOrderedCollection.ts b/packages/dds/ordered-collection/src/consensusOrderedCollection.ts index d89e556b3996..d52055391bc4 100644 --- a/packages/dds/ordered-collection/src/consensusOrderedCollection.ts +++ b/packages/dds/ordered-collection/src/consensusOrderedCollection.ts @@ -270,8 +270,9 @@ export class ConsensusOrderedCollection const blob = await storage.readBlob(snapshotFileNameTracking); const rawContentTracking = bufferToString(blob, "utf8"); const content = this.deserializeValue(rawContentTracking, this.serializer); - // TODO: this was using any before, but probably should be using a better type - this.jobTracking = new Map(content as any) as JobTrackingInfo; + this.jobTracking = new Map( + content as Iterable, + ); assert( this.data.size() === 0, From 72e01b901f68cf7498cb94353c41ea22a7914d68 Mon Sep 17 00:00:00 2001 From: Alex Villarreal <716334+alexvy86@users.noreply.github.com> Date: Wed, 8 Jan 2025 22:14:11 +0000 Subject: [PATCH 8/8] Add changeset --- .changeset/smooth-roses-repair.md | 56 +++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 .changeset/smooth-roses-repair.md diff --git a/.changeset/smooth-roses-repair.md b/.changeset/smooth-roses-repair.md new file mode 100644 index 000000000000..ad463bc29204 --- /dev/null +++ b/.changeset/smooth-roses-repair.md @@ -0,0 +1,56 @@ +--- +"@fluidframework/shared-object-base": minor +--- +--- +"section": legacy +--- + +Replace 'any' in return type for several APIs + +To improve type safety of the Fluid Framework legacy+alpha API surface, +we're moving away from using the `any` type in favor of `unknown`. + +We mostly expect that any changes required in consumers of these APIs will be limited to having to provide explicit types +when calling any of the APIs whose return value changed to `unknown`, like `IFluidSerializer.parse()`. + +So code that looked like this: + +```typescript +// 'myVariable' ended up typed as 'any' here and TypeScript would not do any type-safety checks on it. +const myVariable = this.serializer.parse(stringHeader); +``` + +Will now have to look like this: + +```typescript +// Do this if you know the type of the object you expect to get back. +const myVariable = this.serializer.parse(stringHeader) as MyType; + +// Alternatively, this will maintain current behavior but also means no type-safety checks will be done by TS. +// const myVariable = this.serializer.parse(stringHeader) as any; +``` + +The appropriate type will depend on what the calling code is doing and the objects it expects to be dealing with. + +We further encourage consumers of any of these APIs to add runtime checks +to validate that the returned object actually matches the expected type. + +The list of affected APIs is as follows: + +- `IFluidSerializer.encode(...)` now takes `value: unknown` instead of `value: any` and returns `unknown` instead of `any`. +- `IFluidSerializer.decode(...)` now takes `input: unknown` instead of `input: any` and returns `unknown` instead of `any`. +- `IFluidSerializer.stringify(...)` now takes `value: unknown` instead of `value: any`. +- `IFluidSerializer.parse(...)` now returns `unknown` instead of `any`. +- `SharedObjectCore.applyStashedOps(...)` now takes `content: unknown` instead of `content: any`. +- `SharedObjectCore.rollback(...)` now takes `content: unknown` instead of `content: any`. +- `SharedObjectCore.submitLocalMessage(...)` now takes `content: unknown` instead of `content: any`. +- `SharedObjectCore.reSubmitCore(...)` now takes `content: unknown` instead of `content: any`. +- In `SharedObjectCore.newAckBasedPromise(...)` the `executor` parameter now takes `reject: (reason?: unknown)` + instead of `reject: (reason?: any)`. +- `makeHandlesSerializable(...)` now returns `unknown` instead of `any`. +- `parseHandles(...)` now returns `unknown` instead of `any`. + +Additionally, the following APIs were never designed to return a value and have thus been updated to return `void` instead of `any`: + +- `SharedObjectCore.processCore(...)`. +- `SharedObjectCore.onDisconnect(...)`