TS2531Strict Mode
Since TS 2.0Updated in TS 3.7

Fix TS2531: Object Is Possibly 'null'

Learn why TypeScript throws TS2531 when accessing properties on potentially null values, and how to handle null safely with type narrowing and optional chaining.

error TS2531: Object is possibly 'null'

What This Error Means

TS2531 tells you that you're trying to use a value that could be null. Under strictNullChecks, TypeScript won't let you access properties or call methods on a value unless it's sure the value isn't null.

This directly prevents one of JavaScript's most infamous runtime errors: TypeError: Cannot read properties of null. If you've ever called document.getElementById and forgotten to check the result, you've hit exactly the bug this error protects against.

// The general shape of the error:
// Object is possibly 'null'.
//
// TypeScript sees: someValue: SomeType | null
// You wrote:       someValue.property   — not safe!

Common Causes

1. DOM Queries That Return null

DOM methods like getElementById, querySelector, and closest all return null when no matching element is found.

// ❌ Broken
const loginForm = document.getElementById("login-form")
loginForm.addEventListener("submit", handleSubmit)
// ~~~~~~~ Error: Object is possibly 'null'.
// ✅ Fixed — check for null before using the element
const loginForm = document.getElementById("login-form")
 
if (loginForm) {
  loginForm.addEventListener("submit", handleSubmit)
}
 
// Or with optional chaining (for one-off access)
document.getElementById("login-form")?.addEventListener("submit", handleSubmit)

2. Nullable API Response Fields

Many APIs return null for missing or empty fields. If your types reflect this, you need to handle the null case.

// ❌ Broken
interface GitHubUser {
  login: string
  name: string | null
  bio: string | null
  company: string | null
}
 
function displayUserBio(user: GitHubUser) {
  const bioLength = user.bio.length
  //                ~~~~~~~~ Error: Object is possibly 'null'.
}
// ✅ Fixed — provide a fallback for null values
function displayUserBio(user: GitHubUser) {
  const bioLength = user.bio?.length ?? 0
  const displayBio = user.bio ?? "This user hasn't written a bio yet."
}

3. Array.prototype.match() and Regex Results

String.prototype.match() returns null when the pattern doesn't match.

// ❌ Broken
function extractDomain(email: string): string {
  const match = email.match(/@(.+)$/)
  return match[1]
  //     ~~~~~ Error: Object is possibly 'null'.
}
// ✅ Fixed — handle the no-match case
function extractDomain(email: string): string {
  const match = email.match(/@(.+)$/)
 
  if (!match) {
    throw new Error(`Invalid email format: ${email}`)
  }
 
  return match[1]
}

4. Type Narrowing Lost Across Async Boundaries

TypeScript's narrowing doesn't persist across await or callback boundaries, because the value could change in between.

// ❌ Broken
let activeConnection: WebSocket | null = null
 
async function sendMessage(message: string) {
  if (activeConnection) {
    await delay(100)
    activeConnection.send(message)
    // ~~~~~~~~~~~~~~~~ Error: Object is possibly 'null'.
    // TypeScript can't guarantee it's still non-null after await
  }
}
// ✅ Fixed — capture in a local constant before await
async function sendMessage(message: string) {
  const connection = activeConnection
  if (connection) {
    await delay(100)
    connection.send(message) // OK — local const can't be reassigned
  }
}

How to Fix It

1. Null Check with if

The most explicit and readable approach. TypeScript narrows the type inside the block.

const element = document.querySelector(".modal")
 
if (element !== null) {
  element.classList.add("visible") // OK — narrowed to Element
}

2. Optional Chaining (?.)

Short-circuits the expression if the value is null (or undefined). Returns undefined instead of throwing.

const headerText = document.querySelector("h1")?.textContent
// headerText: string | null | undefined

3. Nullish Coalescing (??)

Provides a default when the value is null or undefined.

const username = response.data.user?.name ?? "Anonymous"

4. Early Return Pattern

Useful in functions where a null value means you should stop processing entirely.

function initializeChart(containerId: string) {
  const container = document.getElementById(containerId)
 
  if (!container) {
    console.warn(`Chart container #${containerId} not found`)
    return
  }
 
  // From here on, container is guaranteed to be HTMLElement
  container.style.width = "100%"
  renderChart(container)
}

5. Non-Null Assertion (!) — Use with Caution

// Only when you have certainty TypeScript can't verify
const app = document.getElementById("app")! // you control the HTML

FAQ

What causes TS2531?

TS2531 occurs when you access a property or method on a value that could be null. Common sources include:

How do I fix "object is possibly null"?

The best approach depends on context:

For DOM elements, use the early return pattern or an if check. DOM queries commonly return null and you should always handle that case.

For API data, use optional chaining with nullish coalescing: user.bio ?? "No bio".

For regex matches, check for null and either throw an error or handle the no-match case explicitly.

Avoid blanket use of ! (non-null assertion) as it provides no runtime safety. If the value turns out to be null, you'll get the exact same TypeError that TypeScript was trying to prevent.

What's the difference between TS2531 and TS2532?

Both errors protect you from the same class of runtime error (TypeError: Cannot read properties of null/undefined), but they arise from different sources:

TS2531 (null)TS2532 (undefined)
SourceDOM queries, API responses, explicit null returnsOptional properties, missing Map entries, Array.find()
Meaning"This value was explicitly set to nothing""This value was never set"
FixSame toolset: ?., ??, if checks, !Same toolset: ?., ??, if checks, !

In practice, you'll often see both together. A value typed as string | null | undefined can trigger either error depending on which branch TypeScript is analyzing. Optional chaining (?.) and nullish coalescing (??) handle both null and undefined, making them the most convenient fix for either error.

Related Errors

Related Concepts

Share this reference

Stay Updated

Get the latest TypeScript tips, tutorials, and course updates delivered straight to your inbox.

No spam, unsubscribe at any time.