Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >使用 Effect 魔法解锁 TypeScript 的函数式超能力!

使用 Effect 魔法解锁 TypeScript 的函数式超能力!

作者头像
萌萌哒草头将军
发布于 2025-05-12 02:55:50
发布于 2025-05-12 02:55:50
4401
代码可运行
举报
文章被收录于专栏:前端框架前端框架
运行总次数:1
代码可运行

前言

这个周末学习了一个新工具 Effect-TS ,打开我了写代码的新思路,现在迫不及待的分享给大家!

正文

Effect-TS 的核心是一个名为 Effect数据结构,它封装了副作用(例如网络请求、文件操作等),并提供了类型安全的操作方式。Effect 的几个关键特性包括:

  • 🔒 类型安全:通过 TypeScript 的类型推断,确保副作用的输入输出和错误类型明确!
  • 💻 流式(functional)编程风格:将多个操作符或函数按顺序组合起来,使代码更简洁、可读,并且符合函数式编程的理念。
  • 🚀 组合性:Effect 提供了丰富的组合操作符,类似 Lego 积木,让复杂逻辑变得简单。
  • 结构化并发:支持异步任务的取消和资源管理,避免内存泄漏。
  • 错误处理:将错误视为值,允许开发者以声明式的方式处理异常。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Produces a value of type number
         │  Fails with an Error
         │       │ Requires no dependencies
         ▼       ▼      ▼
Effect<number, Error, never>
安装与初始化

首先可以通过以下命令安装 Effect-TS 到你的项目:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
pnpm add effect

Effect-TS 同时提供了一个命令行工具 create-effect-app,可以重新初始化一个新的项目:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
pnpm create effect-app@latest

运行后,工具会引导你选择模板和配置 ESLint 等工具,生成一个预配置好的 Effect 项目!

初始化
初始化

初始化

第一个 Effect 程序
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import { Console, Effect } from "effect";
const main = Console.log("Hello, World!");
Effect.runSync(main);

这里 Console.log 是一个 Effect 操作,Effect.runSync 是同步执行 Effect 的方法。

流式编码风格

pipe 是 Effect 库中用于流式组合操作的核心工具,它通过线性化的方式将 Effect 的操作符和函数连接起来,使代码更简洁、可读且符合函数式编程风格。

代码语言:javascript
代码运行次数:1
运行
AI代码解释
复制
import { Effect } from "effect";

const program = Effect.succeed(42).pipe(
  Effect.map((n) => n * 2),
  Effect.map((n) => n + 10)
);
// 运行后得到:Effect<never, never, 94>
// 解释:42 先被 map 乘以 2 得到 84,再被 map 加上 10 得到 94
丰富的操作符

操作符(Operator)是指一类用于处理、转换或组合数据流(在这里是 Effect 值)的函数或方法。这些操作符通常以声明式的方式操作 Effect 对象,帮助开发者以函数式编程风格管理副作用、异步流程或复杂逻辑。

除了上面提到的 map,还要很多类似数组的操作方法,flatMapzip等等!

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Effect.succeed(10)
  .pipe(Effect.flatMap((n) => Effect.succeed(n + 5))); 
// 结果:Effect<never, never, 15>

通常,我们需要和 pip 配合,将多个操作符组合起来

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import { Effect } from "effect";

const program = Effect.succeed(10).pipe(
  Effect.map((n) => n * 2),
  Effect.flatMap((n) => Effect.succeed(n + 5)),
  Effect.map((n) => `Result: ${n}`)
);
// 结果:Effect<never, never, "Result: 25">
结构化并发

Effect-TS 的结构化并发确保所有异步任务都能被正确管理。例如,运行多个并发请求:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import { Effect } from "effect";

const program = Effect.all([
  getTodo(1),
  getTodo(2),
  getTodo(3)
]).pipe(
  Effect.tap((todos) => Console.log(`Fetched todos: ${JSON.stringify(todos)}`))
);

Effect.runPromise(program);

Effect.all 并行执行多个 Effect,并在所有任务完成时返回结果。如果某个任务失败,Effect 会自动清理其他任务,避免资源泄漏。

处理异步操作

Effect-TS 特别擅长处理异步逻辑。假设我们要从一个 API 获取数据,可以这样实现:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import { Effect, HttpClient } from "effect";

const getTodo = (id: number) =>
  HttpClient.get(`/todos/${id}`).pipe(
    Effect.andThen((response) => response.json)
  );

const program = getTodo(1).pipe(
  Effect.tap((data) => Console.log(`Fetched todo: ${JSON.stringify(data)}`)),
  Effect.catchAll((error) => Console.log(`Error: ${error.message}`))
);

