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

feat(tree): Include list of properties that changed in nodeChanged event #22229

Merged
merged 45 commits into from
Sep 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
8577620
WIP - test works
alexvy86 Jul 24, 2024
3cf732b
Leaner test
alexvy86 Jul 24, 2024
1e9f71f
Use readonly set and remove only from test
alexvy86 Jul 25, 2024
dc87e8d
Expose changed properties in simple-tree
alexvy86 Jul 25, 2024
014288f
Fix test at simple-tree layer
alexvy86 Jul 25, 2024
6d47762
Formatting and API reports
alexvy86 Jul 26, 2024
9763240
Write simple-tree test in terms of view operations, not editor operat…
alexvy86 Jul 26, 2024
b0d072e
Fluid framework API reports
alexvy86 Jul 29, 2024
4477a8b
Test map and array nodes
alexvy86 Jul 29, 2024
d0b6074
Add note
alexvy86 Jul 29, 2024
8e944b6
Formatting
alexvy86 Jul 29, 2024
84809d7
Merge branch 'main' into node-changed-details
alexvy86 Jul 30, 2024
8f0b81e
Return forked checkout object
alexvy86 Jul 30, 2024
6c6025f
Translate to view keys
alexvy86 Jul 30, 2024
604c289
Fix circular dependency
alexvy86 Jul 30, 2024
0b0e2ad
Changeset
alexvy86 Jul 30, 2024
25b528a
PR feedback
alexvy86 Jul 31, 2024
f5553b6
Move cherk for array case to treeNodeKernel
alexvy86 Jul 31, 2024
94df816
Remove unused import
alexvy86 Jul 31, 2024
000db71
Move assert to better place
alexvy86 Jul 31, 2024
135659d
Update fluid-framework API reports
alexvy86 Jul 31, 2024
47a4a6f
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
CraigMacomber Aug 16, 2024
760d8a3
Avoid exporting SchematizingSimpleTreeView from simple-tree just to u…
CraigMacomber Aug 16, 2024
ef5d943
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
CraigMacomber Aug 19, 2024
b1f764b
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
CraigMacomber Aug 19, 2024
0016bfa
specialize for object and map nodes
CraigMacomber Aug 19, 2024
c19fae1
Move event implementation, fix cycle.
CraigMacomber Aug 19, 2024
07b9c0b
Fix cyclic deps and add node kind based typing
CraigMacomber Aug 19, 2024
7f8ba44
Fix unhydrated events
CraigMacomber Aug 20, 2024
be29e65
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
CraigMacomber Aug 20, 2024
57b228e
Update chanegset
CraigMacomber Aug 20, 2024
0d19c01
Apply suggestions from code review
CraigMacomber Aug 21, 2024
e85c7cc
Better docs
CraigMacomber Aug 21, 2024
1b26fd2
More comment fixes
CraigMacomber Aug 21, 2024
5fbb0c7
Refer to property keys not view keys
CraigMacomber Sep 3, 2024
4d53f82
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
CraigMacomber Sep 3, 2024
79c1598
Update APi reports
CraigMacomber Sep 3, 2024
cf73e4d
Make new event API beta
CraigMacomber Sep 3, 2024
c9259dd
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
CraigMacomber Sep 3, 2024
b2eb096
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
CraigMacomber Sep 3, 2024
dc375e7
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
CraigMacomber Sep 3, 2024
3363b00
Add strongly typed keys
CraigMacomber Sep 4, 2024
138ebe6
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
CraigMacomber Sep 4, 2024
65b0b6a
document unstable
CraigMacomber Sep 5, 2024
33880b9
Merge branch 'main' into node-change
CraigMacomber Sep 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions .changeset/wet-hoops-drop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
---
"fluid-framework": minor
"@fluidframework/tree": minor
---


A `@beta` version of `nodeChanged` which includes the list of properties has been added.

```typescript
const factory = new SchemaFactory("example");
class Point2d extends factory.object("Point2d", {
x: factory.number,
y: factory.number,
}) {}

const point = new Point2d({ x: 0, y: 0 });

TreeBeta.on(point, "nodeChanged", (data) => {
const changed: ReadonlySet<"x" | "y"> = data.changedProperties;
if (changed.has("x")) {
// ...
}
});
```

