DEV Community

Cover image for Compact Is Not TypeScript. That's the Whole Point.

Compact Is Not TypeScript. That's the Whole Point.

Most developers approach Compact with the wrong frame.

They see the syntax - functions, types, imports, curly braces, and conclude: this is basically TypeScript with some ZK stuff sprinkled in. Then they start writing. And things break in ways that don't make sense. Loops that should work don't compile. Logic that feels correct fails silently. Private data bleeds into places it shouldn't.

The syntax didn't lie to them. Their mental model did.

The Illusion Is the Lesson

Here's a Compact circuit:

export circuit get(): Uint<64> {
  assert(state == State.SET, "Value not set");
  return value;
}
Enter fullscreen mode Exit fullscreen mode

Your brain reads this and fires the usual pattern: function, assertion, return value. It looks like a getter. Call it, get a thing back.

But that's not what's happening.

This circuit doesn't "run." It declares a set of constraints. When you call it from your dApp, the proof system generates a zero-knowledge proof that those constraints were satisfied, without revealing the inputs. What goes on-chain isn't the output. It's the proof.

The frame shift: You're not writing code that executes. You're writing a description of a valid state, and the system proves you were in it.

Two Mental Models. One Will Break You.

Traditional code:

Input → Code executes → Output
Enter fullscreen mode Exit fullscreen mode

You write instructions. The machine follows them. You get a result.

Compact circuits:

Input → Constraints are declared → Proof is generated → Proof is verified
Enter fullscreen mode Exit fullscreen mode

There are no "instructions" in the traditional sense. The circuit defines relationships. The prover proves the relationships held. The chain verifies the proof without seeing the inputs.

Nothing is executed. Correctness is proved.

This is why assert is your only runtime guard. It's not just input validation, it's the mechanism by which you define what a valid state even is. Every assert is a constraint. Every constraint becomes part of the circuit. The circuit is the proof.

The Constraints Are the Feature

The first reaction most developers have to Compact's restrictions:

  • No recursion
  • Bounded loops only (bounds must be compile-time constants)
  • Fixed type sizes
  • No any
  • Unsigned types only

"These seem arbitrary. Why can't I just-"

They're not arbitrary. They're causal.

ZK proofs require finite circuits. A circuit is a fixed structure; gates, wires, constraints, determined entirely at compile time. If you could write unbounded loops or recursion, the compiler couldn't produce a circuit. The circuit literally couldn't exist. The proof couldn't be generated.

The constraints don't limit what Compact can do. They're what make the magic possible at all.

Accept this, and the language makes complete sense. Fight it, and you'll spend weeks trying to port TypeScript patterns into a tool designed around a completely different model.

What "Privacy" Actually Means Here

Compact is not just "TypeScript with encryption." The privacy model is structural.

Midnight has two worlds:

World Where Who can see it
Public On-chain Everyone
Private Local Only you

Your sensitive data; balances, credentials, secrets, never leaves your machine. What goes on-chain is a proof that you ran the computation correctly on that private data. Validators verify the proof. They never see the inputs.

This has a concrete implication: you have to know the boundary.

export ledger is public. witness data is private. disclose() is the explicit line you cross when you intentionally move private data into public state.

The compiler enforces this. If private data tries to flow into public state without going through disclose(), it fails. But knowing why this boundary exists — not just that it does — is what lets you design contracts correctly from the start instead of debugging your way there.

The Use Cases This Unlocks

This matters because entire categories of blockchain applications were previously impossible:

  • Healthcare: Prove you meet age or eligibility requirements without revealing your date of birth or medical history.
  • Finance: Prove your balance exceeds a threshold for a loan without revealing the balance.
  • Identity: Prove citizenship or credential validity without revealing the underlying document.
  • Competitive markets: Submit bids or inventory levels that can be verified as legitimate without being revealed to competitors.

These aren't niche edge cases. They're the reason regulated industries haven't fully adopted public blockchains. With Compact, the privacy model that makes these use cases viable is built into the language, not bolted on after the fact.

Why the Comparison Breaks Down

Concept TypeScript Solidity Compact
Private data Convention only On-chain (visible) Stays local, always
Functions Execute instructions Execute instructions Declare constraints
Loops Unbounded Unbounded (gas-limited) Bounded at compile time
Recursion Allowed Allowed Not allowed
Privacy enforcement None None Type system + compiler

The closest thing Compact resembles isn't TypeScript. It's a constraint satisfaction system with TypeScript syntax. The syntax is a DX choice, not a design philosophy.

The One Thing to Take Away

Every concept in Compact, witnesses, circuits, disclose(), the boundedness rules, becomes clear once you have the right frame:

You're not writing programs. You're describing valid states and proving you were in them.

With that frame:

  • Witnesses make sense: they're the private inputs the prover uses to generate the proof.
  • disclose() makes sense: it's the intentional act of moving a constraint into public view.
  • Bounded loops make sense: the circuit is fixed at compile time, so everything has to be fixed at compile time.
  • assert makes sense: it's not validation, it's constraint declaration.

Without that frame, everything in Compact feels like TypeScript with arbitrary restrictions. With it, everything is exactly as it should be.

What I Built for This

Most documentation explains the what. Compact's own docs are good. But the gap isn't information, it's the conceptual layer underneath.

I've been building a structured guide that goes through each concept with the execution model shift front and center: Compact Book

If you're trying to actually understand Compact rather than just cargo-cult your way through examples, start there.

The syntax is the easy part. The mental model is the work. Get that right, and the rest follows.

Top comments (0)