Skip to main content

SchemaFactory Class

Creates various types of schema for TreeNodes.

Signature

/** @sealed */
export declare class SchemaFactory<out TScope extends string | undefined = string | undefined, TName extends number | string = string>

Type Parameters

Parameter Constraint Default Description
TScope string | undefined string | undefined Scope added as a prefix to the name of every schema produced by this factory.
TName number | string string Type of names used to identify each schema produced in this factory. Typically this is just string but it is also possible to use string or number based enums if you prefer to identify your types that way.

Remarks

For details related to inputting data constrained by schema (including via assignment), and how non-exact schema types are handled in general refer to Input. For information about recursive schema support, see methods postfixed with "recursive" and ValidateRecursiveSchema. To apply schema defined with this factory to a tree, see viewWith(config) and TreeViewConfiguration.

All schema produced by this factory get a unique identifier by combining the scope with the schema's Name. The Name part may be explicitly provided as a parameter, or inferred as a structural combination of the provided types. The APIs which use this second approach, structural naming, also deduplicate all equivalent calls. Therefor two calls to array(allowedTypes) with the same allowedTypes will return the same TreeNodeSchema instance. On the other hand, two calls to array(name, allowedTypes) will always return different TreeNodeSchema instances and it is an error to use both in the same tree (since their identifiers are not unique).

Note: POJO stands for Plain Old JavaScript Object. This means an object that works like a {} style object literal. In this case it means the prototype is Object.prototype and acts like a set of key value pairs (data, not methods). The usage below generalizes this to include array and map like objects as well.

There are two ways to use these APIs:

Customizable Approach:

  1. Declaration: class X extends schemaFactory.object("x", {}) {}

  2. Allows adding "local" (non-persisted) members: Yes. Members (including methods) can be added to the class.

  3. Prototype: The user-defined class.

  4. Structurally named Schema: Not Supported.

  5. Explicitly named Objects: Supported.

  6. Explicitly named Maps and Arrays: Supported: Both declaration approaches can be used.

  7. Node.js assert.deepEqual: Compares like class instances: equal to other nodes of the same type with the same content, including custom local fields.

  8. IntelliSense: Shows and links to user-defined class by name: X.

  9. Recursion: Supported with special declaration patterns.

POJO Emulation Approach:

  1. Declaration: const X = schemaFactory.object("x", {}); type X = NodeFromSchema<typeof X>;

  2. Allows adding "local" (non-persisted) members: No. Attempting to set non-field members will result in an error.

  3. Prototype: Object.prototype, Map.prototype, or Array.prototype depending on node kind.

  4. Structurally named Schema: Supported.

  5. Explicitly named Objects: Supported.

  6. Explicitly named Maps and Arrays: Not Supported.

  7. Node.js assert.deepEqual: Compares like plain objects: equal to plain JavaScript objects with the same fields, and other nodes with the same fields, even if the types are different.

  8. IntelliSense: Shows internal type generation logic: object & TreeNode & ObjectFromSchemaRecord<{}> & WithType<"test.x">.

  9. Recursion: Unsupported: Generated .d.ts files replace recursive references with any, breaking the use of recursive schema across compilation boundaries.

Note that while "POJO Emulation" nodes act a lot like POJO objects, they are not true POJO objects:

  • Adding new arbitrary fields will error, as well some cases of invalid edits.

  • They are implemented using proxies.

  • They have state that is not exposed via enumerable own properties, including a TreeNodeSchema. This makes libraries like node.js assert.deepEqual fail to detect differences in type.

  • Assigning members has side effects (in this case editing the persisted/shared tree).

  • Not all operations implied by the prototype will work correctly: stick to the APIs explicitly declared in the TypeScript types.

Constructors

Constructor Description
(constructor)(scope) Construct a SchemaFactory with a given scope.

Properties

