6 min read

Decoding Angular’s null: A Journey Through Its Dart Origins

Table of Contents

Typescript-Angular-Dart-Venn-Diagram

While watching the Angular Documentary, I came across a segment1 featuring Alex Rickabaugh, a core member of the Angular team. He discussed a subtle but impactful design choice from Angular’s early development: returning null in many places where JavaScript developers might expect undefined. What sounds like a minor quirk is actually a remnant of Angular’s close collaboration with Dart. That insight ignited my curiosity, prompting me to dive deeper into the framework’s history—and ultimately, it led me to research this topic further and write this article.

Dart’s Imprint on Angular

When Angular 2 was being built, it aimed to become a next-generation framework that could seamlessly target both TypeScript and Dart. At the time, Google had high hopes for Dart as a dominant web language, and Angular’s design had to be compatible with Dart’s constraints. One key detail? Dart doesn’t have undefined - only null 2.

This difference significantly influenced Angular’s internals. In JavaScript and TypeScript, undefined is a common way to say “there’s no value here,” but Dart had only null. To keep Angular uniform across both TypeScript and Dart, the team standardized on null. Consequently, in many internal APIs and public behaviors—like handling dependency injection, form controls, and asynchronous data—Angular returns null where pure JavaScript developers might have expected undefined.

Although Google’s push for Dart as a mainstream web language eventually waned, this early design choice became a permanent part of Angular’s DNA.

Two Ways to Say “No Value”: null vs. undefined

Why does JavaScript even have two different ways3 to represent nothing? It boils down to JavaScript’s rapid inception. During its creation, undefined emerged to represent an uninitialized variable, while null was intended for an intentionally empty or non-existent value 4. Over time, this duality caused confusion:

  • Loose equality: null == undefined is true, yet null !== undefined under strict checking.
  • Frequent checks: Developers often feel compelled to write extra conditions (if (value != null)), ensuring they don’t trip over a silent bug.

Tony Hoare once called null a “billion-dollar mistake” for the endless crashes and bugs it has caused 5. Yet, in Angular, null continues to dominate, mainly due to historical ties with Dart.

A Shift to TypeScript… But null Stays

When Angular 2 launched in 2016 6, Google had scaled back Dart’s role in mainstream web development, and TypeScript was rapidly rising. Angular pivoted to fully embrace TypeScript; however, the decision to use null was already woven into Angular’s infrastructure. Changing it after the fact would have been enormously disruptive, touching everything from forms to dependency injection to how observables emit initial values.

These are some notable areas where null appears in Angular instead of undefined:

  • Dependency Injection: When a service is optional and not provided, Angular returns null.
  • Forms: Empty or uninitialized form controls often begin with null.
  • Async Values: The async pipe emits null initially, before any observable data arrives 7.

It’s not a bug—it’s simply a design choice. Yet it sometimes surprises modern developers who are used to undefined elsewhere in JavaScript/TypeScript.

Practical Implications

  • Type Checking
    With TypeScript’s strictNullChecks8 enabled, be prepared for explicit null checks when using Angular’s features. While many developers assume they only need to handle undefined, Angular’s defaults can require verifying null specifically—e.g., if (value !== null).

  • Code Clarity
    In some scenarios, null offers a clearer semantic signal that “there is intentionally no value.” This aligns well with the Dart-like notion that a value is consciously set to null, rather than simply being uninitialized. However, many developers with a JavaScript/TypeScript background often expect undefined as the “missing” or “not yet assigned” value.

  • Community Discussions
    Multiple GitHub issues and proposals 79 have explored aligning Angular’s behavior more closely with typical TypeScript usage by replacing null with undefined in certain APIs. However, a full-scale change remains unlikely, given the potential to break existing applications and the extensive rewrites it would entail.

  • Optional Chaining and Nullish Coalescing
    Features like optional chaining (?.) and nullish coalescing (??) help mitigate confusion by handling null (and undefined) more gracefully. For instance, using myValue ?? 'default' ensures a fallback only when myValue is null or undefined, rather than any falsy value.

  • Debugging and Error Handling
    Many runtime errors originate in assumptions about value presence. A typical "Cannot read property X of undefined" can just as easily occur with null. Recognizing that Angular might return null at various points helps pinpoint the source of an error more quickly.

  • Form Value Flow
    In Angular Reactive Forms, uninitialized controls begin with null. This is intentional but can surprise new developers expecting undefined. Code that checks for undefined in form logic might need updating to account for null instead.

  • Consistency in Large Teams
    Inconsistent use of null and undefined across teams or projects can lead to subtle bugs and redundant checks. While Angular’s APIs often return null, the TypeScript Style Guide recommends avoiding null entirely in favor of undefined for “missing” values. To reduce confusion, establish clear guidelines and consider using lint rules to enforce consistent handling. Where Angular’s use of null is unavoidable (e.g., optional services or form controls), ensure teams understand its role and handle it properly.

Understanding this backstory helps developers see why Angular behaves differently and how to handle those differences more confidently.

Looking Forward

The story of null in Angular underscores how framework decisions are rarely random. Often, they spring from collaborations and ambitions that may fade over time—but leave permanent footprints on the codebase. While TypeScript has become Angular’s primary language, the Dart-driven preference for null persists as a reminder that design choices made in one era can echo long into another.

As Angular continues to evolve, so may its approach to “absence of value.” For now, null remains part of Angular’s heritage, and recognizing its historical roots can help us navigate it more gracefully in modern development.


Footnotes

  1. Alex Rickabaugh - Angular Documentary ↩

  2. Dart’s Sound Null Safety ↩

  3. Null vs. Undefined in JavaScript ↩

  4. JavaScript: The First 20 Years ↩

  5. Tony Hoare’s Billion-Dollar Mistake ↩

  6. Angular 2 Release Announcement ↩

  7. Change async pipe’s default value from null to undefined ↩ ↩2

  8. TypeScript “strictNullChecks” - a migration guide ↩

  9. Abandon null in favor of undefined ↩