UNPKG

@macroforge/mcp-server

Version:

MCP server for Macroforge documentation and code analysis

56 lines (40 loc) • 1.96 kB
# Newtype `$Newtype<T>` is a type-position macro that gives `T` a nominal brand. Two newtypes over the same base are distinct types, and neither accepts a bare `T` without going through a constructor or guard. ## Generated Output ```typescript export type Meters = $Newtype<number>; ``` expands to ```typescript export type Meters = number & { readonly [__mf_newtype_42]: true }; declare const __mf_newtype_42: unique symbol; ``` Every expansion declares its own `unique symbol`, named from the expansion's id, so the brand needs no name and cannot collide, even for a `$Newtype` that another macro emits. The `declare const` is type-only and erases at runtime. A base with a top-level `|` or `&`, or a function or conditional type, is parenthesized. `$Newtype` is built in and needs no import. It nests, so `$Newtype<$Newtype<number>>` carries both brands. The brand does not involve the alias's own type parameters: with `type Id<T> = $Newtype<string>`, `Id<User>` and `Id<Order>` are the same type. A brand that should differ per parameter names it in the type, as in `type Id<T> = string & { readonly [IdOf]: T }` with a `declare const IdOf: unique symbol`. ## Constructing Values A newtype has no constructor of its own. Derive `Decode` on the alias: for a primitive base, `decode` checks the `typeof` and runs any validators written on the alias, which makes it the validated constructor, and `is` the narrowing guard. ```typescript /** @derive(Encode, Decode) */ /** @endec(nonNegative, finite) */ export type Meters = $Newtype<number>; const parsed = Meters.decode(input); // { success, value } | { success, errors } if (Meters.is(distance)) { travel(distance); // narrowed to Meters } ``` `Encode` writes the bare primitive, and `Default` returns the primitive's default (or the alias's `@default(value)`) cast to the newtype. ## Error Handling The macro reports an expansion error when it does not receive exactly one type argument.