Skip to main content Instalar con Codex o Claude Copia este prompt, pégalo en Codex, Claude u otro asistente, y deja que revise la página de la skill y la instale por ti.
Un comando directo omite el prompt de revisión. Revisa el origen antes de ejecutarlo.
npx skills add https://github.com/aiskillstore/marketplace --skill functional-patternsEl comando permanece en una sola línea. Desplázate horizontalmente para revisarlo antes de copiarlo.
¿Prefieres una copia local? Descarga los archivos que SkillsMP tiene disponibles ahora.
Ocupaciones relacionadasSOC
Basado en la clasificación ocupacional SOC
Explorador de archivos
2 archivos| name | functional-patterns |
| description | Functional programming patterns that promote testability, composability, and maintainability. |
Functional Patterns for Node.js/TypeScript
Overview
Functional programming patterns that promote testability, composability, and maintainability.
Pure Functions
Definition
A pure function:
- Always returns the same output for the same input
- Has no side effects (no I/O, no mutation)
Examples
const add = (a: number, b: number): number => a + b;
const calculateTotal = (items: OrderItem[]): number =>
items.reduce((sum, item) => sum + item.price * item.quantity, 0);
const filterActiveUsers = (users: User[]): User[] =>
users.filter((user) => user.isActive);
saveUser = (: ): <> => {
database.(user);
};
logMessage = (: ): {
.(msg);
};
generateId = (): {
crypto.();
};
const
async
user
User
Promise
void
await
save
const
msg
string
void =>
console
log
const
string =>
return
randomUUID
Pure Core, Impure Shell
const validateOrder = (order: Order): Result<Order, ValidationError> => {
if (!order.items.length) return Result.fail({ code: 'EMPTY_ORDER' });
if (order.total < 0) return Result.fail({ code: 'INVALID_TOTAL' });
return Result.ok(order);
};
const calculateDiscount = (order: Order, user: User): number => {
const baseDiscount = user.isPremium ? 0.15 : 0;
const volumeDiscount = order.items.length > 10 ? 0.05 : 0;
return baseDiscount + volumeDiscount;
};
const applyDiscount = (order: Order, discountRate: number): Order => ({
...order,
total: order.total * (1 - discountRate),
});
const processOrderHandler = (deps: Dependencies) => async (order: Order) => {
const validation = validateOrder(order);
if (validation.isFailure) return validation;
const user = await deps.userRepo.findById(order.userId);
const discount = calculateDiscount(validation.value, user);
const discounted = applyDiscount(validation.value, discount);
await deps.orderRepo.save(discounted);
await deps.notifier.send(user.email, 'Order confirmed');
return Result.ok(discounted);
};
Immutability
Immutable Updates
const addItemToCart = (cart: Cart, item: Item) => {
cart.items.push(item);
cart.total += item.price;
return cart;
};
const addItemToCart = (cart: Cart, item: Item): Cart => ({
...cart,
items: [...cart.items, item],
total: cart.total + item.price,
});
const updateUserAddress = (user: User, address: Partial<Address>): User => ({
...user,
address: {
...user.address,
...address,
},
});
type ReadonlyUser = {
readonly id: string;
readonly email: string;
readonly addresses: readonly Address[];
};
const addItem = <T>(arr: readonly T[], item: T): readonly T[] => [...arr, item];
const removeAt = <T>(arr: readonly T[], index: number): readonly T[] =>
arr.filter((_, i) => i !== index);
const updateAt = <T>(arr: readonly T[], index: number, item: T): readonly T[] =>
arr.map((existing, i) => (i === index ? item : existing));
Function Composition
Pipe and Compose
type Fn<A, B> = (a: A) => B;
const pipe = <A, B, C>(
f: Fn<A, B>,
g: Fn<B, C>
): Fn<A, C> => (a) => g(f(a));
const pipe3 = <A, B, C, D>(
f: Fn<A, B>,
g: Fn<B, C>,
h: Fn<C, D>
): Fn<A, D> => (a) => h(g(f(a)));
const processInput = pipe3(
trim,
toLowerCase,
validateEmail
);
const pipeAll = <T>(...fns: Array<(x: T) => T>) =>
(initial: T): T => fns.reduce((acc, fn) => fn(acc), initial);
const processString = pipeAll(
(s: string) => s.trim(),
(s: string) => s.toLowerCase(),
(s: string) => s.replace(/\s+/g, '-')
);
Higher-Order Functions
const withLogging = <T extends (...args: any[]) => any>(fn: T) =>
(...args: Parameters<T>): ReturnType<T> => {
console.log('Calling with:', args);
const result = fn(...args);
console.log('Result:', result);
return result;
};
const retry = <T>(
fn: () => Promise<T>,
attempts: number = 3
): Promise<T> =>
fn().catch((error) =>
attempts > 1 ? retry(fn, attempts - 1) : Promise.reject(error)
);
const multiply = (a: number) => (b: number): number => a * b;
const double = multiply(2);
const triple = multiply(3);
const createLogger = (prefix: string) =>
(message: string): void => console.log(`[${prefix}] ${message}`);
const infoLog = createLogger('INFO');
const errorLog = createLogger('ERROR');
Result Pattern (Monadic Error Handling)
Basic Result Type
type Result<T, E> =
| { readonly _tag: 'Ok'; readonly value: T }
| { readonly _tag: 'Err'; readonly error: E };
const ok = <T>(value: T): Result<T, never> => ({ _tag: 'Ok', value });
const err = <E>(error: E): Result<never, E> => ({ _tag: 'Err', error });
const isOk = <T, E>(result: Result<T, E>): result is { _tag: 'Ok'; value: T } =>
result._tag === 'Ok';
const isErr = <T, E>(result: Result<T, E>): result is { _tag: 'Err'; error: E } =>
result._tag === 'Err';
Result Operations
const map = <T, U, E>(
result: Result<T, E>,
fn: (value: T) => U
): Result<U, E> =>
isOk(result) ? ok(fn(result.value)) : result;
const mapError = <T, E, F>(
result: Result<T, E>,
fn: (error: E) => F
): Result<T, F> =>
isErr(result) ? err(fn(result.error)) : result;
const flatMap = <T, U, E>(
result: Result<T, E>,
fn: (value: T) => Result<U, E>
): Result<U, E> =>
isOk(result) ? fn(result.value) : result;
const match = <T, E, R>(
result: Result<T, E>,
handlers: { ok: (value: T) => R; err: (error: E) => R }
): R =>
isOk(result) ? handlers.ok(result.value) : handlers.err(result.error);
Chaining Results
type ValidationError = { field: string; message: string };
type ProcessingError = { code: string; details: string };
type AppError = ValidationError | ProcessingError;
const validateInput = (input: unknown): Result<ValidInput, ValidationError> => {
};
const processData = (input: ValidInput): Result<ProcessedData, ProcessingError> => {
};
const formatOutput = (data: ProcessedData): Output => {
};
const handleRequest = (input: unknown): Result<Output, AppError> => {
const validated = validateInput(input);
if (isErr(validated)) return validated;
const processed = processData(validated.value);
if (isErr(processed)) return processed;
return ok(formatOutput(processed.value));
};
const handleRequestFunctional = (input: unknown): Result<Output, AppError> =>
flatMap(validateInput(input), (valid) =>
map(processData(valid), formatOutput)
);
Option/Maybe Pattern
type Option<T> =
| { readonly _tag: 'Some'; readonly value: T }
| { readonly _tag: 'None' };
const some = <T>(value: T): Option<T> => ({ _tag: 'Some', value });
const none: Option<never> = { _tag: 'None' };
const isSome = <T>(opt: Option<T>): opt is { _tag: 'Some'; value: T } =>
opt._tag === 'Some';
const isNone = <T>(opt: Option<T>): opt is { _tag: 'None' } =>
opt._tag === 'None';
const mapOption = <T, U>(opt: Option<T>, fn: (value: T) => U): Option<U> =>
isSome(opt) ? some(fn(opt.value)) : none;
const getOrElse = <T>(opt: Option<T>, defaultValue: T): T =>
isSome(opt) ? opt.value : defaultValue;
const fromNullable = <T>(value: T | null | undefined): Option<T> =>
value != null ? some(value) : none;
const findUser = (id: string): Option<User> => {
const user = users.find((u) => u.id === id);
return fromNullable(user);
};
const getUserEmail = (id: string): string =>
getOrElse(
mapOption(findUser(id), (user) => user.email),
'unknown@example.com'
);
Dependency Injection via Functions
type Dependencies = {
userRepo: UserRepository;
orderRepo: OrderRepository;
logger: Logger;
clock: () => Date;
};
const createOrderService = (deps: Dependencies) => ({
createOrder: async (data: CreateOrderData): Promise<Result<Order, OrderError>> => {
const user = await deps.userRepo.findById(data.userId);
if (!user) {
return err({ code: 'USER_NOT_FOUND', userId: data.userId });
}
const order: Order = {
id: generateId(),
...data,
createdAt: deps.clock(),
status: 'pending',
};
deps.logger.info({ orderId: order.id }, 'Creating order');
await deps.orderRepo.save(order);
return ok(order);
},
});
describe('OrderService', () => {
it('should create order', async () => {
const deps: Dependencies = {
userRepo: { findById: jest.fn().mockResolvedValue({ id: '1' }) },
orderRepo: { save: jest.fn() },
logger: { info: jest.fn() },
clock: () => new Date('2024-01-01'),
};
const service = createOrderService(deps);
const result = await service.createOrder({ userId: '1', items: [] });
expect(isOk(result)).toBe(true);
});
});