Skip to content

Engineering

TypeScript Strict Mode — Why Every Velocity X File Compiles With All Flags On

Type Safety Before Runtime

🔐 ⚙️

Here's a frustration every full-stack team knows: the code compiles, tests pass, you ship it to production, and three hours later a user hits a path where something is null and your code tries to call .map() on it. You knew it could be null. You wrote a comment about it. But TypeScript didn't stop you because loose mode doesn't care about null safety.

Velocity X runs with strict TypeScript mode on by default. Every file compiles with strictNullChecks, noImplicitAny, noUnusedParameters, and five other flags enabled. This is how we catch entire categories of bugs before they see daylight — especially when AI-assisted code-gen is writing half your components. One strict tsconfig. One source of type truth. Never ship a null error again.

The Problem: Loose Mode Lets Bugs Through

In loose TypeScript mode, this compiles without a peep:

{`const user: { name: string; email?: string } = { name: 'Alice' };

// No error, even though email might be undefined
const email = user.email.toLowerCase();

// This function works with any input
function processData(data) {
  return data.id + 1;
}`}

The first snippet crashes at runtime if email is undefined. The second function accepts anything — maybe you meant it to accept a specific shape. Loose mode calls these "features". Strict mode calls them bugs.

Velocity X's Strict Setup: The tsconfig.json That Protects You

Velocity X's tsconfig.json enables strict mode and builds on top of it:

{`{
  "compilerOptions": {
    "strict": true,
    "strictNullChecks": true,
    "noImplicitAny": true,
    "noUnusedParameters": true,
    "noUnusedLocals": true,
    "noFallthroughCasesInSwitch": true,
    "exactOptionalPropertyTypes": true,
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true,
    "moduleResolution": "bundler",
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "jsx": "react-jsx"
  }
}`}

What does each flag do? strictNullChecks means null and undefined are distinct types — you must check for them. noImplicitAny means every parameter and variable must have a type (either explicit or inferred). noUnusedParameters and noUnusedLocals catch dead code. exactOptionalPropertyTypes means prop?: string is string | undefined, not string | undefined | null. Together, they create a type wall that bugs cannot pass.

Null Safety in Action

With strict mode, that first snippet becomes an error:

{`const user: { name: string; email?: string } = { name: 'Alice' };

// ERROR: Object is possibly 'undefined'
const email = user.email.toLowerCase();

// FIX: Check first
if (user.email) {
  const email = user.email.toLowerCase();
}`}

You can't call methods on something that might be undefined. You have to check. This is inconvenient the first time. By the hundredth time you ship without a null-ref error, you'll love it.

Implicit Any is Gone

Every parameter must have a type:

{`// ERROR: Parameter 'data' implicitly has an 'any' type
function processData(data) {
  return data.id + 1;
}

// FIX: Type it
function processData(data: { id: number }) {
  return data.id + 1;
}`}

This is where Zod shines. Instead of hand-rolling types, you validate with a schema and infer the type:

{`// lib/schemas.ts
import { z } from 'zod';

export const dataSchema = z.object({
  id: z.number(),
  name: z.string()
});

export type Data = z.infer;

// components/DataProcessor.tsx
import { dataSchema, type Data } from '@/lib/schemas';

function processData(data: Data) {
  return data.id + 1;
}

// Validate incoming data
const result = dataSchema.safeParse(incoming);
if (result.success) {
  processData(result.data); // Type-safe, validated
}`}

One source of truth. Zod validates at runtime. TypeScript knows the shape at compile time. No hand-rolled interfaces. No type drift.

Why Strict Mode Matters for AI-Assisted Code

When Claude generates a React component or API handler, it often skips null checks or uses loose types because it doesn't know your business logic. Strict mode forces the generator to be explicit. You see the gaps immediately:

{`// AI generates this (with strict mode: COMPILE ERROR)
function UserCard({ user }) {
  return 
{user.name} — {user.email.toLowerCase()}
; } // Strict mode forces the fix function UserCard({ user }: { user: { name: string; email?: string } }) { return (
{user.name} — {user.email ? user.email.toLowerCase() : '—'}
); }`}

The error is visible before you test. You don't ship a crash and find out three hours later. Strict mode is a safety net AI-assisted development needs.

Six Common Questions

Doesn't strict mode slow down development?

It slows down the initial write. It saves weeks of debugging. Every production bug that strict mode would have caught is hours of digging. The payoff is immediate and massive.

Can I opt out for legacy code?

Yes. Use // @ts-ignore or //@ts-nocheck on specific lines or files. But mark them and fix them incrementally. Don't ignore warnings and pile them up — that defeats the purpose.

What's the difference between null and undefined?

undefined means "not set". null means "explicitly set to nothing". Strict mode treats them differently. Zod lets you specify which one your field accepts. This clarity is valuable.

Does strict mode work with third-party libraries?

Most do. Some older libraries ship without types. Install @types/package-name if it exists, or @ts-ignore the import. The good ones ship types natively now.

How do I handle any when I really don't know the type?

Use unknown instead. any disables all checks. unknown forces you to narrow the type before using it. It's the same power, but safe.

Can I migrate an existing project to strict mode?

Gradually. Enable one flag at a time. Fix the errors. Move to the next. Or copy the tsconfig above and set skipLibCheck: true to suppress library errors, then fix your own code first.

The Bottom Line

Strict TypeScript is not a nice-to-have. It's table stakes for production code in 2026. Especially when AI is writing code alongside you. Velocity X enforces it from day one. Every file compiles with all flags on. Every null check is explicit. Every type is known. And every bug that strict mode catches is a bug you didn't ship. Start with strict. Don't go back.

Check out the pricing page and the Zod schema post to see how these pieces fit together.

Let us make some quick suggestions?

Please provide your full name.
Please provide your phone number.
Please provide a valid phone number.
Please provide your email address.
Please provide a valid email address.
Please provide your brand name or website.
Please provide your brand name or website.