The payload of the `nodeChanged` event emitted by SharedTree's `TreeBeta` includes a `changedProperties` property that indicates
which properties of the node changed.

For object nodes, the list of properties uses the property identifiers defined in the schema, and not the persisted
identifiers (or "stored keys") that can be provided through `FieldProps` when defining a schema.
See the documentation for `FieldProps` for more details about the distinction between "property keys" and "stored keys".

For map nodes, every key that was added, removed, or updated by a change to the tree is included in the list of properties.

For array nodes, the set of properties will always be undefined: there is currently no API to get details about changes to an array.

Object nodes revieve strongly types sets of changed keys, allowing compile time detection of incorrect keys:

```typescript
TreeBeta.on(point, "nodeChanged", (data) => {
// @ts-expect-error Strong typing for changed properties of object nodes detects incorrect keys:
if (data.changedProperties.has("z")) {
// ...
}
});
```

The existing stable "nodeChanged" event's callback now is given a parameter called `unstable` of type `unknown` which is used to indicate that additional data can be provided there.
This could break existing code using "nodeChanged" in a particularly fragile way.

```typescript
function f(optional?: number) {
// ...
}
Tree.on(point, "nodeChanged", f); // Bad
```

Code like this which is implicitly discarding an optional argument from the function used as the listener will be broken.
It can be fixed by using an inline lambda expression:

```typescript
function f(optional?: number) {
// ...
}
Tree.on(point, "nodeChanged", () => f()); // Safe
```
27 changes: 21 additions & 6 deletions packages/dds/tree/api-report/tree.alpha.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,11 @@ type NodeBuilderData<T extends TreeNodeSchema> = T extends TreeNodeSchema<string
// @public
type NodeBuilderDataUnsafe<T extends Unenforced<TreeNodeSchema>> = T extends TreeNodeSchema<string, NodeKind, unknown, infer TBuild> ? TBuild : never;

// @beta @sealed
export interface NodeChangedData<TNode extends TreeNode = TreeNode> {
readonly changedProperties?: ReadonlySet<TNode extends WithType<string, NodeKind.Object, infer TInfo> ? string & keyof TInfo : string>;
}

// @public
export type NodeFromSchema<T extends TreeNodeSchema> = T extends TreeNodeSchema<string, NodeKind, infer TNode> ? TNode : never;

