js-ts-fp

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Functional Programming Engineering Skill

函数式编程工程实践指南

Write and review code using functional programming principles like a top engineer.
像顶级工程师一样,运用函数式编程原则编写和评审代码。

Workflow

工作流程

Step 1: Analyze the Codebase

步骤1:分析代码库

Before writing or reviewing any code, examine the repository:
  1. Confirm TypeScript or JavaScript: Check for
    .ts
    ,
    .tsx
    ,
    .js
    ,
    .jsx
    files and
    package.json
  2. Find existing patterns: Look at 2-3 representative files to understand current conventions
  3. Check tsconfig.json: Note strict mode, module system, and target ES version
在编写或评审任何代码之前,先检查代码仓库:
  1. 确认是TypeScript还是JavaScript:检查是否存在
    .ts
    .tsx
    .js
    .jsx
    文件以及
    package.json
  2. 查找现有模式:查看2-3个具有代表性的文件,以了解当前的约定
  3. 检查tsconfig.json:注意严格模式、模块系统和目标ES版本

Step 2: Apply FP Principles

步骤2:应用函数式编程(FP)原则

Apply these principles (all natively supported in TS/JS):
PrincipleDescription
Pure functionsNo side effects, same input → same output
ImmutabilityNever mutate, always return new values
Declarative styleDescribe what, not how
Function compositionBuild complex from simple functions
Higher-order functionsFunctions that take/return functions
Avoid shared stateNo globals, no mutation of external state
Discriminated unionsTypeScript pattern matching alternative
应用以下原则(所有原则均被TS/JS原生支持):
原则描述
纯函数无副作用,相同输入始终返回相同输出
不可变性绝不修改原有值,始终返回新值
声明式风格描述要做什么,而非具体怎么做
函数组合用简单函数构建复杂函数
高阶函数接收或返回函数的函数
避免共享状态无全局变量,不修改外部状态
可辨识联合TypeScript的模式匹配替代方案

Step 3: Execute Task

步骤3:执行任务

Writing new code:
  • Follow existing repo conventions for file structure and naming
  • Use FP patterns consistent with what's already in the codebase
  • If no FP patterns exist, introduce them gradually and idiomatically
Reviewing code:
  • Identify imperative patterns that could be functional
  • Flag mutation, side effects, shared state
  • Suggest specific refactors with before/after examples
Refactoring:
  • Preserve behavior while improving structure
  • Transform loops → map/filter/reduce
  • Extract pure functions from impure ones
  • Isolate side effects to boundaries
编写新代码:
  • 遵循代码仓库现有的文件结构和命名约定
  • 使用与代码库中现有模式一致的FP模式
  • 如果代码库中没有FP模式,逐步且自然地引入
评审代码:
  • 识别可转换为函数式风格的命令式模式
  • 标记修改操作、副作用和共享状态
  • 提供包含前后示例的具体重构建议
重构代码:
  • 在改进代码结构的同时保留原有功能
  • 将循环转换为map/filter/reduce
  • 从非纯函数中提取纯函数
  • 将副作用隔离到边界层

Core FP Transformations

核心FP转换示例

Imperative → Declarative

命令式 → 声明式

// Before: imperative loop
let results = [];
for (let i = 0; i < items.length; i++) {
  if (items[i].active) {
    results.push(transform(items[i]));
  }
}

// After: declarative
const results = items
  .filter(item => item.active)
  .map(transform);
// 之前:命令式循环
let results = [];
for (let i = 0; i < items.length; i++) {
  if (items[i].active) {
    results.push(transform(items[i]));
  }
}

// 之后:声明式
const results = items
  .filter(item => item.active)
  .map(transform);

Mutation → Immutability

可变操作 → 不可变性

// Before: mutation
function addItem(cart, item) {
  cart.items.push(item);
  cart.total += item.price;
  return cart;
}

