Destructuring & Optional Values

The Course
•
4 min read

Give fields local names

Destructuring takes values out of a record: const { title, pages } = book means declare title from book.title and pages from book.pages. It does not remove those properties or clone nested objects. In const { title: label } = book, title is the field name and label is the new local variable.

A default such as pages = 0 applies only when the value is undefined. It does not replace null. Missing data and explicitly empty data may require different rules. Do not use a convenient default to hide a required field that should have caused rejection.

Ask whether something is missing

Optional chaining, book.details?.pages, returns undefined when details is null or undefined rather than reading a property from an absent object. It does not validate that a present value has the correct type. value ?? fallback supplies the fallback only for null or undefined. Unlike value || fallback, it preserves meaningful zero, false, and empty text.

Read a compact expression in stages: look up the optional field, decide whether it is absent, then choose the display value. These operations are useful when optional data is genuinely optional. A required book id will still need explicit validation in the next lessons.

The ?. guards only the value immediately before it: book.details?.pages permits missing details but still assumes book is a record. To permit a missing book too, use book?.details?.pages. Optional chaining cannot rescue an undeclared variable name. Keep the expected input contract explicit.

Predict and trace

Write the output before running. Follow the values through each call; if your prediction differs, identify the first step that surprised you.

Predict, then run JavaScript
const book = { title: "Notes", pages: 0, details: null };
const { title: label, pages = 99 } = book;

console.log(label);
console.log(pages ?? 99);
console.log(pages || 99);
console.log(book.details?.author ?? "Unknown");
Check your prediction
Notes
0
99
Unknown

Zero is present. The || expression replaces it because zero is falsy; ?? does not.

Separate absence from a meaningful zero

A destructuring default is applied when the property is undefined. A nullish default is applied for null or undefined. Neither one should automatically replace false, zero or empty text. These distinctions are useful only when you have decided which values the domain permits.

Renaming while destructuring changes the local name, not the original property. A nested value is still a shared reference. Destructuring makes access convenient; it is not validation or a copy policy.

Separate absence from a meaningful zero: trace JavaScript
const source = { pages: 0, title: "Types" };
const { title: label, pages = 99 } = source;

console.log(label, pages);
console.log(source.title);
console.log(source.label);
Check your prediction
Types 0
Types
undefined

The field remains title on source. The default does not replace zero. Reading source.label shows why a local rename should not be mistaken for changing the record schema.

Separate absence from a meaningful zero: contrast JavaScript
const source = { note: null, pages: 0 };
const { note = "default" } = source;

console.log(note);
console.log(source.note ?? "fallback");
console.log(source.pages || 99);
console.log(source.pages ?? 99);
Check your prediction
null
fallback
99
0

Destructuring leaves explicit null intact, while ?? chooses the fallback. || also replaces zero, which can silently change a legitimate zero-page result.

Try the rule on new inputs

Test a missing property, explicit undefined, null, zero and empty text. Write down which operation changes each one. Do not combine defaults until you can explain the policy at each stage.

Build it yourself

Exercise

Destructuring & Optional Values: practise

Write pageLabel(book). Use the optional details.pages field, default to “unknown” only when absent, and return text. Print labels for zero pages and absent details.

Your working space JavaScript
// Expected: Pages: 0, then Pages: unknown
Hint 1: the idea

Do not confuse a zero value with a missing field.

Hint 2: a first step

Read book.details?.pages and use ?? before formatting.

Show one solution
function pageLabel(book) {
  const pages = book.details?.pages ?? "unknown";

  return `Pages: ${pages}`;
}

console.log(pageLabel({ details: { pages: 0 } }));
console.log(pageLabel({}));
Pages: 0
Pages: unknown

Try null details and pages: null. Then try pages: “many”: it remains present, proving this helper formats rather than validates.

Test a changed requirement

Try null details and pages: null. Then try pages: “many”: it remains present, proving this helper formats rather than validates.

Explain before moving on

Explain the difference between a destructuring default and ??. Why is optional chaining not a schema check?

Was this article helpful?

Your response is saved on this device.