Building Type-Safe APIs with Nuxt 3 and Prisma
Learn how to build end-to-end type-safe APIs using Nuxt 3 server routes and Prisma ORM for a seamless developer experience.
Apply functional programming principles to everyday JavaScript: immutability, pure functions, composition, and practical uses of map/filter/reduce.
Mbeah Essilfie
May 18, 2026 at 06:04 AM
You don't need monads or category theory to benefit from functional programming. Start with three principles: pure functions, immutability, and composition.
A pure function: same input → same output, no side effects.
// ❌ Impure — depends on external state
let taxRate = 0.2
function calculatePrice(amount: number) {
return amount * (1 + taxRate) // relies on external variable
}
// ✅ Pure — all inputs explicit
function calculatePrice(amount: number, taxRate: number) {
return amount * (1 + taxRate)
}
Why it matters: pure functions are trivial to test, cache, and parallelize.
Never mutate — create new values:
// ❌ Mutation
function addItem(cart: Item[], item: Item) {
cart.push(item) // modifies the original!
return cart
}
// ✅ Immutable
function addItem(cart: Item[], item: Item): Item[] {
return [...cart, item] // new array
}
// ✅ For objects
function updateUser(user: User, changes: Partial<User>): User {
return { ...user, ...changes }
}
Build complex operations from simple ones:
const pipe = <T>(...fns: Array<(arg: T) => T>) =>
(value: T): T =>
fns.reduce((acc, fn) => fn(acc), value)
const processText = pipe(
(s: string) => s.trim(),
(s: string) => s.toLowerCase(),
(s: string) => s.replace(/\s+/g, '-'),
(s: string) => s.replace(/[^a-z0-9-]/g, ''),
)
processText(' Hello World! ') // → "hello-world"
interface Order {
id: string
items: Array<{ price: number; quantity: number }>
status: 'pending' | 'shipped' | 'delivered'
createdAt: Date
}
function getMonthlyRevenue(orders: Order[], month: number): number {
return orders
.filter(order => order.status !== 'pending')
.filter(order => order.createdAt.getMonth() === month)
.flatMap(order => order.items)
.reduce((total, item) => total + item.price * item.quantity, 0)
}
Functions that take or return functions:
// Retry wrapper
function withRetry<T>(fn: () => Promise<T>, attempts = 3): () => Promise<T> {
return async () => {
for (let i = 0; i < attempts; i++) {
try {
return await fn()
} catch (e) {
if (i === attempts - 1) throw e
await new Promise(r => setTimeout(r, 1000 * (i + 1)))
}
}
throw new Error('Unreachable')
}
}
const fetchWithRetry = withRetry(() => fetch('/api/data'))
FP is a tool, not a religion. Use it where it makes code clearer and more reliable.
Fullstack Software Developer
Learn how to build end-to-end type-safe APIs using Nuxt 3 server routes and Prisma ORM for a seamless developer experience.
Go beyond basic utility classes and learn how to build cohesive, maintainable design systems with Tailwind CSS.
Understand the power of Vue 3's Composition API through practical, real-world composable patterns that you can use today.
