10 · The real comparison
Why not just strict TypeScript + zod + eslint + ts-pattern?
Because every one of those guarantees is opt-in, and an agent can route around each of them in one line. Glyph's strictness isn't a config file the agent can edit — it's the language. The enforcement point moves from "did we remember to lint this file" to "does it compile."
First, the honest concession
A well-configured TypeScript setup gets you a long way, and if your team runs all of it in CI you've already closed most of the gaps Glyph targets. Credit where it's due — this is the real alternative, so here's the honest mapping:
no `any` → noImplicitAny + @typescript-eslint/no-explicit-any exhaustive match → ts-pattern .exhaustive() (compile-time, today) errors as values → neverthrow / Effect runtime validation → zod at every boundary must-handle errors → an eslint rule deterministic diffs → Biome / Prettier
If you have all that wired up and enforced, you're most of the way there. So the question isn't "does TypeScript lack these ideas" — it's "what does bundling them into a language, non-optionally, actually buy." Three things.
01 Non-optional beats opt-in
Your eslint config only protects code the agent routes through it — and the
agent can write as unknown as User, @ts-ignore,
// eslint-disable-next-line, or simply forget the .exhaustive(),
and it still compiles and merges. Every one of those escape hatches is a config the agent
can edit. Glyph has no such hatch to reach for: there is no as, no ignore
pragma, no way to get a typed value out of unknown without a check the compiler
can see.
const user = body as unknown as User; // @ts-ignore doThing(user.mispelled); // eslint-disable-next-line return anything as any;
return match User.parse(body) {
Ok(user) => use(user),
Err(_) => fallback(),
}
// no `as`, no ignore pragma,
// no lint to switch off.
The strictness the agent cannot config-disable is a categorically different enforcement point than the strictness it can. That's the whole bet.
02 The type is the validator — no second artifact
zod inverts your source of truth: you write the schema, derive the type from it,
and then keep the type, the schema, and any serializer in sync by hand. Keeping those
aligned is exactly where an agent introduces drift — it renames a field in the type
and not the schema, and both still compile. In Glyph the type is the validator:
declaring type User = {...} generates User.parse alongside it.
One artifact, nothing to keep in sync, nothing to forget.
03 Greppable mutation
In TypeScript a state change can hide behind =, .push(),
Object.assign, a setter, or a spread — there's no single token to search
for, and no lint rule fully fixes it. In Glyph shared state lives in a store and every
change is a literal .set(/.update(; grep 'mut '
finds every local mutation. That's a property you can't buy for stock TypeScript at any
price.
The failure-mode diff
Same task, an agent adds a variant to a union and forgets to handle it in one of three places:
// ts-pattern .exhaustive() catches it — // IF every site used ts-pattern and // nobody wrote a plain switch or // a default: case. One that didn't // compiles green and returns undefined.
[E0200] non-exhaustive match on `Feed`: missing variant `Archived` // every unhandled match, everywhere, // fails the build. No opt-in, no // escape, no forgotten default.
Where tooled TypeScript is still ahead (the honest edge)
This cuts both ways, and pretending otherwise would be exactly the dishonesty this page is trying to avoid:
- Richer validation. Glyph descriptors are strict by default (they
reject undeclared keys), but zod still has refinements (
.email(),.min(3), custom predicates) that a generated descriptor doesn't. For rich per-field rules today, zod is ahead. - Deeper matching. ts-pattern's guards and deep structural patterns go
beyond what Glyph's
matchexpresses. - "Provable absence" stops at the
.tsboundary. Glyph's guarantees hold for code Glyph authored; a thrown exception from an npm dependency still bypassesResult, and an imported.d.tstype carries no runtime descriptor. - Ecosystem and hiring. The TypeScript tooling, community, and hiring pool are enormous and battle-tested. Glyph is an early preview.
So the honest summary: if you've fully wired tooled TypeScript and your agents stay inside it, you've got most of this. Glyph's argument is that "stay inside it" is the load-bearing phrase — and it's the phrase an agent breaks. Non-optionality, one-artifact validation, and greppable mutation are the parts you genuinely cannot get by adding more opt-in tools.
Where it stands
Shipping today
No any/as, exhaustive match (E0200/E0218), discarded-Result warning (E0217), type-generated validators, and greppable mutation — all non-optional, none an eslint rule you can disable.
Being measured
The claim that agents produce fewer escaped defects in Glyph than in well-configured strict TS is the benchmark we're building — against tooled TS, not naive TS. See the benchmarks.