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
istrue
, yetnull !== 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 emitsnull
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’sstrictNullChecks
8 enabled, be prepared for explicitnull
checks when using Angular’s features. While many developers assume they only need to handleundefined
, Angular’s defaults can require verifyingnull
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 expectundefined
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 replacingnull
withundefined
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 handlingnull
(andundefined
) more gracefully. For instance, usingmyValue ?? 'default'
ensures a fallback only whenmyValue
isnull
orundefined
, 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 returnnull
at 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 forundefined
in form logic might need updating to account fornull
instead. -
Consistency in Large Teams
Inconsistent use ofnull
andundefined
across teams or projects can lead to subtle bugs and redundant checks. While Angular’s APIs often returnnull
, the TypeScript Style Guide recommends avoidingnull
entirely in favor ofundefined
for “missing” values. To reduce confusion, establish clear guidelines and consider using lint rules to enforce consistent handling. Where Angular’s use ofnull
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.