UNPKG

@macroforge/mcp-server

Version:

MCP server for Macroforge documentation and code analysis

78 lines (56 loc) • 2.26 kB
# Type-Position Macros A type-position macro rewrites TypeScript **types** rather than values. It's invoked with angle brackets: ```typescript const $Nullable = macroRules({ kind: 'type', expand: macroRules` ($t:Type) => $t | null | undefined ` }); type MaybeUser = $Nullable<User>; // → type MaybeUser = User | null | undefined; ``` ## Requirements **The object form is mandatory.** A tag-form `` macroRules`…` `` always declares a value macro; there is no way to mark it as a type macro. You must use `macroRules({ kind: "type", expand: … })`. Only `Type` and `Tt` fragment kinds are accepted in type-position patterns. Any other kind produces a dedicated error. ## Zero-argument references A bare `$Foo` with no type arguments matches only an arm whose pattern is `()`: ```typescript const $Id = macroRules({ kind: 'type', expand: macroRules` () => string ($t:Type) => $t ` }); type A = $Id; // → string type B = $Id<number>; // → number ``` Qualified names never resolve — `a.$Foo` is not a macro reference. ## Sharing modes are rejected Types have no runtime representation, so a type macro cannot share a runtime helper. Setting `mode` to `share-only` or `share-anyway` with `kind: "type"` is an error — and so is supplying `runtime` or `call` at all, independently of the mode. ## Cross-position misuse The two directions behave differently: - Using a **value macro in type position** is a hard error: _"macro `$X` is value-only; cannot use it in type position"_. - Using a **type macro in value position** falls through to the ordinary no-arm-matched path, since the value-position matcher never sees its type arms. ## No backtracking Type-position repetition matching is greedy with no retry. A pattern like `($($t:Type),* $last:Type)` that works in value position will never match in type position. Keep the variable-length group last, or write one arm per arity. See [Repetitions & Backtracking](/docs/declarative-macros/repetitions). ## Composition Type macros compose with each other exactly like value macros, and nested expansions run in type context: ```typescript const $Wrap = macroRules({ kind: 'type', expand: macroRules`($t:Type) => Array<$Nullable<$t>>` }); ```