Effect.runPromise(program);

这段代码定义了一个 getTodo 函数,使用 HttpClient 发送 GET 请求。使用 pipe 组合操作,通过 Effect.andThen 解析 JSON 响应。使用 Effect.tap 打印结果,Effect.catchAll 捕获并处理错误。 最后通过 Effect.runPromise 异步执行程序。

错误重试与超时

Effect-TS 内置了强大的错误处理和重试机制。例如,我们可以为 API 请求添加重试和超时逻辑:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import { Effect, Schedule } from "effect";

const robustGetTodo = (id: number) =>
  getTodo(id).pipe(
    Effect.retry(Schedule.exponential("100 millis", 2).pipe(Schedule.upTo(3))),
    Effect.timeout("1 second")
  );

const program = robustGetTodo(1).pipe(
  Effect.tap((data) => Console.log(`Success: ${JSON.stringify(data)}`)),
  Effect.catchAll((error) => Console.log(`Failed: ${error.message}`))
);

Effect.runPromise(program);

这里 Effect.retry 使用指数退避策略重试最多 3 次。Effect.timeout 设置 1 秒超时,超时后自动中止请求。所有这些操作都是声明式的,代码清晰且易于维护。

相较于 VueUse 或 ahooks 返回的错误类型通常是 unknown 或泛型,需要我们手动处理类型断言或错误边界!

最后

Effect-TS 不仅仅是一个核心库,它还有丰富的生态系统。感兴趣的小伙伴可以看这里

https://github.com/Effect-TS/effect?tab=readme-ov-file#monorepo-structure

生态
生态

生态

文章有限,我介绍了九牛一毛,感兴趣的同学可以看看文档:https://effect.website/docs

