forwardRef()
forwardRef() wraps a function that returns a validator. Luthor calls the function each time a value is validated, so the validator it returns can be one that is still being defined when the schema literal is built. Schemas has the explanation.
Signature
Section titled “Signature”ValidatorReference<O> forwardRef<O>(Validator<O> Function() resolver)
abstract interface class ValidatorReference<O> { Validator<O> resolve();}ValidatorReference is the interface shared by every validator and every forward reference. Schema fields, list elements, map keys and values, and union options are all typed as ValidatorReference, so a forward reference fits wherever a validator does.
Parameters
Section titled “Parameters”| Parameter | Type | Meaning |
|---|---|---|
resolver |
Validator<O> Function() |
Called on each validation. Return the validator to use, with modifiers such as .required() applied inside the function. |
Example
Section titled “Example”late final SchemaValidator node;node = l.schema({ 'value': l.string().required(), 'children': l.list(forwardRef(() => node.required())),});node.validate(input)+1-1- valid:
{'value': 'root', 'children': [{'value': 'leaf'}]} - invalid:
{'value': 'root', 'children': [{'value': 'a', 'children': [{'value': 1}]}]}
Every level is validated, and the error path says where:
value must be a stringTwo schemas that refer to each other follow the same pattern:
late final SchemaValidator author;late final SchemaValidator post;author = l.schema({ 'name': l.string().required(), 'posts': l.list(forwardRef(() => post.required())),});post = l.schema({ 'title': l.string().required(), 'author': forwardRef(() => author),});{posts.0.author.name: [name must be a string]}Recursion is bounded by the input and by l.maxDepth.
Code generation
Section titled “Code generation”The generator wraps every reference to another model’s schema in forwardRef(), so self-referential and mutually recursive models work without any annotation.
@luthorForwardRef and its class LuthorForwardRef are deprecated. The generator still accepts the annotation, and the generated code is the same with or without it. Remove it; the analyzer reports a deprecation warning while it is there. Hand-written forwardRef() in runtime code is unaffected and still needed for a hand-written schema that refers to itself.
List<Node>? children, // l.list(forwardRef(() => $NodeSchema.required()))Node? parent, // forwardRef(() => $NodeSchema)