Every TypeScript starter ships a tsconfig.json. Almost every one ships it with strict: false, or with a partial strict config that leaves the most useful checks off. The reasoning is usually kindness: "don't scare the new dev with a wall of type errors on day one."
I think that's backwards. The first week of a project is when type discipline gets set, and a starter that defaults to lax checking is teaching the team the wrong lesson. It's easier to start strict and loosen a specific check that's genuinely in your way than to start lax and retrofit strictness onto a codebase that's already full of any-shaped holes.
This is the position I built into the TypeScript templates in scaffoldx-cli: strict: true from the first file, no opt-out prompt, no "relaxed mode" option.
What strict mode actually buys you in week one
The checks that matter most in a new project are the ones that catch the first errors, when they're cheap to fix:
1. noImplicitAny — the function parameter you forgot to type. In week one, that's a five-second fix. In month three, after 200 untyped parameters have propagated, it's a refactor.
2. strictNullChecks — the user.name that throws when user is undefined. This is the single most valuable check in the list, and it's the one lax configs disable most often "because it's annoying." The annoyance is the point: it's the check that turns "undefined at 2am in production" into "type error at 2pm in development."
3. noImplicitReturns — the function that returns a value on some paths and undefined on others. A new project is when your function shapes are being decided; catching a missing return while the function is three lines long is free.
4. noUnusedLocals / noUnusedParameters — the dead code that tells you the design changed and the old path wasn't cleaned up. In a new project, "unused" almost always means "I should delete this," and the compiler is doing your cleanup pass for free.
The "it's too annoying" objection, handled
The standard objection: "strict mode generates a wall of errors and slows me down." True, in the first hour. The counter:
The errors are front-loaded, not ongoing. A strict config produces its maximum error count in the first few files, when the codebase is small. Once the base types are in place, the steady-state error rate drops to near zero — you're not fighting the compiler all day, you're fighting it for an hour and then it's a safety net.
The "annoying" errors are the cheap ones. The errors strict mode generates in week one are almost all five-second fixes (add a type, handle the null, return on the missing path). The errors it prevents are the expensive ones (runtime undefined, silent type drift, the refactor that strict mode would have made unnecessary). The trade is a hour of cheap fixes for a year of avoided expensive ones.
Loosening one check is easy; tightening is hard. If noUnusedParameters is genuinely in your way (say, you have a callback interface that requires an unused argument), you can suppress it per-line or disable that one flag. Starting lax means you've disabled all the checks, and re-enabling them one by one on a grown codebase is the expensive direction.
The starter's actual config
The TypeScript templates ship with a tsconfig that's strict and boring:
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"skipLibCheck": true,
"esModuleInterop": true
}
}
skipLibCheck: true is the one pragmatic concession — it stops the compiler from type-checking node_modules's declaration files, which is a tax nobody wants. Everything else is on. There's no --relaxed flag, no prompt asking if you want strict mode, no "easy mode" template. The position is deliberate: a starter that makes you think about your type discipline is a starter that's doing its job.
The meta-point
A starter encodes a position on how the team will work. "We type-check strictly from day one" is a position, and it's the right one for a new project, where the cost of the position is an hour and the benefit is a year. The lax starter encodes the opposite position — "we'll get to types when we need to" — and "when we need to" is always later and more expensive than "day one."
Pick the starter that argues for the discipline you want, because the discipline you don't pick on day one is the discipline you'll have to fight for in month three.
npx scaffoldx-cli
More Tools
| Tool | What it does | Command |
|---|---|---|
| scaffoldx-cli | Production-ready project templates in seconds | npx scaffoldx-cli |
| dotguard | Scan .env files for exposed secrets | npx @wuchunjie/dotguard |
| gitpulse | Git repo analytics in your terminal | npx @wuchunjie/gitpulse |
| snippetx | Terminal code snippet manager | npx @wuchunjie/snippetx |
If these save you time, consider buying me a coffee. All tools are MIT-licensed, zero-dependency, and run fully offline.
Top comments (0)