今天的分享就这些了,感谢大家的阅读,如果文章中存在错误的地方欢迎指正!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-05-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 萌萌哒草头将军 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
《现代Javascript高级教程》JavaScript函数式编程
函数式编程(Functional Programming)是一种编程范式,它将计算机程序视为数学函数的组合,强调函数的纯粹性和不可变性。JavaScript作为一种多范式的语言,也支持函数式编程风格。本文将介绍JavaScript函数式编程的基本概念和特点,并通过代码示例来展示其实际应用。
linwu
2023/07/27
2150
函数式编程概要
函数式编程是一种通过组合纯函数来编写软件的编程范式,它是声明式而非命令式的,其原则是避免共享状态, 改变数据,以及副作用。
宅蓝三木
2024/10/09
1250
函数式编程了解一下(下)
一步一步来理解,第一次调用curry函数的时候,返回一个curried函数,待调用状态,当我们传入1的时候,返回的依旧是一个函数,args是利用闭包,记录你传入的参数是否为函数定义时候的参数个数,如果不是,那我接着等待你在传入。因为我们利用args来记录每次传入的值,所以我们每次拿curry函数后的传入的参数就必须使用arguments了,由于它是类数组,我们想拿到参数值,所以这里我们使用slice。最终,我们其实还是调用a+b+c的运算。
Nealyang
2019/09/29
1.1K0
函数式编程了解一下(下)
JavaScript——函数式编程Functor(函子)
容器: 包含值和值的变形关系(函数) 函子: 是一个特殊的容器,通过一个普通的对象来实现,该对象具有map方法,map方法可以运行一个函数对值进行处理(变形关系)
思索
2024/08/16
1260
JavaScript——函数式编程Functor(函子)
【Spring底层原理高级进阶】基于Spring Boot和Spring WebFlux的实时推荐系统的核心:响应式编程与 WebFlux 的颠覆性变革
传统的Spring MVC架构是一种基于Java的Web应用程序开发框架,它遵循了MVC(Model-View-Controller)设计模式。下面将介绍传统Spring MVC架构的基本原理和组件:
苏泽
2024/03/01
4520
[译]精通JavaScript面试之什么是函数式编程?
在JavaScript的世界中函数式编程已然变成热门的话题了。仅仅在几年之前,极少数的JavaScript程序员听说过函数式编程是什么,但是在过去三年里我看到的每个大型应用的代码库中都使用了大量函数式编程的想法。
the5fire
2019/03/01
9360
如何编写高质量的 JS 函数(4) --函数式编程[实战篇]
本文会从如何用函数式编程思想编写高质量的函数、分析源码里面的技巧,以及实际工作中如何编写,来展示如何打通你的任督二脉。话不多说,下面就开始实战吧。
2020labs小助手
2019/11/11
2.1K0
深入学习JavaScript ES8函数式编程:特性与实践指南
函数式编程已经成为现代JavaScript开发中的一种主要范式。它提供了一种更清晰、更模块化、更可维护的代码编写方式。随着ECMAScript 2017(通常称为ES8)的发布,JavaScript引入了一些新的语法和功能,进一步提高了函数式编程的能力。本文将深入探讨ES8中的一些关键特性,并演示如何使用这些特性进行函数式编程实践。
海拥
2023/09/07
3400
【JS】394- 简明 JavaScript 函数式编程-入门篇
本文较长,总共分为三大部分:(对于函数式编程以及其优点有一定理解的童鞋,可以直接从 第二部分 开始阅读)
pingan8787
2019/10/30
1.1K0
【JS】394- 简明 JavaScript 函数式编程-入门篇
JavaScript函数式编程,真香之组合(二)
组合是一种为软件的行为,进行清晰建模的一种简单、优雅而富于表现力的方式。通过组合小的、确定性的函数,来创建更大的软件组件和功能的过程,会生成更容易组织、理解、调试、扩展、测试和维护的软件。
桃翁
2019/03/14
7470
必点?JavaScript 召唤师【必点】的 4 个函数式编程【天赋】~~
前面已经写了 7 篇关于 JS 函数式编程、2 篇关于函数组合、2 篇关于 Haskell 入门,想看的话,可以在我的 JS 专栏 中找到它们;
掘金安东尼
2022/09/19
2830
必点?JavaScript 召唤师【必点】的 4 个函数式编程【天赋】~~
前端开发者的 Kotlin 之旅:函数式编程深入
纯函数是函数式编程的核心概念:给定相同输入总是返回相同输出,且没有副作用。这使得代码更可预测、更易测试,也更容易进行并行处理。
骑猪耍太极
2025/05/14
990
前端开发者的 Kotlin 之旅:函数式编程深入
JavaScript 函数式编程
函数式编程是一种编程范式,主要是利用函数把运算过程封装起来,通过组合各种函数来计算结果。 举个例子,要把字符串 functional programming is great 变成每个单词首字母大写,可以这样实现:
Leophen
2021/08/06
3780
JavaScript 函数式编程
《JavaScript ES6 函数式编程入门经典》读书笔记
函数式编程是一种范式,我们能够以此创建仅依赖输入就可以完成自身逻辑的函数。这保证了当函数多次调用时仍然返回相同的结果。函数不会改变任何外部环境的变量,这将产生可缓存,可测试的代码库。
kai666666
2020/10/27
2.4K0
【响应式编程的思维艺术】 (5)Angular中Rxjs的应用示例
尽管看起来Http请求的返回结果是一个可观测对象,但是它却没有map方法,当需要对http请求返回的可观测对象进行操作时,可以使用pipe操作符来实现:
大史不说话
2019/02/21
7.1K0
【响应式编程的思维艺术】 (5)Angular中Rxjs的应用示例
JavaScript函数式编程之函子
函子是一个特殊的容器,通过一个普通对象来实现,该对象具有map方法,map方法可以运行一个函数对值进行处理(变形关系),容器包含值和值变形关系(这个变形关系就是函数)。函数式编程中解决副作用的存在
开水泡饭
2022/12/26
1.3K0
《JavaScript函数式编程指南》读书笔记
老规矩,这篇文章记录书中的重点部分,外加自己的见解,不会对全书进行复述,但记录的绝对是最重要的部分,想要了解跟多内容请看原版图书。
kai666666
2020/10/19
1K0
《JavaScript函数式编程指南》读书笔记
你会用RxJS吗?【初识 RxJS中的Observable和Observer】
可以看到,我们用到了scan操作符,该操作符的工作方式和数组的reduce类似,回调函数接收一个值, 回调的返回值作为下一次回调运行暴露的一个值。
科技新语
2022/08/17
1.5K0
函数式编程了解一下(上)
所以我们说,函数式编程是一种范式,我们能够以此创建仅依赖输入就可以完成自身逻辑的函数。这保证了当函数多次调用时,依然可以返回相同的结果。因此可以产生可缓存的、可测试的代码库
Nealyang
2019/09/29
5480
函数式编程了解一下(上)
JavaScript 函数式编程解析(上)
在 JavaScript 中,函数是一等公民,它意味着函数就跟其他任何数据类型一样,并没有什么特殊之处——可以存储在数组中,作为函数的参数传递、赋值给变量,等等。作为“一等公民”,函数的意义至少有如下几点:
用户4456933
2021/07/12
6240
JavaScript 函数式编程解析(上)
推荐阅读
相关推荐
《现代Javascript高级教程》JavaScript函数式编程
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验