Home › JavaScript

Object is possibly 'undefined'. ts(2532) — how to fix

error TS2532: Object is possibly 'undefined'.
error TS18048: 'user' is possibly 'undefined'.
error TS2531: Object is possibly 'null'.

Quick fix: Narrow before use: if (user) { user.name }, or use optional chaining user?.name and a default user?.name ?? 'anon'. Use ! (user!.name) only when you are certain it is set. For arrays and records with noUncheckedIndexedAccess, check the element after indexing.

What it means

With strict (or strictNullChecks) enabled, undefined and null are separate types. If a value's type is User | undefined, TypeScript won't let you access .name on it until you prove it isn't undefined. Newer TypeScript versions (5.0+) report the same thing as TS18048: 'x' is possibly 'undefined' when it can name the variable.

Common sources of | undefined:

Fix 1: narrow with a check

TypeScript understands normal control flow:

const user = users.find(u => u.id === id);   // User | undefined

if (!user) {
  throw new Error(`No user ${id}`);
}
console.log(user.name);   // user is User here

typeof x === "string", x !== undefined, "key" in obj and instanceof all narrow too.

Fix 2: optional chaining and defaults

When "missing" is a valid state, handle it inline:

const city = user?.address?.city;          // string | undefined
const label = user?.name ?? "Anonymous";   // string
const count = cart.items?.length ?? 0;

?. returns undefined instead of throwing; ?? supplies a fallback only for null/undefined (unlike ||, it keeps 0 and "").

Fix 3: the narrowing got lost in a callback

Narrowing on a property doesn't survive into callbacks, because the property could change before the callback runs:

if (this.config) {
  items.forEach(i => this.config.apply(i));   // TS2532
}

Copy to a local const first:

const config = this.config;
if (config) {
  items.forEach(i => config.apply(i));        // OK
}

Fix 4: indexed access with noUncheckedIndexedAccess

With this option arr[0] is T | undefined:

const first = arr[0];
if (first !== undefined) {
  use(first);
}

// or for records
const value = map[key];
if (value) { ... }

for (const item of arr) gives you T, not T | undefined, so prefer it over index loops.

Fix 5: React refs and state

const ref = useRef<HTMLInputElement>(null);
ref.current?.focus();                 // current is HTMLInputElement | null

const [user, setUser] = useState<User | null>(null);
if (!user) return <Spinner />;
return <p>{user.name}</p>;

Fix 6: non-null assertion (last resort)

If you know the value is set and TypeScript can't see it, ! removes undefined/null from the type:

const el = document.getElementById("app")!;

This is only a compile-time claim. If you're wrong you get Cannot read properties of undefined at runtime, so prefer a check that throws a clear error.

Fix 7: the type itself is wrong

If a property is always present, don't declare it optional. Change name?: string to name: string, or give function parameters a default (function f(opts: Options = {})). Turning off strictNullChecks silences the error everywhere but hides real bugs; avoid it.

Last updated 2026-11-01.