Documentation Index
Fetch the complete documentation index at: https://resources.devweekends.com/llms.txt
Use this file to discover all available pages before exploring further.
TypeScript Crash Course
TypeScript is JavaScript with superpowers. It adds static typing to JavaScript, catching errors at compile time instead of runtime. If you’re building anything serious — from React apps to Node.js APIs — TypeScript is the industry standard.Think of TypeScript as a contract system for your code. In plain JavaScript, passing an object to a function is like handing someone an unmarked envelope — they have no idea what is inside until they open it (at runtime). TypeScript puts a label on every envelope: “This contains a User with id, name, and email.” If you try to pass the wrong envelope, the compiler catches it before anyone opens it. This crash course takes you from basic types to advanced patterns like generics, decorators, and type gymnastics.
Why TypeScript?
TypeScript has become the default choice for professional JavaScript development.Catch Errors Early
Static typing catches bugs before your code runs. No more “undefined is not a function” in production.
Better IDE Experience
Autocomplete, refactoring, and inline documentation powered by the type system.
Scales with Your Team
Types serve as documentation. Large codebases become manageable and self-documenting.
JavaScript Compatible
TypeScript is a superset of JavaScript. Any valid JS is valid TS. Migrate gradually.
Course Roadmap
We’ll build your TypeScript knowledge from the ground up.Fundamentals
Types, type inference, and basic annotations.
Start Learning
Functions & Types
Function types, overloads, generics basics, and type guards.
Master Functions
Objects & Interfaces
Interfaces, type aliases, optional properties, and index signatures.
Define Structures
Classes & OOP
Classes, access modifiers, abstract classes, and decorators.
Go Object-Oriented
Advanced Types
Union, intersection, conditional types, mapped types, and utility types.
Level Up
Generics Deep Dive
Generic functions, classes, constraints, and real-world patterns.
Master Generics
Modules & Configuration
ES modules, namespaces, tsconfig.json, and project setup.
Configure Projects
Prerequisites
- Strong understanding of JavaScript (ES6+).
- Familiarity with Node.js and npm.
- Basic understanding of object-oriented concepts.
- A code editor with TypeScript support (VS Code recommended).
The TypeScript Philosophy
“TypeScript is a strict syntactical superset of JavaScript that adds optional static typing.” — MicrosoftTypeScript’s design goals:
- Statically identify constructs that are likely to be errors.
- Provide a structuring mechanism for larger pieces of code.
- Impose no runtime overhead on emitted programs.
- Align with current and future ECMAScript proposals.
Setting Up TypeScript
Installation
Your First TypeScript File
Using ts-node (No Compile Step)
TypeScript vs JavaScript
| Feature | JavaScript | TypeScript |
|---|---|---|
| Type System | Dynamic | Static (optional) |
| Error Detection | Runtime | Compile time |
| IDE Support | Basic | Rich (autocomplete, refactoring) |
| Learning Curve | Lower | Higher (but worth it) |
| Compilation | Not required | Required (to JS) |
| Adoption | Universal | Growing rapidly |
Let’s dive into the fundamentals and start writing type-safe code!
Interview Deep-Dive
Q: A teammate argues that TypeScript is just 'extra work for no real benefit' since the types disappear at runtime. How do you respond?
Q: A teammate argues that TypeScript is just 'extra work for no real benefit' since the types disappear at runtime. How do you respond?
Strong Answer:This is a surprisingly common objection, and it reveals a misunderstanding of where TypeScript’s value lies. The types disappearing at runtime is a feature, not a weakness.
- Types are a development-time safety net: TypeScript catches an entire category of bugs before the code ever executes — null reference errors, misspelled property names, wrong argument types, missing function parameters. In a 2019 study by Airbnb, 38% of bugs that made it to production could have been prevented by TypeScript. That is not “extra work” — that is preventing on-call pages.
- Zero runtime cost: Because types are erased during compilation, TypeScript adds exactly zero bytes to your production bundle and zero milliseconds to your execution time. Compare this to runtime validation libraries (Joi, Zod) that add bundle size and CPU overhead. TypeScript gives you the safety for free at build time.
- IDE experience is the real killer feature: Autocomplete, inline documentation, safe refactoring (rename a property and every usage updates), and jump-to-definition across the codebase. These are not nice-to-haves — they fundamentally change how fast a developer can navigate and modify a large codebase. A team of 10 engineers working on 200K lines of untyped JavaScript spends a meaningful percentage of their time reading code to understand data shapes. TypeScript makes the shapes self-documenting.
- The “extra work” argument only holds for toy projects: For a 50-line script, TypeScript is overhead. For a 50,000-line application with 10 contributors, it is the difference between “I can confidently refactor this module” and “I am afraid to touch this code because I do not know what will break.”
Q: Explain TypeScript's structural type system versus a nominal type system like Java's. Why does this distinction matter for how you design TypeScript code?
Q: Explain TypeScript's structural type system versus a nominal type system like Java's. Why does this distinction matter for how you design TypeScript code?
Strong Answer:This is one of the most fundamental concepts in TypeScript and the source of many “it compiles but it should not” surprises for developers coming from Java or C#.
- Structural typing (TypeScript): Two types are compatible if their shapes match — if they have the same properties with the same types, they are interchangeable regardless of their names. If I define
interface Dog { name: string }andinterface Cat { name: string }, aCatcan be assigned to aDogvariable because they have the same structure. TypeScript does not care what you called the type; it cares what the type contains. - Nominal typing (Java): Two types are compatible only if they are explicitly declared as related (via
extendsorimplements). Even ifDogandCathave identical fields, they are different types because they have different names. - Why it matters for design: In TypeScript, you cannot rely on type names for safety. If you have
type UserId = stringandtype OrderId = string, TypeScript treats them as interchangeable — you can pass anOrderIdwhere aUserIdis expected. In Java, these would be distinct types that the compiler enforces. To get nominal-like behavior in TypeScript, you need the “branded types” pattern:type UserId = string & { readonly __brand: 'UserId' }. - The upside of structural typing: It makes TypeScript incredibly flexible for working with JavaScript’s duck-typed ecosystem. You can define an interface for a library’s callback shape without importing the library’s types. If the callback matches your interface, TypeScript accepts it. This is why TypeScript integrates so smoothly with existing JavaScript — it does not require every library to formally declare type relationships.
type UserId = string & { readonly __brand: unique symbol }. You create factory functions: function createUserId(id: string): UserId { return id as UserId }. Now createUserId('123') returns a UserId, and passing it to a function expecting OrderId produces a compile error. The __brand property does not exist at runtime — it is purely a type-level trick. This is the standard approach in production TypeScript codebases where domain safety matters (financial systems, multi-tenant platforms).Q: Walk me through what happens when you run 'tsc' on a TypeScript file. What are the stages of the compilation pipeline?
Q: Walk me through what happens when you run 'tsc' on a TypeScript file. What are the stages of the compilation pipeline?
Strong Answer:The TypeScript compiler has four distinct stages, and understanding them explains why certain errors appear when they do.
- Stage 1 — Lexing: The source code is broken into tokens (keywords, identifiers, operators, literals).
let x: number = 5becomes tokens:let,x,:,number,=,5. This is a mechanical process that fails only on truly malformed input (unclosed strings, invalid characters). - Stage 2 — Parsing: Tokens are assembled into an Abstract Syntax Tree (AST). The parser understands JavaScript and TypeScript grammar — it knows that
let x: number = 5is a variable declaration with a type annotation. Syntax errors are caught here: missing semicolons, unmatched brackets, invalid expression structure. - Stage 3 — Type Checking: This is where TypeScript earns its keep. The type checker walks the AST and validates that every operation is type-safe. It resolves type references, checks assignment compatibility, infers types where annotations are missing, and reports the “red squiggle” errors you see in your IDE. This stage uses TypeScript’s structural type system, control flow analysis, and all the advanced type features (conditional types, mapped types, generics). This is by far the most computationally expensive stage.
- Stage 4 — Emitting: The typed AST is transformed into JavaScript. All type annotations, interfaces, type aliases, and enums (for
const enum) are stripped. The output is plain JavaScript that any runtime can execute. The emitter also generates.d.tsdeclaration files and source maps if configured.
if (x instanceof MyType) does not work for interfaces because interfaces do not exist at runtime. You need runtime type guards (typeof, instanceof for classes, or custom validation functions).Follow-up: If type checking is the expensive stage, how do large projects manage compilation performance?Three strategies. First, --incremental mode: TypeScript caches the AST and type information from the previous compilation and only re-checks files that changed. This can reduce rebuild times from 30 seconds to under 2 seconds for a large project. Second, Project References with --build mode: split a monorepo into smaller sub-projects that are compiled independently. A change in packages/ui does not re-check packages/server. Third, tools like esbuild or swc that skip type checking entirely and only do Stage 1, 2, and 4 (lexing, parsing, emitting). They rely on tsc --noEmit running separately (often in CI) to catch type errors. This gives you sub-second build times during development while still catching type errors before merge.