TypeScript 中的函数式编程:从理论到实践
函数式编程(FP)是一种基于函数应用的计算范式,避免状态突变。TypeScript 作为 JavaScript 的严格类型超集,为实施函数式编程提供了强大工具。本文将结合实际代码示例,深入解析 TypeScript 中函数式编程的核心概念。
1. 纯函数与不可变性
纯函数 是一种具备以下特性的函数:
- 对相同参数始终返回相同结果(确定性)
- 无副作用(不修改外部变量,不执行 I/O 操作)
// 纯函数const add = (a: number, b: number): number => a + b;
// 非纯函数(副作用 —— 修改外部状态)let counter = 0;const increment = (): number => ++counter;不可变性 意味着数据不被修改,而是创建新副本。在 TypeScript 中,可以使用展开运算符和非变异方法:
interface User { name: string; age: number;}
// 可变方式(不良实践)const updateAgeMutable = (user: User, newAge: number): void => { user.age = newAge;};
// 不可变方式(良好实践)const updateAgeImmutable = (user: User, newAge: number): User => ({ ...user, age: newAge,});不可变性简化了调试和测试过程,因为数据始终是可预测的。
2. 高阶函数与闭包
高阶函数 是接受其他函数作为参数或返回函数的函数。例如 Array.map 方法:
const numbers: number[] = [1, 2, 3, 4];const doubled: number[] = numbers.map((x) => x * 2);console.log(doubled); // [2, 4, 6, 8]闭包 是一种即使外部函数执行完毕,仍能"记住"其外部作用域变量的函数:
const createMultiplier = (factor: number): ((x: number) => number) => { return (x: number) => x * factor;};
const double = createMultiplier(2);const triple = createMultiplier(3);
console.log(double(5)); // 10console.log(triple(5)); // 15闭包广泛用于创建具有部分参数应用(柯里化)的函数。
3. 函数组合与柯里化
函数组合 是将多个函数合并为一个函数,其中前一个函数的输出作为下一个函数的输入。在 TypeScript 中可以编写组合工具函数:
const compose = <T, R>(...fns: Array<(arg: T) => T>) => (arg: T): T => fns.reduceRight((acc, fn) => fn(acc), arg);
// 示例:字符串转换const toUpperCase = (s: string): string => s.toUpperCase();const exclaim = (s: string): string => `${s}!`;const shout = compose(toUpperCase, exclaim);
console.log(shout("hello")); // "HELLO!"柯里化 是将多参数函数转换为一系列单参数函数的过程:
// 常规函数const add = (a: number, b: number): number => a + b;
// 柯里化版本const curriedAdd = (a: number) => (b: number): number => a + b;
const add5 = curriedAdd(5);console.log(add5(3)); // 8柯里化简化了专用函数的创建,并提升了代码复用性。
4. 单子与 Option/Maybe 的处理
单子是一种函数式编程模式,用于封装值并提供转换接口。最简单的单子之一是 Maybe(或称 Option),它能安全地处理 n