Docker Multi-Stage Builds: How I Cut My Image Size by 90%
Most Docker images are bloated because they ship the build toolchain alongside the app. Multi-stage builds fix that with one simple pattern.
Enabling strict mode on an existing TypeScript codebase feels brutal at first. But the bugs it catches are real, and the migration is more manageable than it looks.
I avoided enabling strict: true in tsconfig.json for months. The codebase had about 200 files — mostly typed, but with implicit any scattered everywhere. Flipping the switch produced over 400 errors.
It took two days to fix them. Every single one was a real bug waiting to happen.
strict: true is shorthand for a collection of compiler flags. The ones that cause the most friction — and catch the most bugs:
| Flag | What it does |
|---|---|
strictNullChecks | Forces explicit handling of null and undefined |
noImplicitAny | Bans silent any on function parameters |
strictFunctionTypes | Catches unsound function parameter variance |
strictPropertyInitialization | Class properties must be initialized or declared optional |
noImplicitThis | Prevents this from being implicitly any |
Together, they close most of the type holes that make TypeScript feel unreliable. Individually, strictNullChecks alone catches roughly half the bugs in most migrations.
Don’t flip the switch globally and try to fix 400 errors in one sitting. Go flag by flag:
strictNullChecks. It produces the most errors but catches the most real bugs. Work through one module at a time — start with leaf modules that have fewer dependents.// @ts-expect-error sparingly as a temporary escape hatch. Track these with an ESLint rule like @typescript-eslint/prefer-ts-expect-error so they don’t pile up silently.noImplicitAny next. Usually easier — most parameters already have types. You’re just catching the ones that slipped through.If you want even more granularity, TypeScript’s --showConfig flag prints exactly which strict sub-flags are active, so you can verify your incremental progress.
These weren’t hypothetical — strict mode surfaced real issues hiding in production code:
undefined return. A function returned undefined when the caller expected an object. It only failed when a specific API endpoint returned an empty response — a path that unit tests didn’t cover.document.querySelector returned null when the component rendered before the target existed.any swallowing errors. A utility function accepted any implicitly, which meant three different call sites were passing wrong types without any compiler warning.None of these had caused production incidents yet. All of them would have.
Unequivocally yes. The two days of migration paid for themselves the following week when strict null checks caught a bug during a refactor that would have shipped to production. That pattern kept repeating — every major refactor since has been caught by the type system rather than by users.
If you’re starting a new project, enable strict mode from day one — the cost is near zero when there’s no legacy code to fix. If you’re migrating, do it incrementally with the strategy above. Either way, do it.