惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

U
Unit 42
T
The Blog of Author Tim Ferriss
H
Help Net Security
博客园 - 叶小钗
云风的 BLOG
云风的 BLOG
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
D
DataBreaches.Net
博客园 - 聂微东
A
About on SuperTechFans
大猫的无限游戏
大猫的无限游戏
P
Proofpoint News Feed
Martin Fowler
Martin Fowler
博客园 - 【当耐特】
S
SegmentFault 最新的问题
Blog — PlanetScale
Blog — PlanetScale
酷 壳 – CoolShell
酷 壳 – CoolShell
G
Google Developers Blog
I
InfoQ
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
GbyAI
GbyAI
B
Blog
Engineering at Meta
Engineering at Meta
V
V2EX
Hugging Face - Blog
Hugging Face - Blog

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
Making my TypeScript types 15.7x faster
Dmitry Zakharov · 2026-06-17 · via DEV Community

If you opened this article, you probably already agree with me: sometimes TypeScript compiles painfully slowly.

The same thing happened to @_chenglou — an amazing dev who inspires me (he worked on React, Messenger, ReasonML and ReScript, and currently Midjourney, Pretext).

He's also a user of Sury — the fastest schema validation library, which I maintain — and the author of this issue: "Large TS types cause type inference slowdown".

That's... not nice. But I knew ArkType exists, and that people have built wild things in TS's type system (Doom included). So the slowness was clearly solvable, not fundamental. Here's the recipe I used. You can apply it to your own library.

Before we begin, here are the results. These are type-instantiation counts, measured with @ark/attest:

Operation Before After Faster
Define a 10-field object 1409 343 4.1×
Define a 5-field object (mixed optional) 17916 10557 1.7×
Define a 3-level nested object 31013 20419 1.5×
Define a union of 5 objects 67580 53173 1.3×
Extract S.Output (5-field object) 7842 501 15.7×
Extract S.Input (5-field object) 6767 501 13.5×
Extract S.Output (nested object) 7732 501 15.4×
Define + extract (10-field object) 9446 844 11.2×
Merge + extract output 13651 7039 1.9×

The title comes from that 15.7× on S.Output. Extraction is the operation you hit most often: every type X = S.Output<typeof schema> in your code pays for it.

Let's begin. The recipe is three steps.

1. Pin it down first

If you want to change something, you first need a way to know you didn't break it. For a library like this, that means tests for types:

import { expectTypeOf } from "vitest";
import * as S from "sury";

const user = S.schema({ id: S.string, age: S.number });

// Pin the inferred type. If it drifts, the test fails.
expectTypeOf<S.Output<typeof user>>().toEqualTypeOf<{
  id: string;
  age: number;
}>();

I used to use ts-expect for this, but I migrated to Vitest's type-testing utils (expectTypeOf, above) to drop a dependency. Either way, I already had the tests, and I'll admit they really earned their keep. A type optimization can quietly turn { a: string } into { a?: string } and nothing throws. The tests are what catch that.

2. Measure before you touch anything

If you want to improve something, you have to measure it first, or you can't actually tell whether you improved anything.

For this I used Attest (@ark/attest) from the ArkType creators. I'm very inspired by their TS skills, and I'll admit I'm not that strong at type-level optimization myself. Good thing I have other strong parts. 😄

It counts the type instantiations an expression costs and pins them as a baseline:

import { bench } from "@ark/attest";
import * as S from "sury";

bench("define a user schema", () => {
  return S.schema({ id: S.string, age: S.number });
}).types([230, "instantiations"]);

Bonus: bake those baselines into CI, and any future regression will fail the build.

3. Let Claude do the heavy lifting

The third step was the easy one: I asked Claude to find the most impactful type-instantiation optimizations.

The fix turned out to be small. To read a schema's type back out, S.Output / S.Input matched against the entire Schema<…> type. That type is huge: a big object with several with overloads, intersected with a union of every schema variant. So TypeScript had to expand all of it on every extraction, and the cost grew with the schema:

// Before: match the whole Schema<…> shape just to read Output back out
type Output<T> = T extends Schema<infer Output, unknown> ? Output : never;

But every Sury schema already carries a ~standard field (the Standard Schema marker) that holds the resolved types. So the fix is to read that one slot directly, instead of re-deriving it from the whole shape:

// After: match only the one field that already holds the type
type Output<T> = T extends { "~standard": { types?: { output: infer Output } } }
  ? Output
  : never;

Now extraction costs the same no matter how big the schema is. That one change is most of the 11–16× you see above.

Do you even need it?

It depends (my favorite answer). But feedback loop speed matters more and more as AI iterates on your code. If your codebase's TS compilation is slow, you can use the same approach to identify the slow parts and optimize them.

Wrapping up

One caveat: 15.7× is the drop in type instantiations, not seconds. I didn't time the actual compile. But instantiations are the work tsc does while type-checking, so fewer of them is a fair proxy for what you feel in the editor. 🙂

Hope this was useful. Check out Sury — the most powerful schema library in the TS ecosystem. Follow me on X at @dzakh_dev, and ask your questions in the comments!