Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose .is() typeguard on SharedObjectKind #21850

Merged
merged 5 commits into from
Jul 16, 2024

Conversation

Abe27342
Copy link
Contributor

@Abe27342 Abe27342 commented Jul 11, 2024

Description

With the removal of concrete DDS classes, one pattern that's come up repeatedly is customer code which previously checked instanceof MySharedObject (usually when the code supported multiple shared object types for whatever reason), which no longer works. This change adds a drop-in replacement to the public API surface.

Breaking Changes

As SharedObjectKind was marked sealed, this is non-breaking.

Alternatives Considered

We could expose free functions in each package easily e.g. by using a helper like this:

export function createSharedObjectTypeguard<TSharedObject>(
	kind: ISharedObjectKind<TSharedObject>,
): (loadable: IFluidLoadable) => loadable is IFluidLoadable & TSharedObject {
	const factoryType = kind.getFactory().type;
	return (loadable: IFluidLoadable): loadable is IFluidLoadable & TSharedObject => {
		return isChannel(loadable) && loadable.attributes.type === factoryType;
	};
}

Ultimately this will be more code though and arguably less discoverable.

We could also add back support for instanceof using Symbol.hasInstance (and the same implementation as .is), but due to microsoft/TypeScript#56536, this won't work for customers using TS below 5.5, so we'll need something else anyway at least for now.

@Abe27342 Abe27342 requested a review from a team as a code owner July 11, 2024 19:38
@github-actions github-actions bot added area: dds Issues related to distributed data structures public api change Changes to a public API base: main PRs targeted against main branch labels Jul 11, 2024
Abram Sanderson added 2 commits July 11, 2024 12:52
Copy link
Contributor

@anthony-murphy anthony-murphy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this. Its discoverable, and an easy change given that all instanceof uses already have the shared object type. curious how @CraigMacomber feels about having an implementation leak through the type erasure like this, and if he foresees any problems from that

@Abe27342 Abe27342 requested a review from a team as a code owner July 11, 2024 22:31
@github-actions github-actions bot added area: dds: sharedstring area: framework Framework is a tag for issues involving the developer framework. Eg Aqueduct and removed area: framework Framework is a tag for issues involving the developer framework. Eg Aqueduct area: dds: sharedstring labels Jul 11, 2024
@msfluid-bot
Copy link
Collaborator

msfluid-bot commented Jul 11, 2024

@fluid-example/bundle-size-tests: +708 Bytes
Metric NameBaseline SizeCompare SizeSize Diff
aqueduct.js 457.54 KB 457.63 KB +91 Bytes
azureClient.js 555.3 KB 555.41 KB +116 Bytes
connectionState.js 680 Bytes 680 Bytes No change
containerRuntime.js 258.68 KB 258.7 KB +14 Bytes
fluidFramework.js 391.52 KB 391.58 KB +70 Bytes
loader.js 134.07 KB 134.08 KB +14 Bytes
map.js 42.12 KB 42.18 KB +64 Bytes
matrix.js 145.63 KB 145.69 KB +64 Bytes
odspClient.js 523.08 KB 523.18 KB +105 Bytes
odspDriver.js 97.17 KB 97.19 KB +21 Bytes
odspPrefetchSnapshot.js 42.27 KB 42.29 KB +14 Bytes
sharedString.js 162.64 KB 162.7 KB +64 Bytes
sharedTree.js 382.03 KB 382.09 KB +64 Bytes
Total Size 3.27 MB 3.27 MB +708 Bytes

Baseline commit: 957b194

Generated by 🚫 dangerJS against 4c97f7c

@CraigMacomber
Copy link
Contributor

I like this. Its discoverable, and an easy change given that all instanceof uses already have the shared object type. curious how @CraigMacomber feels about having an implementation leak through the type erasure like this, and if he foresees any problems from that

I don't think this is leaking any implementation info: nothing in the exposed API says how it works (well the remarks comment does a bit, but I think thats ok as its documenting historical things not usage contracts)

One of the reasons I created SharedObjectKind was to be able to add things like this to all of them in a consistent way easily. Since the interface is sealed, we are allowed to add to it like this as a non breaking change.

I don't see any problem supporting this going forward. either, so I think its a good change.

@github-actions github-actions bot added area: dds: sharedstring area: framework Framework is a tag for issues involving the developer framework. Eg Aqueduct labels Jul 16, 2024
@Abe27342 Abe27342 enabled auto-merge (squash) July 16, 2024 18:55
@Abe27342 Abe27342 requested a review from a team July 16, 2024 18:59
@Abe27342 Abe27342 merged commit 6bdec1a into microsoft:main Jul 16, 2024
32 checks passed
@Abe27342 Abe27342 deleted the typeguard-sharedobjectkind branch July 16, 2024 21:02
RishhiB pushed a commit to RishhiB/FluidFramework-1 that referenced this pull request Jul 18, 2024
## Description

With the removal of concrete DDS classes, one pattern that's come up
repeatedly is customer code which previously checked `instanceof
MySharedObject` (usually when the code supported multiple shared object
types for whatever reason), which no longer works. This change adds a
drop-in replacement to the public API surface.

## Breaking Changes

As `SharedObjectKind` was marked sealed, this is non-breaking.


## Alternatives Considered

We could expose free functions in each package easily e.g. by using a
helper like this:

```typescript
export function createSharedObjectTypeguard<TSharedObject>(
	kind: ISharedObjectKind<TSharedObject>,
): (loadable: IFluidLoadable) => loadable is IFluidLoadable & TSharedObject {
	const factoryType = kind.getFactory().type;
	return (loadable: IFluidLoadable): loadable is IFluidLoadable & TSharedObject => {
		return isChannel(loadable) && loadable.attributes.type === factoryType;
	};
}
```

Ultimately this will be more code though and arguably less discoverable.

We could also add back support for `instanceof` using
`Symbol.hasInstance` (and the same implementation as `.is`), but due to
microsoft/TypeScript#56536, this won't work
for customers using TS below 5.5, so we'll need something else anyway at
least for now.

---------

Co-authored-by: Abram Sanderson <[email protected]>
Co-authored-by: Craig Macomber (Microsoft) <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: dds: sharedstring area: dds Issues related to distributed data structures area: framework Framework is a tag for issues involving the developer framework. Eg Aqueduct base: main PRs targeted against main branch public api change Changes to a public API
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants