Blog
3 min read

TypeScript "Object Is Possibly Undefined" (or Null): How to Fix It

TypeScript warns that a value might be undefined or null before you use it — the exact situation that causes 'Cannot read properties of undefined' at runtime. The right fixes: optional chaining, nullish coalescing, early returns and narrowing, typed state and refs, and when the ! operator is acceptable.

'user' is possibly 'undefined'.
Object is possibly 'null'.

TypeScript is warning you that a value might not be there, and you're using it as if it definitely is. At runtime, that's exactly what produces the most common JavaScript crash: "Cannot read properties of undefined". The warning is TypeScript catching that bug in advance.

This check comes from the strictNullChecks option (part of strict), which is on in most modern projects.

Where "possibly undefined" comes from

  • array.find() — returns undefined if nothing matches.
  • Optional properties — user.address?: Address.
  • Map lookups, process.env.X, localStorage.getItem().
  • document.querySelector() — returns null if no element matches.
  • React refs — ref.current is null before mounting.
  • State initialised as undefined or null while data loads.

Fix 1: optional chaining ?.

Read a property only if the object exists:

const city = user?.address?.city      // undefined instead of a crash
order.items?.length
callback?.()                          // call only if defined

Good for display code where "nothing" is an acceptable result.

Fix 2: nullish coalescing ??

Provide a fallback:

const name = user?.name ?? 'Guest'
const port = Number(process.env.PORT ?? 3000)

?? only falls back on null/undefined; || also falls back on 0 and '', which is often a bug.

Fix 3: check first (narrowing)

TypeScript understands checks and narrows the type afterwards:

const product = products.find(p => p.id === id)
if (!product) {
  return res.status(404).json({ error: 'Not found' })
}
product.price   // ✅ TypeScript knows it's defined here

An early return like this is usually the clearest fix — and it forces you to decide what should happen when the value is missing, which is the real question.

Fix 4: type your state properly

const [user, setUser] = useState<User | null>(null)

if (!user) return <Spinner />
return <p>{user.name}</p>     // ✅ narrowed

(React useState explained)

Fix 5: refs and DOM elements

const inputRef = useRef<HTMLInputElement>(null)

function focus() {
  inputRef.current?.focus()
}
const button = document.querySelector('#save')
if (button) button.addEventListener('click', save)

Fix 6: fail loudly for things that must exist

For configuration that the app can't run without, throw a clear error at start-up instead of sprinkling ?. everywhere:

const dbUrl = process.env.DATABASE_URL
if (!dbUrl) throw new Error('DATABASE_URL is not set')
// dbUrl is string from here on

(Environment variable undefined?)

The ! operator: use sparingly

const el = document.getElementById('root')!

The non-null assertion ! tells TypeScript "trust me, it's not null". It removes the error without adding any check. If you're wrong, you get the runtime crash TypeScript was trying to prevent.

Acceptable when you genuinely know (an element that's always in your HTML). Not acceptable as a reflex to silence errors — a common shortcut in AI-generated fixes. (Type is not assignable to type)

Arrays: noUncheckedIndexedAccess

By default, items[0] is typed as the item type even if the array is empty. Enabling noUncheckedIndexedAccess in tsconfig.json makes it Item | undefined, catching another whole class of crashes. Stricter, but worth it in new projects.


EasySpawn runs your TypeScript app with Claude Code on the same server, so it can fix these warnings with real checks rather than ! — and test the result. See how it works or join the waitlist.

Related: "Cannot Read Properties of Undefined" · Type Is Not Assignable to Type · Property Does Not Exist on Type · NULL in SQL

Keep reading