Type Safety & Developer Productivity

TypeScript Basics

Master static type checking, primitive annotations, type inference, union types, narrowing, interfaces vs type aliases, and how to write robust, error-free modern code.

18 Comprehensive Chapters Interactive Type Checker Lab 8 Assessment Questions Production Best Practices
INTRO

Introduction to Type Safety

JavaScript is dynamically typed: variables can hold any type, and types can mutate arbitrarily during execution. While flexible for small scripts, dynamic typing in large applications frequently leads to runtime crashes like TypeError: Cannot read properties of undefined.

TypeScript introduces a compile-time static type system that inspects your code before it ever executes in the browser or Node.js runtime, catching bugs during development while providing autocompletion and safe refactoring.

01

What Is TypeScript?

TypeScript is an open-source programming language developed by Microsoft. It is a typed superset of JavaScript:

The Superset Principle

Every valid JavaScript program is already a valid TypeScript program. TypeScript simply layers static types on top of JavaScript.

02

TypeScript vs JavaScript

FeatureJavaScriptTypeScript
TypingDynamic (evaluated at runtime)Static (checked at compile time)
Error DetectionDuring runtime execution in browser/serverInstantly inside editor / at build time
Tooling & AutocompleteBasic inferenceIntelliSense, automated refactoring, type docs
ExecutionDirectly executed by browsers and Node.jsCompiled to pure JavaScript before execution
03

How TypeScript Works

TypeScript operates via a two-phase process:

Phase 1

Type Checking

The TypeScript compiler (tsc) verifies all types, interfaces, and function signatures. If any type contract is violated, compilation fails with clear error messages.

Phase 2

Type Erasure & Transpilation

All type annotations and interfaces are completely removed. The output is clean, standard JavaScript that any browser or engine can run with zero overhead.

04

Basic Primitive Types

TypeScript supports the foundational JavaScript primitives:

primitives.ts
let developerName: string = "Sandeep";
let yearsExperience: number = 6;
let isSenior: boolean = true;
let middleName: null = null;
let secondaryEmail: undefined = undefined;
05

Type Annotations

Type annotations use the : type syntax to explicitly declare what type a variable, function parameter, or function return value must be.

annotations.ts
function calculateTotal(price: number, taxRate: number): number {
  return price + (price * taxRate);
}
06

Type Inference

You do not need to annotate every single variable. When you assign an initial value, TypeScript automatically infers the type.

Best Practice: Let TypeScript Infer Obvious Types

Writing let count = 0; is cleaner than let count: number = 0; because TypeScript already knows count is a number. Reserve explicit annotations for function signatures and uninitialized variables.

07

Arrays and Objects

arraysAndObjects.ts
// Typed Arrays
let skills: string[] = ["React", "TypeScript", "Next.js"];
let scores: Array<number> = [98, 85, 92];

// Object Types with Optional Properties
let user: {
  id: string;
  name: string;
  age?: number; // Optional property
} = {
  id: "usr_101",
  name: "Alex"
};
08

Union Types

Union types (|) allow a variable or parameter to accept one of multiple types:

unions.ts
type Status = "idle" | "loading" | "success" | "error";
let currentStatus: Status = "loading";

let identifier: string | number = 402;
identifier = "AB-901"; // Also valid!
09

Type Narrowing

Type Narrowing is the process of refining a broad type (like string | number) into a specific type within conditional branches.

Guard 1

typeof

if (typeof val === "string") — Narrows primitives (string, number, boolean).

Guard 2

in Operator

if ("role" in user) — Checks if a property exists on an object.

Guard 3

instanceof

if (err instanceof Error) — Narrows class instances and errors.

10 & 11

Type Aliases vs. Interfaces

Type Alias

type Person = { ... }

Can model object shapes, primitives, union types, tuples, and function signatures. Cannot be reopened with declaration merging.

Interface

interface Person { ... }

Specifically designed for object shapes and class contracts. Supports extends and declaration merging.

12

any vs. unknown (Crucial Distinction)

'any' is NOT a Normal Solution

Using any tells TypeScript to completely turn off type checking for that value. It re-introduces runtime bugs and breaks autocompletion. Official TypeScript guidance recommends avoiding any.

When dealing with untrusted input (like API responses or dynamic JSON parsing), use unknown instead. unknown forces you to safely narrow the type before doing anything with it:

unknownSafety.ts
let rawData: unknown = JSON.parse('{"name": "Sandeep"}');

// TypeScript blocks unsafe access:
// rawData.name; -> ERROR: Object is of type 'unknown'.

// Safe Narrowing:
if (typeof rawData === 'object' && rawData !== null && 'name' in rawData) {
  console.log((rawData as { name: string }).name); // Safe!
}
13-18

TypeScript Best Practices & Guidelines

Production TypeScript Checklist
  • Enable "strict": true in your tsconfig.json for full safety.
  • Avoid any. Use unknown when the type is truly uncertain.
  • Rely on Type Inference for simple local variable assignments.
  • Use Type Guards (typeof, in, instanceof) to narrow union types.
  • Define explicit return types on public service functions for clear API contracts.

🔥 Live Interactive — TypeScript Type Checker Playground

Inspect real compiler diagnostics, observe type mismatches, and fix type errors in real time.

TypeScript Editor (.ts)❌ Type Error
Compiler Output (tsc):
Type Error (TS2322)

Type 'string' is not assignable to type 'number'.

Why this occurs:

The variable 'age' was explicitly declared as type 'number', but was assigned a string '"25"'. TypeScript blocks this assignment at compile time.

Knowledge AssessmentQuestion 1 of 8

What is the primary architectural purpose of TypeScript compared to standard JavaScript?