Primitive types
int, uint, bool, string, principal, and buffer<N> map directly to their Clarity equivalents.
let n: uint = 42u; let flag: bool = true; let who: principal = tx-sender;
Home · Features
StxScript exposes a subset of TypeScript-style syntax that maps cleanly onto Clarity — never more than Clarity can express. That constraint is the point: contracts here settle on Bitcoin through Stacks, so if you can write it in StxScript, you can read the resulting Clarity and predict exactly what it does on chain. Here is the full language surface, grouped, with the Clarity each construct emits.
A static type system where every type resolves to a Clarity primitive.
int, uint, bool, string, principal, and buffer<N> map directly to their Clarity equivalents.
let n: uint = 42u; let flag: bool = true; let who: principal = tx-sender;
The two Clarity container types are first class. match destructures them so you never hand-write nested unwraps.
let maybe: Optional<uint> = some(5u); let res: Response<bool, uint> = ok(true);
Bounded lists, typed maps, and tuple records lower to Clarity list, define-map, and tuple types.
let xs: List<uint> = [1u, 2u, 3u];
let point = { x: 1u, y: 2u }; type Amount = uint; documents intent at the source level and disappears at codegen.
type Amount = uint; let fee: Amount = 100u;
Visibility is a decorator; the body is a familiar function block.
@public compiles to define-public, @readonly to define-read-only. A plain function is private.
@public
function transfer(amt: uint): Response<bool, uint> { ... } Arrow lambdas like (x: uint) => x * 2u become real Clarity expressions for fold and map.
let double = (x: uint) => x * 2u;
function identity<T>(x: T): T monomorphizes at compile time — the runtime only ever sees concrete Clarity types.
function identity<T>(x: T): T { return x; } if/else, match, for, and while — bounded and Clarity-safe.
Destructure Optional and Response without nested if/unwrap ceremony.
match balances.get(who) {
some(b) => b,
none => 0u
} for and while lower to fold/map, staying inside Clarity’s decidability guarantees. No unbounded recursion.
for (i in 0u..n) { total = total + i; } Response-based error handling with the sugar you expect.
value! unwraps a Response or panics; value ?? fallback supplies a default for Optional.
let b = balances.get(who) ?? 0u;
Propagate an error out of the current function early — the Clarity try! primitive, ergonomically.
let x = try!(risky-call());
Interfaces the analyzer verifies, and maps with method syntax.
Declare a trait, mark @implements(Token), and semantic analysis proves conformance before deploy.
@implements(Token)
contract MyToken { ... } map balances<principal, uint>; with .get / .set / .delete generates define-map plus map-get?/map-set/map-delete.
map balances<principal, uint>; balances.set(who, 100u);
A module system and the full bitwise operator set.
Split contracts across files and call across contracts without fighting Clarity’s flat-file model.
import { Token } from "./token.stx"; The complete set — & | ^ ~ << >> — surfacing Clarity capability that had no clean sugar before.
let masked = flags & 0x0Fu;
Yes. StxScript only exposes surface area that has a Clarity counterpart. Generics and type aliases compile away; decorators, match, and error sugar desugar to Clarity primitives. The transpiler never emits Clarity the runtime would reject.
No. Generics monomorphize at compile time. The emitted Clarity contains only concrete, monomorphic types — there is no runtime generic dispatch.
Yes, by design. Codegen emits indented, idiomatic Clarity you ship alongside the .stx source so auditors trace source to target line by line.
No. StxScript runs only at build time. Every feature lowers to Clarity that the Stacks blockchain executes and settles on Bitcoin — the security envelope is exactly Clarity’s, no more and no less. StxScript adds no runtime and no new trust assumptions.
StxScript targets the common contract surface — types, functions, decorators, match, maps, traits, and error handling. Some newer or niche Clarity built-ins may not have dedicated sugar yet; where that happens you can still read the emitted Clarity and, if needed, fall back to writing that contract in raw Clarity. Coverage is grounded in the README feature list, not a claim of 100% parity.
Next: how the transpiler works, or the full CLI reference.