Skip to content

JavaScript and TypeScript Course Curriculum

This course is a sequence of long-form technical articles for an experienced developer who can already read JavaScript but wants enough command of its syntax, semantics, environments, conventions, and ecosystem to write JavaScript and TypeScript confidently.

The course begins with JavaScript as a runtime language. TypeScript is added only after the JavaScript object model, modules, errors, and asynchronous execution are familiar. Browser programming comes before React so JSX, TSX, framework behavior, and Web APIs remain distinguishable.

The writing style is defined in ARTICLE_GUIDE.md. The article-review and maintenance approach is described in TOOLCHAIN.md.

Learning format

The entire learning experience is a connected collection of articles with examples embedded directly in the prose. Articles should feel like strong chapters in a technical book rather than standardized lessons.

There are no assignments, per-article exercises, external example files, prediction worksheets, or completion checklists. Readers may type and modify examples when curiosity calls for it, but the course does not require project work to progress.

When several concepts need to be seen together, an article can develop an extended case study through a sequence of embedded snippets. The prose remains responsible for explaining the design, the tradeoffs, and how the parts interact.

Course shape

The course has six parts and twenty-one planned articles:

  1. JavaScript as a language and runtime
  2. Values, functions, objects, and collections
  3. Modules, errors, and asynchronous programs
  4. TypeScript
  5. Browser JavaScript
  6. JSX, TSX, React, and the broader ecosystem

The article list is a content plan rather than a promise that every heading becomes exactly one file. Closely related articles may be combined during writing, and an unusually dense topic may be divided.


Part 1: JavaScript as a language and runtime

Article 1: What JavaScript actually is

This opening article establishes the layers routinely conflated under the word “JavaScript.”

It covers:

  • ECMAScript as the language.
  • Engines such as V8, JavaScriptCore, and SpiderMonkey.
  • Host environments such as browsers, Node.js, Bun, and Deno.
  • Host-provided globals and APIs.
  • Libraries and frameworks.
  • JavaScript versus TypeScript, JSX, and TSX.
  • How to identify which layer owns an unfamiliar construct.

The reader should leave able to ask the right documentation and compatibility question when encountering an API.

Article 2: Running JavaScript

This article explains the practical path from a source file to a running program.

It covers:

  • Running a file and using a REPL.
  • Node.js as the course's baseline environment.
  • Browser scripts and modules at a conceptual level.
  • Command-line arguments, standard input, standard output, and process exit.
  • package.json, package scripts, and the meaning of "type": "module".
  • Dependencies, development dependencies, and lockfiles.
  • Why a package manager, runtime, compiler, test runner, and bundler are separate roles even when one product combines them.
  • A first comparison of Node.js and Bun.

Part 2: Values, functions, objects, and collections

Article 3: Values, variables, and everyday syntax

This is a compact tour of the syntax needed to begin writing modern JavaScript.

It covers:

  • Statements and expressions.
  • const, let, and recognition of var.
  • Primitive types.
  • Template literals.
  • Arithmetic, comparison, conditional, and logical operators.
  • Blocks and basic control flow.
  • for, for...of, and recognition of for...in.
  • Function calls and property access.
  • Optional chaining and nullish coalescing at an introductory level.

The article moves quickly through familiar constructs and slows down for JavaScript-specific semantics: number, NaN, infinities, negative zero, null, undefined, and the difference between a constant binding and immutable data.

Article 4: Equality, coercion, and absence

This article develops the rules that frequently cause subtle boundary and configuration bugs.

It covers:

  • Strict equality and inequality.
  • Recognition and limited intentional uses of loose equality.
  • Object identity.
  • Truthy and falsy values.
  • Logical operators returning operands.
  • || versus ??.
  • Explicit conversion with String, Number, and Boolean.
  • typeof, Array.isArray, Number.isNaN, and Number.isFinite.
  • Choosing a representation for missing, empty, and invalid values.

Examples use configuration, form, and JSON-like data rather than isolated coercion puzzles.

Article 5: Objects, arrays, maps, and sets

This article explains JavaScript's everyday data structures as a connected toolkit.

It covers:

  • Object and array literals.
  • Reference identity and mutation.
  • Dot and bracket property access.
  • Computed properties and property shorthand.
  • Destructuring.
  • Rest and spread syntax.
  • Shallow copying and aliasing.
  • Array iteration and transformation methods.
  • Map and Set.
  • When a plain object is a record and when Map is a better collection.
  • Enumeration with Object.keys, Object.values, Object.entries, and Object.fromEntries.
  • Immutability as a design choice rather than an automatic language guarantee.

The article discusses readability tradeoffs between loops and chains of map, filter, flatMap, and reduce without presenting functional-looking code as inherently superior.

Article 6: Functions, scope, and closures

This article treats functions as the center of ordinary JavaScript design.