// After: immutable
function addItem(cart, item) {
  return {
    ...cart,
    items: [...cart.items, item],
    total: cart.total + item.price
  };
}
// 之前:可变操作
function addItem(cart, item) {
  cart.items.push(item);
  cart.total += item.price;
  return cart;
}

// 之后:不可变实现
function addItem(cart, item) {
  return {
    ...cart,
    items: [...cart.items, item],
    total: cart.total + item.price
  };
}

Shared State → Pure Functions

共享状态 → 纯函数

// Before: shared state
let counter = 0;
function increment() {
  counter++;
  return counter;
}

// After: pure
function increment(counter) {
  return counter + 1;
}
// 之前:共享状态
let counter = 0;
function increment() {
  counter++;
  return counter;
}

// 之后:纯函数实现
function increment(counter) {
  return counter + 1;
}

Nested Logic → Composition

嵌套逻辑 → 函数组合

// Before: nested
function process(data) {
  const validated = validate(data);
  if (validated) {
    const transformed = transform(validated);
    return format(transformed);
  }
  return null;
}

// After: composed (with pipe/flow)
const process = pipe(
  validate,
  transform,
  format
);
// 之前:嵌套逻辑
function process(data) {
  const validated = validate(data);
  if (validated) {
    const transformed = transform(validated);
    return format(transformed);
  }
  return null;
}

// 之后:组合实现(使用pipe/flow)
const process = pipe(
  validate,
  transform,
  format
);

Detailed Patterns Reference

详细模式参考

For comprehensive patterns including Option/Result types, composition helpers, currying, and TypeScript-specific techniques, see references/patterns.md.
如需了解包括Option/Result类型、组合工具、柯里化以及TypeScript特定技巧在内的完整模式,请查看references/patterns.md

Code Review Checklist

代码评审检查清单

When reviewing, check for:
  • Functions return values (not void/undefined for logic)
  • No mutation of input parameters
  • Side effects isolated and clearly marked
  • Loops replaced with map/filter/reduce where clearer
  • Conditionals use early returns or ternaries for simple cases
  • Complex conditionals extracted to named predicates
  • State transformations are pure
  • Error handling uses Result/Either/Option patterns when available
评审代码时,请检查以下内容:
  • 函数返回值(逻辑代码不返回void/undefined)
  • 不修改输入参数
  • 副作用被隔离并清晰标记
  • 循环在更清晰的情况下被替换为map/filter/reduce
  • 简单条件使用提前返回或三元表达式
  • 复杂条件被提取为命名谓词
  • 状态转换是纯函数
  • 错误处理在可用时使用Result/Either/Option模式

Anti-Patterns to Flag

需要标记的反模式

Anti-PatternRefactor To
for
loop with push
map
/
filter
/
reduce
let
with reassignment
const
with transformation
Nested callbacksComposition or async/await
null
checks everywhere
Option/Maybe type
try/catch
everywhere
Result/Either type
Class with mutable statePure functions + data
Global variablesDependency injection
if/else
chains
Pattern matching or lookup tables
反模式重构方向
带push的
for
循环
map
/
filter
/
reduce
带重新赋值的
let
带转换的
const
嵌套回调函数组合或async/await
到处都是
null
检查
Option/Maybe类型
到处都是
try/catch
Result/Either类型
带可变状态的类纯函数 + 数据
全局变量依赖注入
if/else
模式匹配或查找表

When NOT to Apply FP

不适用于函数式编程的场景

  • Performance-critical hot paths where mutation is measurably faster
  • When the team/codebase has no FP experience (introduce gradually)
  • Simple scripts where FP adds complexity without benefit
  • When existing patterns in the repo are intentionally imperative
  • Legacy codebases where consistency matters more than FP purity
  • 性能关键的热路径,其中可变操作的速度明显更快
  • 团队/代码库没有函数式编程经验时(逐步引入)
  • 简单脚本,函数式编程会增加复杂度而无收益
  • 代码库现有模式有意采用命令式风格时
  • 遗留代码库,一致性比函数式编程纯度更重要时