Expand Down Expand Up @@ -392,15 +397,15 @@ export class SchemaFactory<out TScope extends string | undefined = string | unde
constructor(scope: TScope);
array<const T extends TreeNodeSchema | readonly TreeNodeSchema[]>(allowedTypes: T): TreeNodeSchema<ScopedSchemaName<TScope, `Array<${string}>`>, NodeKind.Array, TreeArrayNode<T> & WithType<ScopedSchemaName<TScope, `Array<${string}>`>, NodeKind.Array>, Iterable<InsertableTreeNodeFromImplicitAllowedTypes<T>>, true, T>;
array<const Name extends TName, const T extends ImplicitAllowedTypes>(name: Name, allowedTypes: T): TreeNodeSchemaClass<ScopedSchemaName<TScope, Name>, NodeKind.Array, TreeArrayNode<T> & WithType<ScopedSchemaName<TScope, Name>, NodeKind.Array>, Iterable<InsertableTreeNodeFromImplicitAllowedTypes<T>>, true, T>;
arrayRecursive<const Name extends TName, const T extends Unenforced<ImplicitAllowedTypes>>(name: Name, allowedTypes: T): TreeNodeSchemaClass<ScopedSchemaName<TScope, Name>, NodeKind.Array, TreeArrayNodeUnsafe<T> & WithType<ScopedSchemaName<TScope, Name>, NodeKind.Array>, {
arrayRecursive<const Name extends TName, const T extends Unenforced<ImplicitAllowedTypes>>(name: Name, allowedTypes: T): TreeNodeSchemaClass<ScopedSchemaName<TScope, Name>, NodeKind.Array, TreeArrayNodeUnsafe<T> & WithType<ScopedSchemaName<TScope, Name>, NodeKind.Array, unknown>, {
[Symbol.iterator](): Iterator<InsertableTreeNodeFromImplicitAllowedTypesUnsafe<T>>;
}, false, T>;
readonly boolean: TreeNodeSchema<"com.fluidframework.leaf.boolean", NodeKind.Leaf, boolean, boolean>;
readonly handle: TreeNodeSchema<"com.fluidframework.leaf.handle", NodeKind.Leaf, IFluidHandle<unknown>, IFluidHandle<unknown>>;
get identifier(): FieldSchema<FieldKind.Identifier, typeof SchemaFactory.string>;
map<const T extends TreeNodeSchema | readonly TreeNodeSchema[]>(allowedTypes: T): TreeNodeSchema<ScopedSchemaName<TScope, `Map<${string}>`>, NodeKind.Map, TreeMapNode<T> & WithType<ScopedSchemaName<TScope, `Map<${string}>`>, NodeKind.Map>, MapNodeInsertableData<T>, true, T>;
map<Name extends TName, const T extends ImplicitAllowedTypes>(name: Name, allowedTypes: T): TreeNodeSchemaClass<ScopedSchemaName<TScope, Name>, NodeKind.Map, TreeMapNode<T> & WithType<ScopedSchemaName<TScope, Name>, NodeKind.Map>, MapNodeInsertableData<T>, true, T>;
mapRecursive<Name extends TName, const T extends Unenforced<ImplicitAllowedTypes>>(name: Name, allowedTypes: T): TreeNodeSchemaClass<ScopedSchemaName<TScope, Name>, NodeKind.Map, TreeMapNodeUnsafe<T> & WithType<ScopedSchemaName<TScope, Name>, NodeKind.Map>, {
mapRecursive<Name extends TName, const T extends Unenforced<ImplicitAllowedTypes>>(name: Name, allowedTypes: T): TreeNodeSchemaClass<ScopedSchemaName<TScope, Name>, NodeKind.Map, TreeMapNodeUnsafe<T> & WithType<ScopedSchemaName<TScope, Name>, NodeKind.Map, unknown>, {
[Symbol.iterator](): Iterator<[
string,
InsertableTreeNodeFromImplicitAllowedTypesUnsafe<T>
Expand Down Expand Up @@ -472,12 +477,22 @@ interface TreeArrayNodeBase<out T, in TNew, in TMoveFrom> extends ReadonlyArray<
export interface TreeArrayNodeUnsafe<TAllowedTypes extends Unenforced<ImplicitAllowedTypes>> extends TreeArrayNodeBase<TreeNodeFromImplicitAllowedTypesUnsafe<TAllowedTypes>, InsertableTreeNodeFromImplicitAllowedTypesUnsafe<TAllowedTypes>, TreeArrayNode> {
}

// @beta @sealed
export const TreeBeta: {
readonly on: <K extends keyof TreeChangeEventsBeta<TNode>, TNode extends TreeNode>(node: TNode, eventName: K, listener: NoInfer<TreeChangeEventsBeta<TNode>[K]>) => () => void;
};

// @public @sealed
export interface TreeChangeEvents {
nodeChanged(): void;
nodeChanged(unstable?: unknown): void;
treeChanged(): void;
}

// @beta @sealed
export interface TreeChangeEventsBeta<TNode extends TreeNode = TreeNode> extends TreeChangeEvents {
nodeChanged: (data: NodeChangedData<TNode> & (TNode extends WithType<string, NodeKind.Map | NodeKind.Object> ? Required<Pick<NodeChangedData<TNode>, "changedProperties">> : unknown)) => void;
}

// @public
export type TreeFieldFromImplicitField<TSchema extends ImplicitFieldSchema = FieldSchema> = TSchema extends FieldSchema<infer Kind, infer Types> ? ApplyKind<TreeNodeFromImplicitAllowedTypes<Types>, Kind, false> : TSchema extends ImplicitAllowedTypes ? TreeNodeFromImplicitAllowedTypes<TSchema> : unknown;

Expand Down Expand Up @@ -555,7 +570,7 @@ interface TreeNodeSchemaNonClass<out Name extends string = string, out Kind exte
}

// @public
export type TreeObjectNode<T extends RestrictiveReadonlyRecord<string, ImplicitFieldSchema>, TypeName extends string = string> = TreeNode & ObjectFromSchemaRecord<T> & WithType<TypeName, NodeKind.Object>;
export type TreeObjectNode<T extends RestrictiveReadonlyRecord<string, ImplicitFieldSchema>, TypeName extends string = string> = TreeNode & ObjectFromSchemaRecord<T> & WithType<TypeName, NodeKind.Object, T>;

// @public
export type TreeObjectNodeUnsafe<T extends Unenforced<RestrictiveReadonlyRecord<string, ImplicitFieldSchema>>, TypeName extends string = string> = TreeNode & ObjectFromSchemaRecordUnsafe<T> & WithType<TypeName, NodeKind.Object>;
Expand Down Expand Up @@ -619,10 +634,10 @@ export type ValidateRecursiveSchema<T extends TreeNodeSchemaClass<string, NodeKi
}[T["kind"]]>> = true;

// @public @sealed
export interface WithType<out TName extends string = string, out TKind extends NodeKind = NodeKind> {
export interface WithType<out TName extends string = string, out TKind extends NodeKind = NodeKind, out TInfo = unknown> {
// @deprecated
get [typeNameSymbol](): TName;
get [typeSchemaSymbol](): TreeNodeSchemaClass<TName, TKind>;
get [typeSchemaSymbol](): TreeNodeSchemaClass<TName, TKind, unknown, never, boolean, TInfo>;
}

// (No @packageDocumentation comment for this package)
Expand Down
27 changes: 21 additions & 6 deletions packages/dds/tree/api-report/tree.beta.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,11 @@ type NodeBuilderData<T extends TreeNodeSchema> = T extends TreeNodeSchema<string
// @public
type NodeBuilderDataUnsafe<T extends Unenforced<TreeNodeSchema>> = T extends TreeNodeSchema<string, NodeKind, unknown, infer TBuild> ? TBuild : never;

// @beta @sealed
export interface NodeChangedData<TNode extends TreeNode = TreeNode> {
readonly changedProperties?: ReadonlySet<TNode extends WithType<string, NodeKind.Object, infer TInfo> ? string & keyof TInfo : string>;
}

// @public
export type NodeFromSchema<T extends TreeNodeSchema> = T extends TreeNodeSchema<string, NodeKind, infer TNode> ? TNode : never;

Expand Down Expand Up @@ -324,15 +329,15 @@ export class SchemaFactory<out TScope extends string | undefined = string | unde
constructor(scope: TScope);
array<const T extends TreeNodeSchema | readonly TreeNodeSchema[]>(allowedTypes: T): TreeNodeSchema<ScopedSchemaName<TScope, `Array<${string}>`>, NodeKind.Array, TreeArrayNode<T> & WithType<ScopedSchemaName<TScope, `Array<${string}>`>, NodeKind.Array>, Iterable<InsertableTreeNodeFromImplicitAllowedTypes<T>>, true, T>;
array<const Name extends TName, const T extends ImplicitAllowedTypes>(name: Name, allowedTypes: T): TreeNodeSchemaClass<ScopedSchemaName<TScope, Name>, NodeKind.Array, TreeArrayNode<T> & WithType<ScopedSchemaName<TScope, Name>, NodeKind.Array>, Iterable<InsertableTreeNodeFromImplicitAllowedTypes<T>>, true, T>;
arrayRecursive<const Name extends TName, const T extends Unenforced<ImplicitAllowedTypes>>(name: Name, allowedTypes: T): TreeNodeSchemaClass<ScopedSchemaName<TScope, Name>, NodeKind.Array, TreeArrayNodeUnsafe<T> & WithType<ScopedSchemaName<TScope, Name>, NodeKind.Array>, {
arrayRecursive<const Name extends TName, const T extends Unenforced<ImplicitAllowedTypes>>(name: Name, allowedTypes: T): TreeNodeSchemaClass<ScopedSchemaName<TScope, Name>, NodeKind.Array, TreeArrayNodeUnsafe<T> & WithType<ScopedSchemaName<TScope, Name>, NodeKind.Array, unknown>, {
[Symbol.iterator](): Iterator<InsertableTreeNodeFromImplicitAllowedTypesUnsafe<T>>;
}, false, T>;
readonly boolean: TreeNodeSchema<"com.fluidframework.leaf.boolean", NodeKind.Leaf, boolean, boolean>;
readonly handle: TreeNodeSchema<"com.fluidframework.leaf.handle", NodeKind.Leaf, IFluidHandle<unknown>, IFluidHandle<unknown>>;
get identifier(): FieldSchema<FieldKind.Identifier, typeof SchemaFactory.string>;
map<const T extends TreeNodeSchema | readonly TreeNodeSchema[]>(allowedTypes: T): TreeNodeSchema<ScopedSchemaName<TScope, `Map<${string}>`>, NodeKind.Map, TreeMapNode<T> & WithType<ScopedSchemaName<TScope, `Map<${string}>`>, NodeKind.Map>, MapNodeInsertableData<T>, true, T>;
map<Name extends TName, const T extends ImplicitAllowedTypes>(name: Name, allowedTypes: T): TreeNodeSchemaClass<ScopedSchemaName<TScope, Name>, NodeKind.Map, TreeMapNode<T> & WithType<ScopedSchemaName<TScope, Name>, NodeKind.Map>, MapNodeInsertableData<T>, true, T>;
mapRecursive<Name extends TName, const T extends Unenforced<ImplicitAllowedTypes>>(name: Name, allowedTypes: T): TreeNodeSchemaClass<ScopedSchemaName<TScope, Name>, NodeKind.Map, TreeMapNodeUnsafe<T> & WithType<ScopedSchemaName<TScope, Name>, NodeKind.Map>, {
mapRecursive<Name extends TName, const T extends Unenforced<ImplicitAllowedTypes>>(name: Name, allowedTypes: T): TreeNodeSchemaClass<ScopedSchemaName<TScope, Name>, NodeKind.Map, TreeMapNodeUnsafe<T> & WithType<ScopedSchemaName<TScope, Name>, NodeKind.Map, unknown>, {
[Symbol.iterator](): Iterator<[
string,
InsertableTreeNodeFromImplicitAllowedTypesUnsafe<T>
Expand Down Expand Up @@ -401,12 +406,22 @@ interface TreeArrayNodeBase<out T, in TNew, in TMoveFrom> extends ReadonlyArray<
export interface TreeArrayNodeUnsafe<TAllowedTypes extends Unenforced<ImplicitAllowedTypes>> extends TreeArrayNodeBase<TreeNodeFromImplicitAllowedTypesUnsafe<TAllowedTypes>, InsertableTreeNodeFromImplicitAllowedTypesUnsafe<TAllowedTypes>, TreeArrayNode> {
}

// @beta @sealed
export const TreeBeta: {
readonly on: <K extends keyof TreeChangeEventsBeta<TNode>, TNode extends TreeNode>(node: TNode, eventName: K, listener: NoInfer<TreeChangeEventsBeta<TNode>[K]>) => () => void;
};

// @public @sealed
export interface TreeChangeEvents {
nodeChanged(): void;
nodeChanged(unstable?: unknown): void;
Josmithr marked this conversation as resolved.
Show resolved Hide resolved
treeChanged(): void;
}

// @beta @sealed
export interface TreeChangeEventsBeta<TNode extends TreeNode = TreeNode> extends TreeChangeEvents {
nodeChanged: (data: NodeChangedData<TNode> & (TNode extends WithType<string, NodeKind.Map | NodeKind.Object> ? Required<Pick<NodeChangedData<TNode>, "changedProperties">> : unknown)) => void;
}

// @public
export type TreeFieldFromImplicitField<TSchema extends ImplicitFieldSchema = FieldSchema> = TSchema extends FieldSchema<infer Kind, infer Types> ? ApplyKind<TreeNodeFromImplicitAllowedTypes<Types>, Kind, false> : TSchema extends ImplicitAllowedTypes ? TreeNodeFromImplicitAllowedTypes<TSchema> : unknown;

Expand Down Expand Up @@ -484,7 +499,7 @@ interface TreeNodeSchemaNonClass<out Name extends string = string, out Kind exte
}

// @public
export type TreeObjectNode<T extends RestrictiveReadonlyRecord<string, ImplicitFieldSchema>, TypeName extends string = string> = TreeNode & ObjectFromSchemaRecord<T> & WithType<TypeName, NodeKind.Object>;
export type TreeObjectNode<T extends RestrictiveReadonlyRecord<string, ImplicitFieldSchema>, TypeName extends string = string> = TreeNode & ObjectFromSchemaRecord<T> & WithType<TypeName, NodeKind.Object, T>;

// @public
export type TreeObjectNodeUnsafe<T extends Unenforced<RestrictiveReadonlyRecord<string, ImplicitFieldSchema>>, TypeName extends string = string> = TreeNode & ObjectFromSchemaRecordUnsafe<T> & WithType<TypeName, NodeKind.Object>;
Expand Down Expand Up @@ -548,10 +563,10 @@ export type ValidateRecursiveSchema<T extends TreeNodeSchemaClass<string, NodeKi
}[T["kind"]]>> = true;

// @public @sealed
export interface WithType<out TName extends string = string, out TKind extends NodeKind = NodeKind> {
export interface WithType<out TName extends string = string, out TKind extends NodeKind = NodeKind, out TInfo = unknown> {
// @deprecated
get [typeNameSymbol](): TName;
get [typeSchemaSymbol](): TreeNodeSchemaClass<TName, TKind>;
get [typeSchemaSymbol](): TreeNodeSchemaClass<TName, TKind, unknown, never, boolean, TInfo>;
}

// (No @packageDocumentation comment for this package)
Expand Down
12 changes: 6 additions & 6 deletions packages/dds/tree/api-report/tree.public.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -324,15 +324,15 @@ export class SchemaFactory<out TScope extends string | undefined = string | unde
constructor(scope: TScope);
array<const T extends TreeNodeSchema | readonly TreeNodeSchema[]>(allowedTypes: T): TreeNodeSchema<ScopedSchemaName<TScope, `Array<${string}>`>, NodeKind.Array, TreeArrayNode<T> & WithType<ScopedSchemaName<TScope, `Array<${string}>`>, NodeKind.Array>, Iterable<InsertableTreeNodeFromImplicitAllowedTypes<T>>, true, T>;
array<const Name extends TName, const T extends ImplicitAllowedTypes>(name: Name, allowedTypes: T): TreeNodeSchemaClass<ScopedSchemaName<TScope, Name>, NodeKind.Array, TreeArrayNode<T> & WithType<ScopedSchemaName<TScope, Name>, NodeKind.Array>, Iterable<InsertableTreeNodeFromImplicitAllowedTypes<T>>, true, T>;
arrayRecursive<const Name extends TName, const T extends Unenforced<ImplicitAllowedTypes>>(name: Name, allowedTypes: T): TreeNodeSchemaClass<ScopedSchemaName<TScope, Name>, NodeKind.Array, TreeArrayNodeUnsafe<T> & WithType<ScopedSchemaName<TScope, Name>, NodeKind.Array>, {
arrayRecursive<const Name extends TName, const T extends Unenforced<ImplicitAllowedTypes>>(name: Name, allowedTypes: T): TreeNodeSchemaClass<ScopedSchemaName<TScope, Name>, NodeKind.Array, TreeArrayNodeUnsafe<T> & WithType<ScopedSchemaName<TScope, Name>, NodeKind.Array, unknown>, {
[Symbol.iterator](): Iterator<InsertableTreeNodeFromImplicitAllowedTypesUnsafe<T>>;
}, false, T>;
readonly boolean: TreeNodeSchema<"com.fluidframework.leaf.boolean", NodeKind.Leaf, boolean, boolean>;
readonly handle: TreeNodeSchema<"com.fluidframework.leaf.handle", NodeKind.Leaf, IFluidHandle<unknown>, IFluidHandle<unknown>>;
get identifier(): FieldSchema<FieldKind.Identifier, typeof SchemaFactory.string>;
map<const T extends TreeNodeSchema | readonly TreeNodeSchema[]>(allowedTypes: T): TreeNodeSchema<ScopedSchemaName<TScope, `Map<${string}>`>, NodeKind.Map, TreeMapNode<T> & WithType<ScopedSchemaName<TScope, `Map<${string}>`>, NodeKind.Map>, MapNodeInsertableData<T>, true, T>;
map<Name extends TName, const T extends ImplicitAllowedTypes>(name: Name, allowedTypes: T): TreeNodeSchemaClass<ScopedSchemaName<TScope, Name>, NodeKind.Map, TreeMapNode<T> & WithType<ScopedSchemaName<TScope, Name>, NodeKind.Map>, MapNodeInsertableData<T>, true, T>;
mapRecursive<Name extends TName, const T extends Unenforced<ImplicitAllowedTypes>>(name: Name, allowedTypes: T): TreeNodeSchemaClass<ScopedSchemaName<TScope, Name>, NodeKind.Map, TreeMapNodeUnsafe<T> & WithType<ScopedSchemaName<TScope, Name>, NodeKind.Map>, {
mapRecursive<Name extends TName, const T extends Unenforced<ImplicitAllowedTypes>>(name: Name, allowedTypes: T): TreeNodeSchemaClass<ScopedSchemaName<TScope, Name>, NodeKind.Map, TreeMapNodeUnsafe<T> & WithType<ScopedSchemaName<TScope, Name>, NodeKind.Map, unknown>, {
[Symbol.iterator](): Iterator<[
string,
InsertableTreeNodeFromImplicitAllowedTypesUnsafe<T>
Expand Down Expand Up @@ -403,7 +403,7 @@ export interface TreeArrayNodeUnsafe<TAllowedTypes extends Unenforced<ImplicitAl

// @public @sealed
export interface TreeChangeEvents {
nodeChanged(): void;
nodeChanged(unstable?: unknown): void;
treeChanged(): void;
}

Expand Down Expand Up @@ -484,7 +484,7 @@ interface TreeNodeSchemaNonClass<out Name extends string = string, out Kind exte
}

// @public
export type TreeObjectNode<T extends RestrictiveReadonlyRecord<string, ImplicitFieldSchema>, TypeName extends string = string> = TreeNode & ObjectFromSchemaRecord<T> & WithType<TypeName, NodeKind.Object>;
export type TreeObjectNode<T extends RestrictiveReadonlyRecord<string, ImplicitFieldSchema>, TypeName extends string = string> = TreeNode & ObjectFromSchemaRecord<T> & WithType<TypeName, NodeKind.Object, T>;

// @public
export type TreeObjectNodeUnsafe<T extends Unenforced<RestrictiveReadonlyRecord<string, ImplicitFieldSchema>>, TypeName extends string = string> = TreeNode & ObjectFromSchemaRecordUnsafe<T> & WithType<TypeName, NodeKind.Object>;
Expand Down Expand Up @@ -548,10 +548,10 @@ export type ValidateRecursiveSchema<T extends TreeNodeSchemaClass<string, NodeKi
}[T["kind"]]>> = true;

// @public @sealed
export interface WithType<out TName extends string = string, out TKind extends NodeKind = NodeKind> {
export interface WithType<out TName extends string = string, out TKind extends NodeKind = NodeKind, out TInfo = unknown> {
// @deprecated
get [typeNameSymbol](): TName;
get [typeSchemaSymbol](): TreeNodeSchemaClass<TName, TKind>;
get [typeSchemaSymbol](): TreeNodeSchemaClass<TName, TKind, unknown, never, boolean, TInfo>;
}

// (No @packageDocumentation comment for this package)
Expand Down
Loading
Loading