It covers:

  • Function declarations, expressions, and arrow functions.
  • Parameters, defaults, rest parameters, and return values.
  • Functions as values.
  • Callbacks and higher-order functions.
  • Lexical scope and block scope.
  • Closures and captured bindings.
  • Hoisting and the temporal dead zone to the extent needed for real code.
  • Module-private and closure-private state.
  • When a closure factory is simpler than a class.

Article 7: this, prototypes, and classes

This article explains JavaScript's object model without making prototypes seem mystical or requiring manual prototype programming for everyday work.

It covers:

  • How call form determines this for ordinary functions.
  • Why extracting a method can lose its receiver.
  • Lexical this in arrow functions.
  • call, apply, and bind for recognition and occasional use.
  • Prototype-based property lookup.
  • Classes as syntax over prototype delegation.
  • Constructors, instance methods, static members, inheritance, and super.
  • Public fields and #private fields.
  • Composition, classes, plain objects, and closure factories as design options.

Part 3: Modules, errors, and asynchronous programs

Article 8: Modules and program structure

This article should explain ECMAScript modules as both syntax and an architectural boundary.

It should cover:

  • Named and default exports.
  • Static imports, dynamic imports, and re-exports.
  • Module scope and live bindings.
  • Entry points and public APIs.
  • Relative resolution and file extensions.
  • Circular dependencies.
  • Side effects during module evaluation.
  • Separating domain logic from environment adapters.
  • CommonJS recognition and interoperability without using it as the course default.
  • File and directory naming conventions.
  • How much structure a small program actually needs.

An extended reporting-program case study can gradually separate parsing, domain behavior, formatting, and an executable entry point entirely within the article.

Article 9: Errors, validation, and boundaries

This article should distinguish different failure categories rather than presenting try and catch as generic error handling.

It should cover:

  • Throwing and catching.
  • Error, subclasses, stacks, and cause.
  • Cleanup with finally.
  • Programmer errors versus expected invalid input.
  • Exceptions versus result objects.
  • Adding context while preserving the original failure.
  • Designing errors at filesystem, network, parsing, and domain boundaries.
  • Testing failure behavior conceptually.

The reporting case study can demonstrate why static expectations never make external JSON valid by themselves.

Article 10: Promises and asynchronous control flow

This article explains promises from their semantics upward rather than treating async and await as magical syntax.

It should cover:

  • Callbacks and completion.
  • Promise states and chaining.
  • Resolution, rejection, and flattening.
  • async functions and await.
  • Sequential versus concurrent work.
  • Promise.all, allSettled, race, and any.
  • Error propagation.
  • Avoiding unnecessary promise construction.
  • Common missing-return and unhandled-rejection bugs.

Examples should make work-start timing visible and distinguish creating a promise from awaiting it.

Article 11: The event loop, cancellation, and async design

This article develops the execution model needed to reason about real asynchronous programs.

It should cover:

  • The call stack.
  • Tasks and microtasks.
  • Timers and promise callbacks.
  • Event-loop ordering.
  • Single-threaded concurrency and race conditions.
  • AbortController and AbortSignal.
  • Timeouts, retries, and cleanup.
  • Concurrency limits.
  • Async iterables and streams at an introductory level.
  • When worker threads or another form of parallelism would actually be relevant.

A bounded job-processor case study can integrate concurrency limits, stable results, cancellation, retry, and progress callbacks without becoming a reader assignment.


Part 4: TypeScript

Article 12: What TypeScript adds—and what it cannot add

This article introduces TypeScript as a static model layered over JavaScript.

It should cover:

  • Type inference and annotations.
  • Type erasure.
  • Primitive, object, array, tuple, and function types.
  • Optional and read-only properties.
  • any, unknown, never, and void.
  • Type assertions and why they do not validate data.
  • The relationship between .js, .ts, compiled output, and direct type stripping.
  • The role of tsconfig.json.

The central theme is that JavaScript runtime knowledge remains necessary. TypeScript should sharpen that knowledge rather than conceal it.

Article 13: Structural types and narrowing

This article develops TypeScript's everyday modeling tools.

It should cover:

  • Type aliases and interfaces.
  • Structural compatibility.
  • Union and intersection types.
  • Literal types.
  • Control-flow narrowing.
  • typeof, instanceof, property checks, and equality narrowing.
  • Discriminated unions.
  • Exhaustive switches and never.
  • Type predicates and assertion functions.
  • Modeling states instead of accumulating optional fields and boolean flags.

Examples should follow external data through validation into a trusted internal model and show a state machine represented by a discriminated union.

Article 14: Generics and type relationships

This article should explain generics as relationships between types rather than placeholder syntax.

