Short answer
Handle the empty case before you use the value: an if check or an early return, optional chaining (el?.focus()) when doing nothing is fine, or ?? to fall back to a default. Use the non-null assertion (!) only when you know the value exists and TypeScript cannot see why. Do not turn strictNullChecks off; it is the check that catches Cannot read properties of null before your users do.
Where the null comes from, and the fix
01
DOM lookups and React refs
“When strictNullChecks is true, null and undefined have their own distinct types and you’ll get a type error if you try to use them where a concrete value is expected.” TypeScript, TSConfig: strictNullChecks
document.getElementById and querySelector return null when nothing matches, and useRef<HTMLInputElement>(null) starts as null. Check before use.
const form = document.getElementById('signup'); if (!form) return; form.addEventListener('submit', onSubmit); const inputRef = useRef<HTMLInputElement>(null); inputRef.current?.focus();02
Array.find, Map.get and optional properties
“TypeScript follows possible paths of execution that our programs can take to analyze the most specific possible type of a value at a given position.” TypeScript, Narrowing
These return undefined when nothing is found. Decide what should happen then: throw, skip or default.
const user = users.find((u) => u.id === id); if (!user) throw new Error(`No user ${id}`); sendEmail(user.email); const name = profile.nickname ?? profile.fullName;03
The check is in another function
TypeScript narrows within one function. A check done in a helper does not carry over unless the helper is a type guard. Return the checked value, or write the helper as a type predicate.
function isDefined<T>(value: T | null | undefined): value is T { return value != null; } const ids = maybeIds.filter(isDefined); // string[]04
The non-null assertion (!)
el!.focus() tells TypeScript the value is there and removes the check. It changes nothing at runtime, so if you are wrong the app still crashes. Use it only for values that are guaranteed, such as an element your own markup always renders.
Checked against the vendor’s docs on : TSConfig: strictNullChecks; TypeScript Handbook: Narrowing.
Rather hand it over?
Fixed scope, fixed price, paid upfront. The work happens in writing; no call needed.
- from $450App Fix TicketOne reproducible bug in an existing mobile or web app, diagnosed and fixed.See scope and start
- from $450AI-Built App RescueA Lovable, Bolt or Cursor app checked end to end in 3 days, then its worst problems fixed at a fixed price.No issues worth fixing, no charge. If the Launch Check finds nothing rated medium or higher, Simon refunds the full $450. You keep the report either way. This applies to the first 10 Launch Checks bought after October 30, 2026.See scope and start
Related: “Cannot read properties of undefined” · TypeScript “Argument of type is not assignable to parameter” · TypeScript “Property does not exist on type”