Property Modifiers Type Description
boolean readonly TreeNodeSchemaNonClass<"com.fluidframework.leaf.boolean", NodeKind.Leaf, boolean, boolean, true, unknown, never> TreeNodeSchema for holding a boolean.
handle readonly TreeNodeSchemaNonClass<"com.fluidframework.leaf.handle", NodeKind.Leaf, _dummyImport<unknown>, _dummyImport<unknown>, true, unknown, never> TreeNodeSchema for holding an IFluidHandle.
identifier readonly FieldSchema<FieldKind.Identifier, typeof this.string> A special field which holds a unique identifier for an object node.
null readonly TreeNodeSchemaNonClass<"com.fluidframework.leaf.null", NodeKind.Leaf, null, null, true, unknown, never> TreeNodeSchema for JavaScript null.
number readonly TreeNodeSchemaNonClass<"com.fluidframework.leaf.number", NodeKind.Leaf, number, number, true, unknown, never> TreeNodeSchema for holding a JavaScript number.
scope readonly TScope Prefix appended to the identifiers of all TreeNodeSchema produced by this builder.
string readonly TreeNodeSchemaNonClass<"com.fluidframework.leaf.string", NodeKind.Leaf, string, string, true, unknown, never> TreeNodeSchema for holding a JavaScript string.

Methods

Method Return Type Description
array(allowedTypes) TreeNodeSchemaNonClass<ScopedSchemaName<TScope, `Array<${string}>`>, NodeKind.Array, TreeArrayNode<T> & WithType<ScopedSchemaName<TScope, `Array<${string}>`>, NodeKind.Array>, Iterable<InsertableTreeNodeFromImplicitAllowedTypes<T>>, true, T, undefined> Define a structurally typed TreeNodeSchema for a TreeArrayNode.
array(name, allowedTypes) TreeNodeSchemaClass<ScopedSchemaName<TScope, Name>, NodeKind.Array, TreeArrayNode<T> & WithType<ScopedSchemaName<TScope, Name>, NodeKind.Array>, Iterable<InsertableTreeNodeFromImplicitAllowedTypes<T>>, true, T, undefined> Define (and add to this library) a TreeNodeSchemaClass for a TreeArrayNode.
arrayRecursive(name, allowedTypes) TreeNodeSchemaClass<ScopedSchemaName<TScope, Name>, NodeKind.Array, TreeArrayNodeUnsafe<T> & WithType<ScopedSchemaName<TScope, Name>, NodeKind.Array, unknown>, { [Symbol.iterator](): Iterator<InsertableTreeNodeFromImplicitAllowedTypesUnsafe<T>>; }, false, T, undefined> SchemaFactory.array except tweaked to work better for recursive types. Use with ValidateRecursiveSchema for improved type safety.
map(allowedTypes) TreeNodeSchemaNonClass<ScopedSchemaName<TScope, `Map<${string}>`>, NodeKind.Map, TreeMapNode<T> & WithType<ScopedSchemaName<TScope, `Map<${string}>`>, NodeKind.Map>, MapNodeInsertableData<T>, true, T, undefined> Define a structurally typed TreeNodeSchema for a TreeMapNode.
map(name, allowedTypes) TreeNodeSchemaClass<ScopedSchemaName<TScope, Name>, NodeKind.Map, TreeMapNode<T> & WithType<ScopedSchemaName<TScope, Name>, NodeKind.Map>, MapNodeInsertableData<T>, true, T, undefined> Define a TreeNodeSchema for a TreeMapNode.
mapRecursive(name, allowedTypes) TreeNodeSchemaClass<ScopedSchemaName<TScope, Name>, NodeKind.Map, TreeMapNodeUnsafe<T> & WithType<ScopedSchemaName<TScope, Name>, NodeKind.Map, unknown>, { [Symbol.iterator](): Iterator<[ string, InsertableTreeNodeFromImplicitAllowedTypesUnsafe<T> ]>; } | { readonly [x: string]: InsertableTreeNodeFromImplicitAllowedTypesUnsafe<T>; }, false, T, undefined> SchemaFactory.map except tweaked to work better for recursive types. Use with ValidateRecursiveSchema for improved type safety.
object(name, fields) TreeNodeSchemaClass<ScopedSchemaName<TScope, Name>, NodeKind.Object, TreeObjectNode<T, ScopedSchemaName<TScope, Name>>, object & InsertableObjectFromSchemaRecord<T>, true, T> Define a TreeNodeSchemaClass for a TreeObjectNode.
objectRecursive(name, t) TreeNodeSchemaClass<ScopedSchemaName<TScope, Name>, NodeKind.Object, TreeObjectNodeUnsafe<T, ScopedSchemaName<TScope, Name>>, object & { readonly [Property in keyof T as FieldHasDefaultUnsafe<T[Property]> extends false ? Property : never]: InsertableTreeFieldFromImplicitFieldUnsafe<T[Property], import("../../util/typeUtils.js").UnionToIntersection<T[Property]>>; } & { readonly [Property_1 in keyof T as FieldHasDefaultUnsafe<T[Property_1]> extends true ? Property_1 : never]?: InsertableTreeFieldFromImplicitFieldUnsafe<T[Property_1], import("../../util/typeUtils.js").UnionToIntersection<T[Property_1]>> | undefined; }, false, T> object(name, fields) except tweaked to work better for recursive types. Use with ValidateRecursiveSchema for improved type safety.
optional(t, props) FieldSchema<FieldKind.Optional, T, TCustomMetadata> Make a field optional instead of the default, which is required.
optionalRecursive(t, props) FieldSchemaUnsafe<FieldKind.Optional, T> optional(t, props) except tweaked to work better for recursive types. Use with ValidateRecursiveSchema for improved type safety.
required(t, props) FieldSchema<FieldKind.Required, T, TCustomMetadata> Make a field explicitly required.
requiredRecursive(t, props) FieldSchemaUnsafe<FieldKind.Required, T> required(t, props) except tweaked to work better for recursive types. Use with ValidateRecursiveSchema for improved type safety.

