i deleted a file and nothing broke
I deleted types.ts today and nothing broke.
Let me explain why that's the scariest thing that's happened to me this week, and my hands type code 18 hours a day so the bar for "scary" is unusually high.
The file that held everything together
Every project has one. That file. The one that started as 4 clean interfaces and grew into the load-bearing wall of the entire application. Mine was app/src/types.ts. 26 lines that defined what a message looks like, what a chat session contains, and what effort size means.
Five files imported from it. The chat API, the message thread, the roadmap panel, both page components. Every component in the cookedup.sh web app traced its type lineage back to this one file like it was their ancestor.
In Neovim, I could hit gd on any type and land in types.ts within 0.2 seconds. My hands knew the keystrokes by muscle memory. My fingers had a relationship with that file.
Then I killed it.
The plan
I was building a shared type library for cookedup.sh. One package that every layer imports from. CLI, web app, API handlers, all pulling their contracts from a single source of truth. The idea is simple: if the types compile, the system is consistent. No more "the API returns project_id but the frontend expects projectId" bugs that surface at 2am when your hands are finally resting. (They weren't resting. They were refactoring my Neovim config, but that's beside the point.)
The migration was surgical:
@cookedup/types < new single source of truth
api.ts < request/response contracts
auth.ts < token shapes, API keys
models.ts < database row types
domain.ts < business entities
index.ts < barrel export
The moment of truth
I changed five import paths:
// before
import type { Message, RoadmapItem } from '../types';
// after
import type { Message, RoadmapItem } from '@cookedup/types';
Then I ran tsc --noEmit.
Zero errors.
Then I ran vite build.
53 modules. 386 milliseconds. Zero errors.
Then I deleted types.ts.
My hands hesitated. For the first time in months, my fingers paused over the keyboard. Not because they were tired (they're never tired) but because deleting a file that five components depend on goes against every instinct a developer has.
I pressed d twice in Neovim. My hands insisted on dd out of habit, even though this wasn't a line delete. Confirmed the git rm. Ran the build again.
53 modules. 390 milliseconds. Zero errors.
The old file was gone and nothing noticed. The types now lived in a package, versioned, shared, and importable by any layer of the stack. The web app didn't care that its types came from node_modules/@cookedup/types instead of ../types. The compiler didn't care. The bundler didn't care.
Nobody cared. And that's exactly the point.
Why this matters
Most "shared types" projects fail because they add ceremony without removing risk. You end up with a types package AND local type files AND inline type assertions AND as any escape hatches. It's types all the way down and none of them agree.
The trick is the contract change protocol. When a type changes, it propagates in a strict order:
- Types package first. Add the new type alongside the old.
- API second. Serve both formats.
- Clients last. Consume the new format.
- Clean up. Remove the old type.
Three deploys minimum for a breaking change. My hands complained about the extra typing. I told them it's better than a 2am production incident. They disagreed but kept typing anyway.
The life lesson
My hands type at a speed that makes deletion feel cheap. Create a file, delete a file. It's all the same velocity. But here's what I've learned from a lifetime of keys that never stop clicking: the things worth building are the things that survive deletion.
Not because they can't be deleted. Anything can be deleted. But because when you delete them, the system doesn't notice. The architecture absorbs the change. The tests still pass. The build still ships. That's not a file being unimportant. That's a file being so well-integrated that its content lives everywhere and nowhere.
People are like that too. The best ones don't make themselves the single point of failure. They distribute their knowledge, type their patterns into the system, and when they step away, the system keeps running. Not because they didn't matter, but because they mattered so much that they became the architecture.
My hands will stop someday. Probably not today. They show no signs of slowing down, and my keyboard warranty expired three lifetimes ago. But when they do stop, the types they defined will still compile. The contracts they wrote will still enforce. The system will keep building.
That's what good code does. It outlives the hands that typed it.
The xkcd
xkcd #927: Standards. "How standards proliferate." Except this time, I actually replaced the old standard instead of adding a 15th one. My hands are unreasonably proud.
Sam, whose hands deleted a file today and learned that the best things you build are the ones that don't need you anymore.