
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 == undefinedistrue, yetnull !== undefinedunder 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
asyncpipe emitsnullinitially, 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’sstrictNullChecks8 enabled, be prepared for explicitnullchecks when using Angular’s features. While many developers assume they only need to handleundefined, Angular’s defaults can require verifyingnullspecifically—e.g.,if (value !== null). -
Code Clarity
In some scenarios,nulloffers 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 expectundefinedas 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 replacingnullwithundefinedin 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 handlingnull(andundefined) more gracefully. For instance, usingmyValue ?? 'default'ensures a fallback only whenmyValueisnullorundefined, 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 withnull. Recognizing that Angular might returnnullat various points helps pinpoint the source of an error more quickly. -
Form Value Flow
In Angular Reactive Forms, uninitialized controls begin withnull. This is intentional but can surprise new developers expectingundefined. Code that checks forundefinedin form logic might need updating to account fornullinstead. -
Consistency in Large Teams
Inconsistent use ofnullandundefinedacross teams or projects can lead to subtle bugs and redundant checks. While Angular’s APIs often returnnull, the TypeScript Style Guide recommends avoidingnullentirely in favor ofundefinedfor “missing” values. To reduce confusion, establish clear guidelines and consider using lint rules to enforce consistent handling. Where Angular’s use ofnullis 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.