Chapter 3: TypeScript Primer
Angular is written in TypeScript, a superset of JavaScript that adds static typing and modern features. If you’re new to TypeScript, this chapter will give you just enough background to be productive in Angular.
3.1 What is TypeScript?
- TypeScript = JavaScript + Types.
- Compiles down to plain JavaScript (runs everywhere).
- Adds features like interfaces, generics, enums, decorators.
- Helps prevent bugs by catching errors at compile-time.
3.2 Basic Types
let isLoggedIn: boolean = true;
let age: number = 25;
let name: string = 'Alice';
let tags: string[] = ['angular', 'typescript'];
let user: [string, number] = ['Bob', 33]; // tuple
3.3 Functions
function add(a: number, b: number): number {
return a + b;
}
const multiply = (a: number, b: number): number => a * b;
- Return type can be inferred (often optional).
- Parameters can be optional or have default values:
function greet(name: string = 'Guest'): string {
return `Hello, ${name}`;
}
3.4 Interfaces
Interfaces define object shapes.
interface User {
id: number;
name: string;
email?: string; // optional property
}
const user: User = { id: 1, name: 'Alice' };
3.5 Classes
Angular uses classes everywhere (components, services, etc.).
class Person {
constructor(public name: string, private age: number) {}
greet(): string {
return `Hi, I'm ${this.name}`;
}
}
const bob = new Person('Bob', 25);
console.log(bob.greet());
3.6 Generics
Generics allow reusable, type-safe code.
function identity<T>(value: T): T {
return value;
}
let num = identity<number>(42); // num: number
let str = identity('Angular'); // str: string
3.7 Enums
Enums define a set of named constants.
enum Role {
Admin,
User,
Guest
}
const currentRole: Role = Role.Admin;
3.8 Type Aliases & Union Types
type ID = number | string;
let userId: ID = 42;
userId = 'abc123'; // valid
3.9 Decorators
Angular uses decorators heavily (@Component, @Injectable, etc.).
A decorator adds metadata to classes.
function Log(constructor: Function) {
console.log('Class decorated:', constructor.name);
}
@Log
class Demo {}
// Output: "Class decorated: Demo"
Great idea 🙌 — null safety and union types are crucial in TypeScript, especially since Angular templates often run into null | undefined values. Let’s expand the TypeScript Primer with a dedicated section on null safety and union types.
3.10 Null Safety and Strict Mode
By default, TypeScript in strict mode prevents you from using null or undefined unless explicitly allowed. This eliminates a whole class of runtime errors.
let name: string = 'Alice';
name = null; // ❌ Error in strict mode
name = undefined; // ❌ Error
To allow null/undefined, you must explicitly declare it with union types:
let name: string | null = null;
let age: number | undefined = undefined;
3.11 TypeScript in Angular Context
While TypeScript is the foundation of Angular, not all features behave exactly the same in Angular templates. Here are some Angular-specific tips and “gotchas” you’ll encounter often.
The Elvis Operator (?.) in Templates
Already discussed, but let’s emphasize Angular usage:
<p>Email: {{ user?.profile?.email }}</p>
- Prevents runtime errors when
userorprofileisnull. - Very common when binding API-driven data that may not exist yet.
Non-Null Assertion Operator (!)
Sometimes you know a value won’t be null, but TypeScript can’t infer it. In Angular, this often happens with @Input() properties or template references.
@Component({
selector: 'app-profile',
standalone: true,
template: `<p>{{ user!.name }}</p>`
})
export class ProfileComponent {
@Input() user!: { name: string }; // “trust me, this will be set”
}
✅ Tells TypeScript: this will not be null.
⚠️ Use carefully — you can cause runtime errors if you’re wrong.
Type Assertions (as) in Templates
Angular templates allow as casting for better type narrowing:
<div *ngIf="user as u">
<p>Hello {{ u.name }}</p>
</div>
Here:
useris checked for truthy value.- If true, it’s assigned to
uwith narrowed type.
This avoids repeating user?.name.
Strict Template Checking
With Angular’s strictTemplates option enabled (angularCompilerOptions.strictTemplates: true in tsconfig.json), the compiler will:
- Catch invalid property bindings.
- Ensure correct types in event handlers.
- Detect missing
asyncpipe unwraps.
Example:
<p>{{ user.age.toUpperCase() }}</p>
❌ Error: age is a number, not a string.
Strict templates = safer apps.
Async Pipe with Type Safety
Angular templates use the async pipe to unwrap Observables and Promises.
<p *ngIf="user$ | async as user">
Hello {{ user.name }}
</p>
- The
as usersyntax narrows the type inside the block. - No need for Elvis operator inside the block.
Angular Inputs and Null Safety
Inputs often need explicit null handling:
@Component({
selector: 'app-avatar',
standalone: true,
template: `
<img [src]="url ?? 'default.png'" />
`
})
export class AvatarComponent {
@Input() url: string | null = null;
}
Using ?? ensures there’s always a fallback.
Angular with Union Types
Union types model flexible inputs:
@Component({
selector: 'app-status',
standalone: true,
template: `<p>Status: {{ status }}</p>`
})
export class StatusComponent {
@Input() status: 'online' | 'offline' | 'busy' = 'offline';
}
✅ Type-safe: only accepts allowed values.
❌ Binding something else (<app-status status="sleeping">) → compile error.
3.12 Putting It Together
Angular templates are TypeScript-aware, but they extend it with:
?.(safe navigation / Elvis operator).!(non-null assertion for inputs and bindings).as(template type narrowing).asyncpipe for Observables/Promises.- Strict template checking to enforce correctness.
3.13 Summary
- TypeScript prevents
nullandundefinedbugs with strict null checks. - Use
string | nullornumber | undefinedto allow nullable types. - Use optional chaining (
?.) and nullish coalescing (??) for safety. - Union types let you model flexible values (
string | number). - Type guards (
typeof,in,instanceof) help narrow union types. - Literal unions let you model finite sets of allowed values.
👉 These features are heavily used in Angular:
- Template bindings often deal with
null | undefined. - Inputs and services may accept multiple types.
- Strong typing makes your app safer and easier to maintain.