It should cover:

  • Generic functions and object types.
  • Inference.
  • Constraints.
  • keyof, indexed access, and typeof in type positions.
  • Mapped and conditional types.
  • Standard utility types.
  • Template literal types where genuinely useful.
  • Reading library signatures.
  • Recognizing over-generalized or unnecessarily clever types.

The examples can progress from a generic collection helper to a typed message map where names determine payload and result types.

Article 15: TypeScript projects and library boundaries

This article covers the mechanics required to work in real TypeScript repositories.

It should cover:

  • Important tsconfig options.
  • Target versus runtime.
  • Module format versus module resolution.
  • Strictness options.
  • Type-only imports.
  • Declaration files and @types packages.
  • Application noEmit workflows versus compiling a distributable library.
  • Source maps.
  • Interoperating with JavaScript and CommonJS packages.
  • Runtime validation libraries as an ecosystem concept without making one mandatory.

A typed message-processing library can serve as the integrated case study, including public types, runtime validation, declaration output, and consumer usage.


Part 5: Browser JavaScript

Article 16: The browser as a JavaScript host

This article reuses the opening language-versus-host model in a browser context.

It should cover:

  • HTML and the DOM tree.
  • Selecting, creating, changing, and removing elements.
  • Attributes versus properties.
  • Text insertion versus HTML insertion.
  • Events, bubbling, capturing, and delegation.
  • Forms and FormData.
  • Focus, keyboard interaction, and basic accessibility.
  • Browser developer tools.
  • Browser module loading.

Examples should build one small interface progressively within the article rather than scattering unrelated DOM snippets.

Article 17: Browser data, networking, and state

This article should cover:

  • fetch, requests, responses, and status handling.
  • JSON boundaries and validation.
  • URLs and query parameters.
  • Cancellation and stale requests.
  • Same-origin policy and CORS conceptually.
  • localStorage, session storage, and IndexedDB at the appropriate depth.
  • Loading, empty, error, and stale states.
  • Keeping URL, persistent preference, and in-memory state distinct.

A framework-free searchable catalog can grow through the article as an integrated case study, connecting data loading, filtering, URL state, persistence, and accessible interactions.


Part 6: JSX, TSX, React, and the ecosystem

Article 18: JSX and component rendering

This article should carefully separate several layers:

  • JavaScript expressions.
  • TypeScript annotations.
  • JSX syntax.
  • React component conventions.
  • Browser DOM behavior.

It should cover:

  • JSX as transformed syntax.
  • Elements, components, props, and children.
  • JSX differences from HTML.
  • Expressions inside markup.
  • Conditional and list rendering.
  • Keys.
  • Component composition.
  • Pure rendering.
  • How JSX ultimately becomes JavaScript values and calls.

The article should occasionally classify parts of a TSX snippet by layer, but it should remain a narrative rather than a worksheet.

Article 19: React state, events, and effects

This article should cover:

  • Rendering and state snapshots.
  • State updates, including updates based on previous state.
  • Controlled inputs.
  • Lifting and deriving state.
  • Immutable updates.
  • Event handling.
  • Effects as synchronization with external systems.
  • Dependency arrays, cleanup, and stale closures.
  • Refs.
  • Recognizing when an effect is unnecessary.

Any comparison with SwiftUI should be limited to places where superficial similarity could produce the wrong model.

Article 20: Typed React and application structure

This article should cover:

  • Typing component props and events.
  • Optional, conditional, and discriminated-union props.
  • children.
  • Generic components where they preserve a useful relationship.
  • Context at an introductory level.
  • API boundaries and runtime validation.
  • Component tests and user-oriented queries conceptually.
  • Client rendering, server rendering, static generation, and server components conceptually.
  • The difference between React itself and a full-stack React framework.

The framework-free catalog from Part 5 can be revisited in React and TSX so the article can compare what remains ordinary language and browser logic with what the framework changes.

Article 21: The modern JavaScript toolchain

This final article places the surrounding tools into a coherent map.

It should cover:

  • npm, pnpm, and Bun's package manager.
  • Semantic versioning and lockfiles.
  • ESLint and type-aware linting.
  • Prettier.
  • Vitest and Node's test runner.
  • Testing Library and browser automation.
  • Vite, bundling, source maps, tree shaking, and code splitting.
  • Workspaces.
  • CI.
  • How to choose a runtime and toolchain for a CLI, library, browser application, full-stack application, or short script.

Tools should be introduced as solutions to specific problems, not as a checklist every project must adopt.


Approximate pacing

PartEstimated reading and exploration
JavaScript and runtime foundations5–7 hours
Values, functions, and objects14–20 hours
Modules and asynchronous programs10–15 hours
TypeScript12–18 hours
Browser JavaScript7–10 hours
React, TSX, and ecosystem12–18 hours

The course should be maintained as a continuous sequence. Revisions should check for repetition, missing transitions, and examples that accidentally assume material from a later article.

Last updated: