langium-zod / extractTypeDescriptors
Function: extractTypeDescriptors()
function extractTypeDescriptors(astTypes, config?): ZodTypeDescriptor[];Defined in: extractor.ts:408
Extracts ZodTypeDescriptor records from a Langium grammar's type model.
Runs a three-phase pipeline:
- Object descriptors — converts each
InterfaceType(with inherited properties resolved through the super-type chain) into aZodObjectTypeDescriptor. - Union / enum descriptors — converts each
UnionTypeinto one of:ZodUnionTypeDescriptor(discriminated union of interfaces),ZodKeywordEnumDescriptor(pure keyword literal union),ZodRegexEnumDescriptor(terminal regex ± keyword alternatives), orZodPrimitiveAliasDescriptor(simple primitive alias such asBigDecimal). - Stub descriptors — synthesises primitive-alias stubs for any referenced type name that does not appear in
astTypes(e.g. standalone datatype rules).
Include/exclude filtering from config is applied at each phase.
Parameters
| Parameter | Type | Description |
|---|---|---|
astTypes | AstTypesLike | The interface and union types collected from a Langium grammar, typically produced by Langium's collectAst(). |
config? | FilterConfig | Optional include/exclude filter controlling which type names are emitted. |
Returns
A flat array of type descriptors ready for code generation.
Remarks
This function operates on the duck-typed AstTypesLike shape rather than Langium's concrete AstTypes class. You can pass plain object literals in tests without importing from Langium internals.
Properties whose names start with $ (other than $type) are silently skipped — these are Langium bookkeeping fields ($container, $document, etc.) that should not appear in user-facing Zod schemas. Use stripInternals in ZodGeneratorConfig (via generateZodSchemas) to also strip $type from the projection surface.
Each object descriptor always includes a synthetic $type literal property set to the interface's name. This property is the discriminator key for generated discriminated-union schemas.
Throws
ZodGeneratorError when a property's type cannot be mapped to a known Zod schema kind (e.g. an unresolvable terminal reference).
Example
import { extractTypeDescriptors } from 'langium-zod';
import { collectAst } from 'langium/grammar';
const astTypes = collectAst(myGrammar);
const descriptors = extractTypeDescriptors(astTypes, { exclude: ['InternalNode'] });
console.log(descriptors.map(d => d.name));Use When
- You want to inspect or transform the intermediate descriptor representation before generating code (e.g. to add custom properties or change types).
- You are caching descriptors across multiple calls to generateZodCode with different options, so you only want to pay the extraction cost once.
- You are writing tests against the descriptor model rather than the generated source.
Avoid When
- You just want generated Zod schemas — use generateZodSchemas instead, which calls this function internally.
- You want to apply
regexOverrides— those are applied in generateZodSchemas after extraction and are not visible in the raw descriptor array.
Never
- NEVER filter by
includewithout including stub types that are transitively referenced (e.g.ValidID). BECAUSE phase 3 only emits stubs for names thatshouldInclude()passes; missing stubs produceundefinedschema references at code-gen time. - NEVER assume the returned array order matches the grammar declaration order. BECAUSE the array is grouped by phase (object, then union, then stub); use generateZodCode which topologically sorts object schemas.
- NEVER mutate the returned descriptors and re-pass them to extraction — descriptors are consumed by the generator as values, but the super-type resolution cache lives inside a single
extractTypeDescriptorscall; mutations do not propagate. - NEVER pass a grammar with a union type whose only member is itself filtered out by
include. BECAUSE the union will have zero members and produce a broken discriminated union schema.