TypeScript Snippets
About TypeScript
TypeScript adds a static type system to JavaScript, helping you catch mistakes earlier and design better APIs. This track covers core types and a small project pattern.
Initialize a TypeScript Project
Create a project and install TypeScript compiler tooling.
mkdir ts-lab
cd ts-lab
npm init -y
npm install -D typescript tsx @types/node
npx tsc --initRecommended tsconfig for Learning
Enable strict mode early so type feedback is useful from day one.
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"strict": true,
"noUncheckedIndexedAccess": true,
"outDir": "dist"
},
"include": ["src"]
}Model Domain Data with Types and Interfaces
Use aliases for unions and interfaces for object shapes.
type ExpenseCategory = 'food' | 'travel' | 'tools'
interface Expense {
id: string
description: string
amount: number
category: ExpenseCategory
}
const sample: Expense = {
id: 'e1',
description: 'Keyboard',
amount: 89,
category: 'tools'
}Generic Helper for API Results
Generics let one utility function stay type-safe for many response shapes.
type Result<T> =
| { ok: true; data: T }
| { ok: false; error: string }
async function toResult<T>(promise: Promise<T>): Promise<Result<T>> {
try {
return { ok: true, data: await promise }
} catch (error) {
return { ok: false, error: (error as Error).message }
}
}Discriminated Union for Command Parsing
Use command tags to safely branch business logic.
type Command = { type: 'add'; text: string } | { type: 'list' } | { type: 'remove'; id: string }
function run(command: Command) {
switch (command.type) {
case 'add':
return `adding ${command.text}`
case 'remove':
return `removing ${command.id}`
case 'list':
return 'listing'
}
}Type Guard for Unknown JSON
Validate unknown values from files or APIs before trusting their shape.
interface User {
id: number
name: string
}
function isUser(value: unknown): value is User {
return typeof value === 'object' && value !== null &&
typeof (value as User).id === 'number' &&
typeof (value as User).name === 'string'
}Mini Project: Expense Store with Typed Reducer
Small project idea: build a typed expense tracker core you can reuse in React, Node, or tests.
interface Expense { id: string; description: string; amount: number }
type Action = { type: 'expense/added'; expense: Expense } | { type: 'expense/removed'; id: string }
function expenseReducer(state: Expense[], action: Action): Expense[] {
switch (action.type) {
case 'expense/added':
return [...state, action.expense]
case 'expense/removed':
return state.filter((expense) => expense.id !== action.id)
}
}Typed Fetch Function
Create one reusable fetch wrapper with a typed return value.
async function getJson<T>(url: string): Promise<T> {
const response = await fetch(url)
if (!response.ok) throw new Error(`Request failed: ${response.status}`)
return (await response.json()) as T
}
type Post = { id: number; title: string }
getJson<Post[]>('https://jsonplaceholder.typicode.com/posts').then(console.log)Run Type Checks and Execute Files
Use tsc for static checks and tsx for fast local execution.
npx tsc --noEmit
npx tsx src/index.ts
npx tscNext Learning Upgrades
Move from language fundamentals to architecture-level usage.
1. Add zod schemas and infer TS types from them.
2. Add utility types for API response normalization.
3. Add strict lint rules for unsafe any usage.
4. Add contract tests for typed clients.
5. Add monorepo packages with shared TypeScript types.