CreaTech
← All posts
typescriptjavascriptfrontend

TypeScript strict mode: the settings worth turning on

Most projects ship with strict: true and call it done. Here are the additional flags that catch the bugs strict mode misses.

strict: true in tsconfig.json is the baseline. It enables a bundle of checks that catch entire classes of bugs before runtime: null dereferences, implicit any, unsafe narrowing. If you're not using it, start there.

But strict mode isn't the ceiling. A handful of additional flags do specific work that strict doesn't cover, and they're worth knowing.

noUncheckedIndexedAccess

Array indexing returns T, not T | undefined. That's wrong.

const items = ["a", "b", "c"];
const first = items[0]; // inferred as string, not string | undefined
first.toUpperCase();    // no error, but what if items is empty?

With noUncheckedIndexedAccess: true, TypeScript infers string | undefined. You're forced to handle the empty case. It's stricter than it sounds (you'll be adding a lot of null checks at first), but it surfaces real bugs, especially in data-processing code.

exactOptionalPropertyTypes

Optional properties and | undefined in a value are not the same thing. This flag makes TypeScript agree:

type Config = {
  timeout?: number;
};
 
const cfg: Config = { timeout: undefined }; // error with exactOptionalPropertyTypes

Without it, TypeScript happily lets you assign undefined explicitly to an optional property, which can break code that checks "timeout" in cfg. A small distinction that bites at runtime.

noPropertyAccessFromIndexSignature

If a type uses an index signature, property access should be explicit:

type Headers = { [key: string]: string };
const h: Headers = {};
h.Authorization;  // allowed without this flag, but the key might not exist
h["Authorization"]; // clearer intent

This one is more style than safety, but it makes ambiguous access visible at a glance.

The tsconfig I start with

{
  "compilerOptions": {
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "exactOptionalPropertyTypes": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true
  }
}

noImplicitReturns and noFallthroughCasesInSwitch round it out. Together these five make TypeScript genuinely strict, not just technically enabled.

The upfront cost is more annotations and more fixes on an existing codebase. The long-term payoff is a system where the compiler earns its keep.

Got a project in mind?

I build fast, production-grade sites for freelance clients. Let’s talk.