ensure before the rest of the function runs.
Define a reusable check
ThisLoggedIn guard requires an AppContext with both a session and a user.
- Forst
- Generated Go
is, followed by the value, its base type, and the
guard name.
is check.
ctx.sessionId and ctx.user are present.
Require fields on a shape
A shape guard describes fields that a value must contain. This is useful when several operations share a basic request shape and add their own requirements. In this example,MutationArg means a request passed to an API operation.
Input requires an input field. Context requires a ctx field.
- Forst
- Generated Go
Build a more specific request type
Apply a guard to a type when every value of that type needs the same fields.AppMutation requires an AppContext in its ctx field.
- Forst
- Generated Go
Check the request in a handler
The handler adds an input requirement and checks that the request belongs to a logged in user.- Forst
- Generated Go
op.input.name.
Why a normal function is not enough
A function that returnsBool can report whether a value passed. Its return
type does not explain what a true value proves about the input.
A type guard records that relationship. When LoggedIn() passes, Forst knows
which fields are present and lets later code use them with the refined type.
Current limits
Type guards are experimental. The examples above can be parsed, checked, and emitted as Go. Narrowing in more complex control flow is still being expanded. See the roadmap.A check applies to the current value
A guard checks the value once at anensure or if. Later changes do not run
the guard again.
Changing a field after the check can make the earlier result outdated.
sessionId: *String need particular care. Clearing the
pointer does not undo the narrowing. Scoped immutability for ensure may
address this later.
Prefer simple variables
Narrowing works best whenensure checks a simple variable.
ensure req.state is ... have partial support. Editor hover may
show the guard while later code still sees the original field type.
Narrowing for compound
ensure subjects is still being expanded. See the
roadmap.Keep guards free of side effects
A guard only checks its subject and parameters. The same input must always produce the same result. Inside a guard you can useif, else if, else, is, and ensure. A guard
cannot change values, use return, add an or clause, or read unrelated
variables.
Shape guards verify fields
A shape guard such asInput(input Shape) verifies that a field exists with the
required shape. It never creates or fills that field.
Changes to op.input or op.ctx after the guard are not tracked. Check the
value again after changing it.
Narrowing after branches
Narrowing inside anif branch may end with that branch. Code after the full
chain can see the earlier type. Branch merging will improve as union type
support expands.
See Ensure and narrowing for
general narrowing limits.
Generated Go
Generated Go uses functions or inline conditions for guard checks. Anensure
that uses the guard follows the normal Go error return path.
Examples
See the type guard examples on GitHubRelated
Continue with built in constraints or learn how to apply guards withensure.
Shapes and constraints
Built-in constraints on primitive fields.
Ensure and narrowing
Using
ensure … is … at call sites.