TypeScript函数式编程pipe/compose嵌套map的代码重构问题
为什么嵌套写法可读性差
你现在的代码问题不是函数式编程本身的锅,是把多层map全塞在map的回调里了——读的时候顺着外层pipe走,走两步就得跳进内层嵌套的pipe里看逻辑,反复跳几次之后,根本记不住哪层拆分对应哪个文本粒度,尤其是几个月后回头改代码的时候,光数嵌套括号就得花十分钟。
完全可以通过几个小调整,把嵌套结构拉成从上到下的线性流程,一点不损失函数式编程的写法优势。
具体优化方向
1. 把嵌套的map从内层回调提到外层流程
借助函数式编程里map的柯里化特性,不需要把多层map塞在回调的pipe里,完全可以顺着数组层级在外层依次叠加map,整个流程没有任何嵌套的pipe块。
原嵌套写法的问题:
// 原写法:map的回调内部嵌套了pipe+map+pipe,流程被反复打断 const parse: $parse = pipe( split("\n\n\n"), map(pipe( split("\n\n"), map(pipe(split("\n"), filter(isNotEmpty))) )) );
拉平后的线性写法:
// 优化后:整个流程是连贯的,没有嵌套pipe块 const parse: $parse = pipe( split("\n\n\n"), // 第一层映射:对最外层按3个换行拆分的大段落,拆成二级小节 map(split("\n\n")), // 第二层映射:对每个二级小节,拆成过滤空行后的有效行 map(map(pipe(split("\n"), filter(isNotEmpty)))) );
刚开始看到
map(map(...))可能会觉得有点绕,其实和返回结构是完全对应的:
- 第一步
split("\n\n\n")得到string[](数组深度1)- 第一个
map(split("\n\n"))把每个字符串拆成小节,数组深度变成2(string[][])- 第二个
map(...)遍历第二层的每个小节块,套内层的map对小节里的每行做拆分过滤,最终数组深度变成3(string[][][]),和你定义的$parse返回值完全对齐。
2. 抽离具名单职责函数,进一步降低认知负担
如果觉得叠两层map还是有点抽象,可以把每一层的拆分逻辑抽成独立的、见名知意的函数,完全去掉流程里的嵌套块:
// 每个函数只做一件事,名字直接说明处理的文本粒度 const splitBlockByTripleNewline = split("\n\n\n"); const splitSectionByDoubleNewline = split("\n\n"); const filterValidLines: (chunk: string) => string[] = pipe( split("\n"), filter(isNotEmpty) ); const parse: $parse = pipe( splitBlockByTripleNewline, map(splitSectionByDoubleNewline), map(map(filterValidLines)) );
哪怕过几个月回头看代码,看到函数名就能立刻知道每一步做了什么,不需要回头翻拆分规则。
3. 借TS类型约束减少结构错配
因为你已经提前定义了$parse的返回类型是string[][][],TS会自动校验你写的流程的类型是不是匹配——比如你漏写一层map,或者把某个拆分步骤放错了层级,TS会直接报类型不匹配的错误,根本不需要靠记忆数嵌套层级来保证结构正确。
避坑提醒
别为了“消掉嵌套”硬套复杂的数组操作工具(比如自定义链式调用、过度封装的奇技淫巧),你这个场景的逻辑本质是固定层级的文本拆分,拉平成线性流程、抽具名函数的写法,是最直观、后续维护成本最低的方案。
内容的提问来源于stack exchange,提问作者Antonin
相关产品推荐
相关产品推荐

