Effect Without Effect-TS:纯 TypeScript 中的代数思维
A lot of people are reaching for Effect-TS.
很多人正在转向Effect-TS。
Every few months you’ll be three functions deep in some TypeScript service, squinting at a try/catch that swallows four different kinds of failure into one catch (err), and you’ll think: “Effect would fix this.” Then you look at the API surface, the generator syntax, the layers and services and fibers, and you quietly close the tab. Not because it’s bad (not at all; it’s genuinely impressive software.) But it requires some investment, and you’re just not quite sure…
每隔几个月,你就会在某个 TypeScript 服务中深入三个函数,眯眼看着一个 try/catch,它将四种不同的失败吞并到一个 catch (err) 中,你会想:“Effect 可以修复这个。”然后你看看 API 表面、生成器语法、层、服务和 fibers,然后悄悄关闭标签页。不是因为它不好(完全不是;它是真正令人印象深刻的软件。)而是因为它需要一些投资,而你只是不太确定……
But what if the ideas behind it don’t require the framework, and you can use most of them with what TypeScript gives you out of the box?
但是,如果它背后的想法并不需要框架,你可以用 TypeScript 开箱即用的大多数功能来使用它们呢?
If you read my parse-don’t-validate post, you already used one of those ideas. The Parsed<T> type that returns either a value or an error? That’s typed errors as values. You were doing algebraic thinking without knowing it. (I was too, for years, before I learned what to call it.)
如果你读了我的 那个 parse-don’t-validate 帖子,你已经使用过那些想法之一。那个返回值或错误的 Parsed<T> 类型?那是作为值的类型化错误。你在不知情的情况下进行了代数思考。(我也是,在学会怎么称呼它之前,好几年。)
This post takes that thread and pulls it further. Same principle (“make the type system carry the proof”) applied to operations instead of data.
这篇文章延续那个思路并拉得更远。相同原则(“让类型系统承载证明”)应用于操作而非数据。
The function that lies to you
欺骗你的函数
Here’s a signup function we’ve written in some form at, well, every company we’ve worked at:
这里是一个我们在、嗯、我们工作过的每家公司都以某种形式写过的 signup 函数:
async function signupUser(email: string, password: string): Promise<User> {
if (!isValidEmail(email)) {
throw new Error("Invalid email");
}
const existing = await db.findUserByEmail(email);
if (existing) {
throw new Error("Email already registered");
}
const user = await db.createUser({
email,
passwordHash: await hash(password),
});
aw...