runtime.boot

Full Stack Systems
Production Mindset

CodeWithMihir

Engineering thoughtful products from interface to infrastructure.

CodeWithMihir

TypeScript Tutorial

TypeScript null and undefined Explained with Examples

Learn how null and undefined work in TypeScript, how strict null checking works, and how to type missing values safely.

Welcome back! I am Mihir, and in this lesson we will learn null and undefined in TypeScript.

Both represent missing values, but they are not exactly the same.

Understanding them is important for API data, forms, React state, optional properties, and real-world application code.


What is null?

null usually means an intentional empty value.

let selectedUser = null;

It often means:

  • no user is selected
  • no result was found
  • a value was intentionally cleared
  • data is currently empty

Example:

type User = {
  id: number;
  name: string;
};

let selectedUser: User | null = null;

This means selectedUser can be:

  • a User
  • null

What is undefined?

undefined usually means a value has not been assigned or does not exist.

let token: string | undefined;

At this point, token is undefined.

Later:

token = "abc123";

Now it is a string.


null vs undefined

Here is a simple way to think about them:

ValueMeaning
nullintentionally empty
undefinedmissing or not assigned

Example:

let selectedCourseId: number | null = null;
let discountCode: string | undefined;

selectedCourseId is intentionally empty.

discountCode has not been provided yet.


strictNullChecks

When strictNullChecks is enabled, TypeScript treats null and undefined carefully.

This is good:

let name: string = "Mihir";

This is invalid:

name = null;
name = undefined;

If a string can be missing, say so explicitly:

let name: string | null = null;

This makes your code honest.


Typing null Values

Use a union type when a value can be null.

type Product = {
  id: number;
  title: string;
};

let selectedProduct: Product | null = null;

Before using it, check for null:

if (selectedProduct !== null) {
  console.log(selectedProduct.title);
}

TypeScript narrows the type inside the if block.


Typing undefined Values

Use undefined when a value may not be assigned yet.

let accessToken: string | undefined;

if (accessToken !== undefined) {
  console.log(accessToken.toUpperCase());
}

Inside the if block, TypeScript knows accessToken is a string.


Optional Properties

Optional properties use ?.

type User = {
  name: string;
  email: string;
  phone?: string;
};

phone?: string means the property may be missing.

These are both valid:

const userOne: User = {
  name: "Mihir",
  email: "mihir@example.com",
};

const userTwo: User = {
  name: "Aarav",
  email: "aarav@example.com",
  phone: "9876543210",
};

When you access phone, TypeScript knows it might be undefined.

if (userTwo.phone) {
  console.log(userTwo.phone.toUpperCase());
}

Optional Parameters

Function parameters can also be optional.

function greet(name?: string): string {
  if (name) {
    return `Hello, ${name}`;
  }

  return "Hello, guest";
}

name?: string means:

string | undefined

So this works:

greet("Mihir");
greet();

Null Checks Before Using Values

This is unsafe:

function printUser(user: { name: string } | null): void {
  console.log(user.name);
}

TypeScript warns because user might be null.

Correct:

function printUser(user: { name: string } | null): void {
  if (user === null) {
    console.log("No user found");
    return;
  }

  console.log(user.name);
}

After the null check, TypeScript knows user is not null.


Optional Chaining

Optional chaining lets you safely access nested values.

type User = {
  profile?: {
    bio?: string;
  };
};

const user: User = {};

console.log(user.profile?.bio);

If profile does not exist, the result is undefined instead of a runtime error.

This is useful, but do not use it as a replacement for thinking clearly about your data.


Nullish Coalescing

Use ?? to provide a fallback for null or undefined.

let displayName: string | null = null;

const finalName = displayName ?? "Guest";

finalName becomes "Guest".

This is different from ||, because ?? only handles null and undefined.


Common Mistake: Forgetting to Check

let selectedUser: { name: string } | null = null;

console.log(selectedUser.name);

TypeScript warns because selectedUser may be null.

Check first:

if (selectedUser) {
  console.log(selectedUser.name);
}

Common Mistake: Using null and undefined Randomly

Choose a consistent meaning in your project.

For example:

  • use null for intentionally empty state
  • use undefined for optional or missing properties

This keeps your code easier to understand.


Quick Reference Summary

ConceptExample
Null valuelet user: User | null = null
Undefined valuelet token: string | undefined
Optional propertyphone?: string
Optional parameterfunction greet(name?: string)
Null checkif (user !== null)
Undefined checkif (token !== undefined)
Optional chaininguser.profile?.bio
Fallbackname ?? "Guest"

Practice

Create a function that prints a selected course:

type Course = {
  id: number;
  title: string;
};

function printSelectedCourse(course: Course | null): void {
  if (course === null) {
    console.log("No course selected");
    return;
  }

  console.log(course.title);
}

printSelectedCourse(null);
printSelectedCourse({ id: 1, title: "TypeScript Basics" });

Now add an optional description?: string property and safely print it with a fallback.


What You've Learned

You now understand:

  • What null means
  • What undefined means
  • The difference between null and undefined
  • Why strictNullChecks matters
  • How to type nullable values
  • How optional properties and optional parameters work
  • How to check before using missing values
  • How optional chaining and nullish coalescing help

What's Next?

In the next lesson, we will learn the any Type in TypeScript.

We will understand why any is powerful, why it is risky, and when you should avoid it.


Need Help?

  • Have questions, confusion, or want to know more? Contact me

Missing values are normal in real applications. Good TypeScript code makes those missing states visible instead of hiding them.