Last 30 Days
No notifications
You've covered the language. Real fluency now comes from reps and projects. Here's a focused roadmap: type-level puzzles for the type system, refactor projects for the muscle memory, interview classics for offer day, and a curated list of resources that don't waste your time.
If you completed Phases 1–4 you can:
.d.ts files.[github.com/type-challenges/type-challenges](https://github.com/type-challenges/type-challenges) is the gym for the TS type system. Work through them in order:
| Tier | Skill | What you practise |
| Easy (13) | Re-implement utility types | Pick, Readonly, First, Length, Includes |
| Medium (~80) | Mapped + conditional + infer | DeepReadonly, TupleToObject, Chainable |
| Hard (~40) | Recursive types, parser-style | Currying, Get, String to Number |
| Extreme (~10) | Arithmetic at the type level | Yes, you can multiply numbers in the type system |
Goal: finish all 13 Easy + 20 Mediums. After that you've internalised the big ideas.
Pick a 200–500-line JS project of yours (or a small open-source one) and convert it. The pattern:
1. Add tsconfig.json with allowJs: true.
2. Rename one file at a time .js → .ts.
3. Fix errors before moving to the next file.
4. Once everything compiles, turn on strict and clean up.
5. Remove allowJs.
You'll learn:
Pick one mini-project. Each forces you to use a different part of the language:
fetcher(url: string): Promise with zod runtime validation. Practises generics + type narrowing + utility types.class Emitter<T extends Record<string, unknown>> {
on<K extends keyof T>(name: K, fn: (payload: T[K]) => void): void { /* … */ }
emit<K extends keyof T>(name: K, payload: T[K]): void { /* … */ }
}
Practises generic constraints + keyof + indexed access types.z.string().min(3) clone. Practises method chaining with generics, branded types, and inference. Hardest of the four — most rewarding.If you're prepping for jobs, drill these patterns until they're automatic:
| Pattern | What to know |
| Discriminated unions | When and why; exhaustiveness with never |
keyof + indexed access | "Get the type of the value at any key" |
| Generics + constraints | Why matters |
infer in conditionals | Pulling pieces out of function/promise/array types |
Mapped types with as | Generating one shape from another |
| Function overloading | When to use it vs union of params |
unknown vs any | The single most common interview gotcha |
as const | Inferring narrow literal types |
The best TS in the wild:
zod — schema builder. Beautiful inference. Read src/types.ts.tRPC — end-to-end type-safe APIs. Borderline magical types.react-hook-form — generics + paths into nested objects.@tanstack/query — generic, deeply-typed cache.type-fest — a library of utility types worth grepping through when you need one.tsc --noEmit in CI. Always.any. If you must, leave a comment explaining when it can be removed.unknown for parsed JSON until you validate.| Week | Goal |
| 1 | Easy Type-Challenges (all 13) |
| 2 | Convert one JS project to TS |
| 3 | Build the typed event emitter |
| 4 | Medium Type-Challenges (10) |
| 5 | Build the typed REST client + zod |
| 6 | Read zod source for an hour |
| 7 | Medium Type-Challenges (10) |
| 8 | Schema validator mini-project |
Eight weeks of this and you're meaningfully better than 80% of TS developers.
Sixteen topics, four phases, every quiz, every practice link. From here it's all reps. Go ship something typed.