Skip to content

Brands

module Brands
AssemblyXantham.Fable.Core
Attributes[<AutoOpen>]

Branded primitives: the F# rendering of TypeScript's intersection brands (type UserId = string & { __brand: "UserId" }).

A brand exists to make two values that share a runtime representation refuse to substitute for one another. F#'s units of measure are exactly that tool, and they are erased at compile time, so a branded value costs nothing at runtime - which is the whole requirement for a binding: the JavaScript on the other side only ever sees the primitive.

Numeric brands need nothing from this module. float<UserId> and int<Ticks> are ordinary measure applications, because measures are built to annotate numbers.

Non-numeric primitives are the gap this module fills. A measure cannot be applied to string directly, but MeasureAnnotatedAbbreviation - the mechanism FSharp.UMX is built on - defines an abbreviation that carries one anyway. The plain string type is unaffected: an application with no measure argument still resolves to the primitive, so this abbreviation can sit in scope over generated code that uses string everywhere.

The brand is enforced in both directions, which is the property that makes it worth emitting: a string<UserId> is not a string<OrderId>, and a raw string is neither. Crossing the boundary is deliberate, and tag/untag are the only ways to do it.

Declared inside

boolA bool carrying a unit of measure
charA char carrying a unit of measure
stringA string carrying a unit of measure, so that differently branded strings do not substitute for one another