TypeScript for JavaScript Developers Quickstart Workbook (2025)
Date: September 12, 2025
How to use this workbook Read a section, then complete the exercises at the end. An answer
key follows after the exercises.
1) Setup
- Install: `npm i -D typescript ts-node @types/node`
- Init: `npx tsc --init` (set `strict: true`, `target: ES2022`, `module: ESNext`)
2) Types & Interfaces
- Primitives, arrays, tuples, enums, unions, intersections.
type Id = string | number;
interface User { id: Id; name: string; email?: string }
3) Functions & Generics
function last<T>(arr: T[]): T | undefined { return arr.at(-1); }
function mapIds<T extends {id: unknown}>(rows: T[]): unknown[] { return rows.map(r =>
r.id); }
4) Narrowing & Control Flow
function toPx(x: number | string): string {
if (typeof x === 'number') return `${x}px`;
const n = Number(x); return Number.isFinite(n) ? `${n}px` : '0px';
}
5) Utility Types & Mapped Types
type ReadonlyUser = Readonly<User>;
type PartialBy<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
6) Modules & Project Structure
- Use path aliases; isolate domain models; avoid circular deps.
7) Interop with JS
- JSDoc types for gradual typing; `checkJs` mode.
8) Exercises
A. Define a `Result<T>` type with `{ok:true, value:T}` or `{ok:false, error:string}` and write
© Workbook Exercises + Answers | Page 1/2
TypeScript for JavaScript Developers Quickstart Workbook (2025)
a function `parseJSON` that returns `Result<unknown>`.
B. Create a `Paginated<T>` type and a function `paginate<T>(items: T[], size: number)`.
C. Write a generic `memoize` with a cache key function.
D. Add a `Brand<K, T>` type and brand a `UserId`.
Answer Key (sample solutions)
type Result<T> = {ok:true; value:T} | {ok:false; error:string};
function parseJSON(s: string): Result<unknown> {
try { return {ok:true, value: JSON.parse(s)}; }
catch (e) { return {ok:false, error: e instanceof Error ? e.message : 'parse error'};
}
}
type Paginated<T> = {pages: T[][], pageSize: number};
function paginate<T>(items: T[], size: number): Paginated<T> {
const pages: T[][] = [];
for (let i=0;i<items.length;i+=size) pages.push(items.slice(i, i+size));
return {pages, pageSize: size};
}
function memoize<A extends unknown[], R>(fn: (...a:A)=>R,
key=(...a:A)=>JSON.stringify(a)) {
const cache = new Map<string, R>();
return (...a:A) => {
const k = key(...a);
if (cache.has(k)) return cache.get(k) as R;
const v = fn(...a); cache.put ? cache.put(k, v) : cache.set(k, v);
return v;
};
}
// Branding
type Brand<K, T> = K & {__brand: T};
type UserId = Brand<string, 'UserId'>;
© Workbook Exercises + Answers | Page 2/2