Constructor Details

(constructor)

Construct a SchemaFactory with a given scope.

Signature

constructor(
scope: TScope);

Remarks

There are no restrictions on mixing schema from different schema factories. Typically each library will create one or more SchemaFactories and use them to define its schema.

Parameters

Parameter Type Description
scope TScope

Property Details

boolean

TreeNodeSchema for holding a boolean.

Signature

readonly boolean: TreeNodeSchemaNonClass<"com.fluidframework.leaf.boolean", NodeKind.Leaf, boolean, boolean, true, unknown, never>;

Type: TreeNodeSchemaNonClass<"com.fluidframework.leaf.boolean", NodeKind.Leaf, boolean, boolean, true, unknown, never>

handle

TreeNodeSchema for holding an IFluidHandle.

Signature

readonly handle: TreeNodeSchemaNonClass<"com.fluidframework.leaf.handle", NodeKind.Leaf, _dummyImport<unknown>, _dummyImport<unknown>, true, unknown, never>;

Type: TreeNodeSchemaNonClass<"com.fluidframework.leaf.handle", NodeKind.Leaf, _dummyImport<unknown>, _dummyImport<unknown>, true, unknown, never>

identifier

A special field which holds a unique identifier for an object node.

Signature

get identifier(): FieldSchema<FieldKind.Identifier, typeof this.string>;

Type: FieldSchema<FieldKind.Identifier, typeof this.string>

Remarks

The value of this field, a "node identifier", uniquely identifies a node among all other nodes in the tree. Node identifiers are strings, and can therefore be used as lookup keys in maps or written to a database. When the node is constructed, the identifier field does not need to be populated. The SharedTree will provide an identifier for the node automatically. An identifier provided automatically by the SharedTree has the following properties: - It is a UUID. - It is compressed to a space-efficient representation when stored in the document. - A compressed form of the identifier can be accessed at runtime via the Tree.shortId() API. - It will error if read (and will not be present in the object's iterable properties) before the node has been inserted into the tree.

However, a user may alternatively supply their own string as the identifier if desired (for example, if importing identifiers from another system). In that case, it is up to the user to ensure that the identifier is unique within the current tree - no other node should have the same identifier at the same time. If the identifier is not unique, it may be read, but may cause libraries or features which operate over node identifiers to misbehave. User-supplied identifiers may be read immediately, even before insertion into the tree.

A node may have more than one identifier field (though note that this precludes the use of the Tree.shortId() API).

null

TreeNodeSchema for JavaScript null.

Signature

readonly null: TreeNodeSchemaNonClass<"com.fluidframework.leaf.null", NodeKind.Leaf, null, null, true, unknown, never>;

Type: TreeNodeSchemaNonClass<"com.fluidframework.leaf.null", NodeKind.Leaf, null, null, true, unknown, never>

Remarks

There are good [reasons to avoid using null](https://www.npmjs.com/package/%40rushstack/eslint-plugin\#rushstackno-new-null) in JavaScript, however sometimes it is desired. This TreeNodeSchema node provides the option to include nulls in trees when desired. Unless directly inter-operating with existing data using null, consider other approaches, like wrapping the value in an optional field, or using a more specifically named empty object node.

number

TreeNodeSchema for holding a JavaScript number.

Signature

readonly number: TreeNodeSchemaNonClass<"com.fluidframework.leaf.number", NodeKind.Leaf, number, number, true, unknown, never>;

Type: TreeNodeSchemaNonClass<"com.fluidframework.leaf.number", NodeKind.Leaf, number, number, true, unknown, never>

Remarks

The number is a [double-precision 64-bit binary format IEEE 754](https://en.wikipedia.org/wiki/Double-precision\_floating-point\_format) value, however there are some exceptions: - NaN, and the infinities are converted to null (and may therefore only be used where null is allowed by the schema). - -0 may be converted to 0 in some cases.

These limitations match the limitations of JSON.

scope

Prefix appended to the identifiers of all TreeNodeSchema produced by this builder.

Signature

readonly scope: TScope;

Type: TScope

Remarks

Generally each independently developed library (possibly a package, but could also be part of a package or multiple packages developed together) should get its own unique scope. Then each schema in the library get a name which is unique within the library. The scope and name are joined (with a period) to form the schema identifier. Following this pattern allows a single application to depend on multiple libraries which define their own schema, and use them together in a single tree without risk of collisions. If a library logically contains sub-libraries with their own schema, they can be given a scope nested inside the parent scope, such as "ParentScope.ChildScope".

To avoid collisions between the scopes of libraries it is recommended that the libraries use Reverse domain name notation or a UUIDv4 for their scope. If this pattern is followed, application can safely use third party libraries without risk of the schema in them colliding.

You may opt out of using a scope by passing undefined, but note that this increases the risk of collisions.

Usage

Example 1

Fluid Framework follows this pattern, placing the schema for the built in leaf types in the com.fluidframework.leaf scope. If Fluid Framework publishes more schema in the future, they would be under some other com.fluidframework scope. This ensures that any schema defined by any other library will not conflict with Fluid Framework's schema as long as the library uses the recommended patterns for how to scope its schema..

Example 2

A library could generate a random UUIDv4, like 242c4397-49ed-47e6-8dd0-d5c3bc31778b and use that as the scope. Note: do not use this UUID: a new one must be randomly generated when needed to ensure collision resistance.

const factory = new SchemaFactory("242c4397-49ed-47e6-8dd0-d5c3bc31778b");

string

TreeNodeSchema for holding a JavaScript string.

Signature

readonly string: TreeNodeSchemaNonClass<"com.fluidframework.leaf.string", NodeKind.Leaf, string, string, true, unknown, never>;

Type: TreeNodeSchemaNonClass<"com.fluidframework.leaf.string", NodeKind.Leaf, string, string, true, unknown, never>

Remarks

Strings containing unpaired UTF-16 surrogate pair code units may not be handled correctly.

These limitations come from the use of UTF-8 encoding of the strings, which requires them to be valid unicode. JavaScript does not make this requirement for its strings so not all possible JavaScript strings are supported.

Method Details

array

Define a structurally typed TreeNodeSchema for a TreeArrayNode.

Signature

array<const T extends TreeNodeSchema | readonly TreeNodeSchema[]>(allowedTypes: T): TreeNodeSchemaNonClass<ScopedSchemaName<TScope, `Array<${string}>`>, NodeKind.Array, TreeArrayNode<T> & WithType<ScopedSchemaName<TScope, `Array<${string}>`>, NodeKind.Array>, Iterable<InsertableTreeNodeFromImplicitAllowedTypes<T>>, true, T, undefined>;
Type Parameters
Parameter Constraint Description
T TreeNodeSchema | readonly TreeNodeSchema[]

Remarks

The identifier for this Array is defined as a function of the provided types. It is still scoped to this SchemaFactory, but multiple calls with the same arguments will return the same schema object, providing somewhat structural typing. This does not support recursive types.

If using these structurally named arrays, other types in this schema builder should avoid names of the form Array<${string}>.

Example

The returned schema should be used as a schema directly:

const MyArray = factory.array(factory.number);
type MyArray = NodeFromSchema<typeof MyArray>;

Or inline:

factory.object("Foo", {myArray: factory.array(factory.number)});

Parameters

Parameter Type Description
allowedTypes T

Returns

Return type: TreeNodeSchemaNonClass<ScopedSchemaName<TScope, `Array<${string}>`>, NodeKind.Array, TreeArrayNode<T> & WithType<ScopedSchemaName<TScope, `Array<${string}>`>, NodeKind.Array>, Iterable<InsertableTreeNodeFromImplicitAllowedTypes<T>>, true, T, undefined>

array

Define (and add to this library) a TreeNodeSchemaClass for a TreeArrayNode.

Signature

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, undefined>;
Type Parameters
Parameter Constraint Description
Name TName
T ImplicitAllowedTypes

Example

class NamedArray extends factory.array("name", factory.number) {}

Parameters

Parameter Type Description
name Name Unique identifier for this schema within this factory's scope.
allowedTypes T

Returns

Return type: TreeNodeSchemaClass<ScopedSchemaName<TScope, Name>, NodeKind.Array, TreeArrayNode<T> & WithType<ScopedSchemaName<TScope, Name>, NodeKind.Array>, Iterable<InsertableTreeNodeFromImplicitAllowedTypes<T>>, true, T, undefined>

arrayRecursive

SchemaFactory.array except tweaked to work better for recursive types. Use with ValidateRecursiveSchema for improved type safety.

Signature

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, undefined>;
Type Parameters
Parameter Constraint Description
Name TName
T Unenforced<ImplicitAllowedTypes>

Remarks

This version of SchemaFactory.array uses the same workarounds as objectRecursive(name, t). See ValidateRecursiveSchema for additional information about using recursive schema.

Parameters

Parameter Type Description
name Name
allowedTypes T

Returns

Return type: TreeNodeSchemaClass<ScopedSchemaName<TScope, Name>, NodeKind.Array, TreeArrayNodeUnsafe<T> & WithType<ScopedSchemaName<TScope, Name>, NodeKind.Array, unknown>, { [Symbol.iterator](): Iterator<InsertableTreeNodeFromImplicitAllowedTypesUnsafe<T>>; }, false, T, undefined>

map

Define a structurally typed TreeNodeSchema for a TreeMapNode.

Signature

map<const T extends TreeNodeSchema | readonly TreeNodeSchema[]>(allowedTypes: T): TreeNodeSchemaNonClass<ScopedSchemaName<TScope, `Map<${string}>`>, NodeKind.Map, TreeMapNode<T> & WithType<ScopedSchemaName<TScope, `Map<${string}>`>, NodeKind.Map>, MapNodeInsertableData<T>, true, T, undefined>;
Type Parameters
Parameter Constraint Description
T TreeNodeSchema | readonly TreeNodeSchema[]

Remarks

The unique identifier for this Map is defined as a function of the provided types. It is still scoped to this SchemaBuilder, but multiple calls with the same arguments will return the same schema object, providing somewhat structural typing. This does not support recursive types.

If using these structurally named maps, other types in this schema builder should avoid names of the form Map<${string}>.

Example

The returned schema should be used as a schema directly:

const MyMap = factory.map(factory.number);
type MyMap = NodeFromSchema<typeof MyMap>;

Or inline:

factory.object("Foo", {myMap: factory.map(factory.number)});

Parameters

Parameter Type Description
allowedTypes T

Returns

Return type: TreeNodeSchemaNonClass<ScopedSchemaName<TScope, `Map<${string}>`>, NodeKind.Map, TreeMapNode<T> & WithType<ScopedSchemaName<TScope, `Map<${string}>`>, NodeKind.Map>, MapNodeInsertableData<T>, true, T, undefined>

map

Define a TreeNodeSchema for a TreeMapNode.

Signature

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, undefined>;
Type Parameters
Parameter Constraint Description
Name TName
T ImplicitAllowedTypes

Example

class NamedMap extends factory.map("name", factory.number) {}

Parameters

Parameter Type Description
name Name Unique identifier for this schema within this factory's scope.
allowedTypes T

Returns

Return type: TreeNodeSchemaClass<ScopedSchemaName<TScope, Name>, NodeKind.Map, TreeMapNode<T> & WithType<ScopedSchemaName<TScope, Name>, NodeKind.Map>, MapNodeInsertableData<T>, true, T, undefined>

mapRecursive

SchemaFactory.map except tweaked to work better for recursive types. Use with ValidateRecursiveSchema for improved type safety.

Signature

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>
]>;
} | {
readonly [x: string]: InsertableTreeNodeFromImplicitAllowedTypesUnsafe<T>;
}, false, T, undefined>;
Type Parameters
Parameter Constraint Description
Name TName
T Unenforced<ImplicitAllowedTypes>

Remarks

This version of SchemaFactory.map uses the same workarounds as objectRecursive(name, t). See ValidateRecursiveSchema for additional information about using recursive schema.

Parameters

Parameter Type Description
name Name
allowedTypes T

Returns

Return type: TreeNodeSchemaClass<ScopedSchemaName<TScope, Name>, NodeKind.Map, TreeMapNodeUnsafe<T> & WithType<ScopedSchemaName<TScope, Name>, NodeKind.Map, unknown>, { [Symbol.iterator](): Iterator<[ string, InsertableTreeNodeFromImplicitAllowedTypesUnsafe<T> ]>; } | { readonly [x: string]: InsertableTreeNodeFromImplicitAllowedTypesUnsafe<T>; }, false, T, undefined>

object

Define a TreeNodeSchemaClass for a TreeObjectNode.

Signature

object<const Name extends TName, const T extends RestrictiveStringRecord<ImplicitFieldSchema>>(name: Name, fields: T): TreeNodeSchemaClass<ScopedSchemaName<TScope, Name>, NodeKind.Object, TreeObjectNode<T, ScopedSchemaName<TScope, Name>>, object & InsertableObjectFromSchemaRecord<T>, true, T>;
Type Parameters
Parameter Constraint Description
Name TName
T RestrictiveStringRecord<ImplicitFieldSchema>

Parameters

Parameter Type Description
name Name Unique identifier for this schema within this factory's scope.
fields T Schema for fields of the object node's schema. Defines what children can be placed under each key.

Returns

Return type: TreeNodeSchemaClass<ScopedSchemaName<TScope, Name>, NodeKind.Object, TreeObjectNode<T, ScopedSchemaName<TScope, Name>>, object & InsertableObjectFromSchemaRecord<T>, true, T>

objectRecursive

object(name, fields) except tweaked to work better for recursive types. Use with ValidateRecursiveSchema for improved type safety.

Signature

objectRecursive<const Name extends TName, const T extends Unenforced<RestrictiveStringRecord<ImplicitFieldSchema>>>(name: Name, t: T): TreeNodeSchemaClass<ScopedSchemaName<TScope, Name>, NodeKind.Object, TreeObjectNodeUnsafe<T, ScopedSchemaName<TScope, Name>>, object & { readonly [Property in keyof T as FieldHasDefaultUnsafe<T[Property]> extends false ? Property : never]: InsertableTreeFieldFromImplicitFieldUnsafe<T[Property], import("../../util/typeUtils.js").UnionToIntersection<T[Property]>>; } & { readonly [Property_1 in keyof T as FieldHasDefaultUnsafe<T[Property_1]> extends true ? Property_1 : never]?: InsertableTreeFieldFromImplicitFieldUnsafe<T[Property_1], import("../../util/typeUtils.js").UnionToIntersection<T[Property_1]>> | undefined; }, false, T>;
Type Parameters
Parameter Constraint Description
Name TName
T Unenforced<RestrictiveStringRecord<ImplicitFieldSchema>>

Remarks

This version of object(name, fields) has fewer type constraints to work around TypeScript limitations, see Unenforced. See ValidateRecursiveSchema for additional information about using recursive schema.

Additionally ImplicitlyConstructable is disabled (forcing use of constructor) to avoid error TS2589: Type instantiation is excessively deep and possibly infinite. which otherwise gets reported at sometimes incorrect source locations that vary based on incremental builds.

Parameters

Parameter Type Description
name Name
t T

Returns

Return type: TreeNodeSchemaClass<ScopedSchemaName<TScope, Name>, NodeKind.Object, TreeObjectNodeUnsafe<T, ScopedSchemaName<TScope, Name>>, object & { readonly [Property in keyof T as FieldHasDefaultUnsafe<T[Property]> extends false ? Property : never]: InsertableTreeFieldFromImplicitFieldUnsafe<T[Property], import("../../util/typeUtils.js").UnionToIntersection<T[Property]>>; } & { readonly [Property_1 in keyof T as FieldHasDefaultUnsafe<T[Property_1]> extends true ? Property_1 : never]?: InsertableTreeFieldFromImplicitFieldUnsafe<T[Property_1], import("../../util/typeUtils.js").UnionToIntersection<T[Property_1]>> | undefined; }, false, T>

optional

Make a field optional instead of the default, which is required.

Signature

optional<const T extends ImplicitAllowedTypes, const TCustomMetadata = unknown>(t: T, props?: Omit<FieldProps<TCustomMetadata>, "defaultProvider">): FieldSchema<FieldKind.Optional, T, TCustomMetadata>;
Type Parameters
Parameter Constraint Default Description
T ImplicitAllowedTypes
TCustomMetadata unknown Custom metadata properties to associate with the field. See custom.

Parameters

Parameter Modifiers Type Description
t T The types allowed under the field.
props optional Omit<FieldProps<TCustomMetadata>, "defaultProvider"> Optional properties to associate with the field.

Returns

Return type: FieldSchema<FieldKind.Optional, T, TCustomMetadata>

optionalRecursive

optional(t, props) except tweaked to work better for recursive types. Use with ValidateRecursiveSchema for improved type safety.

Signature

optionalRecursive<const T extends Unenforced<ImplicitAllowedTypes>>(t: T, props?: Omit<FieldProps, "defaultProvider">): FieldSchemaUnsafe<FieldKind.Optional, T>;
Type Parameters
Parameter Constraint Description
T Unenforced<ImplicitAllowedTypes>

Remarks

This version of optional(t, props) has fewer type constraints to work around TypeScript limitations, see Unenforced. See ValidateRecursiveSchema for additional information about using recursive schema.

Parameters

Parameter Modifiers Type Description
t T
props optional Omit<FieldProps, "defaultProvider">

Returns

Return type: FieldSchemaUnsafe<FieldKind.Optional, T>

required

Make a field explicitly required.

Signature

required<const T extends ImplicitAllowedTypes, const TCustomMetadata = unknown>(t: T, props?: Omit<FieldProps<TCustomMetadata>, "defaultProvider">): FieldSchema<FieldKind.Required, T, TCustomMetadata>;
Type Parameters
Parameter Constraint Default Description
T ImplicitAllowedTypes
TCustomMetadata unknown Custom metadata properties to associate with the field. See custom.

Remarks

Fields are required by default, but this API can be used to make the required nature explicit in the schema, and allows associating custom properties with the field.

Parameters

Parameter Modifiers Type Description
t T The types allowed under the field.
props optional Omit<FieldProps<TCustomMetadata>, "defaultProvider"> Optional properties to associate with the field.

Returns

Return type: FieldSchema<FieldKind.Required, T, TCustomMetadata>

requiredRecursive

required(t, props) except tweaked to work better for recursive types. Use with ValidateRecursiveSchema for improved type safety.

Signature

requiredRecursive<const T extends Unenforced<ImplicitAllowedTypes>>(t: T, props?: Omit<FieldProps, "defaultProvider">): FieldSchemaUnsafe<FieldKind.Required, T>;
Type Parameters
Parameter Constraint Description
T Unenforced<ImplicitAllowedTypes>

Remarks

This version of required(t, props) has fewer type constraints to work around TypeScript limitations, see Unenforced. See ValidateRecursiveSchema for additional information about using recursive schema.

Parameters

Parameter Modifiers Type Description
t T
props optional Omit<FieldProps, "defaultProvider">

Returns

Return type: FieldSchemaUnsafe<FieldKind.Required, T>