effect-patterns-core-concepts
Effect-TS patterns for Core Concepts. Use when working with core concepts in Effect-TS applications.
安装与使用
请根据来源仓库和你的 AI 工具说明安装此技能。先阅读技能文件和依赖要求,再添加到工作流。
查看来源 ↗使用指南技能说明
Effect-TS Patterns: Core Concepts
This skill provides 49 curated Effect-TS patterns for core concepts. Use this skill when working on tasks related to:
- core concepts
- Best practices in Effect-TS applications
- Real-world patterns and solutions
🟢 Beginner Patterns
Combining Values with zip
Rule: Use zip to run two computations and combine their results into a tuple, preserving error and context handling.
Good Example:
import { Effect, Either, Option, Stream } from "effect";
// Effect: Combine two effects and get both results
const effectA = Effect.succeed(1);
const effectB = Effect.succeed("hello");
const zippedEffect = effectA.pipe(Effect.zip(effectB)); // Effect<[number, string]>
// Option: Combine two options, only Some if both are Some
const optionA = Option.some(1);
const optionB = Option.some("hello");
const zippedOption = Option.all([optionA, optionB]); // Option<[number, string]>
// Either: Combine two eithers, only Right if both are Right
const eitherA = Either.right(1);
const eitherB = Either.right("hello");
const zippedEither = Either.all([eitherA, eitherB]); // Either<never, [number, string]>
// Stream: Pair up values from two streams
const streamA = Stream.fromIterable([1, 2, 3]);
const streamB = Stream.fromIterable(["a", "b", "c"]);
const zippedStream = streamA.pipe(Stream.zip(streamB)); // Stream<[number, string]>
Explanation:
zip runs both computations and pairs their results.
If either computation fails (or is None/Left/empty), the result is a failure (or None/Left/empty).
Anti-Pattern:
Manually running two computations, extracting their results, and pairing them outside the combinator world.
This breaks composability, loses error/context handling, and can lead to subtle bugs.
Rationale:
Use the zip combinator to combine two computations, pairing their results together.
This works for Effect, Stream, Option, and Either, and is useful when you want to run two computations and work with both results.
zip lets you compose computations that are independent but whose results you want to use together.
It preserves error handling and context, and keeps your code declarative and type-safe.
Creating from Synchronous and Callback Code
Rule: Use sync and async to create Effects from synchronous or callback-based computations, making them composable and type-safe.
Good Example:
import { Effect } from "effect";
// Synchronous: Wrap a computation that is guaranteed not to throw
const effectSync = Effect.sync(() => Math.random()); // Effect<never, number, never>
// Callback-based: Wrap a Node.js-style callback API
function legacyReadFile(
path: string,
cb: (err: Error | null, data?: string) => void
) {
setTimeout(() => cb(null, "file contents"), 10);
}
const effectAsync = Effect.async<string, Error>((resume) => {
legacyReadFile("file.txt", (err, data) => {
if (err) resume(Effect.fail(err));
else resume(Effect.succeed(data!));
});
}); // Effect<string, Error, never>
Explanation:
-
Effect.syncis for synchronous computations that are guaranteed not to throw. -
Effect.asyncis for integrating callback-based APIs, converting them into Effects.
Anti-Pattern:
Directly calling synchronous or callback-based APIs inside Effects without lifting them, which can break composability and error handling.
Rationale:
Use the sync and async constructors to lift synchronous or callback-based computations into the Effect world.
This enables safe, composable interop with legacy or third-party code that doesn't use Promises or Effects.
Many APIs are synchronous or use callbacks instead of Promises.
By lifting them into Effects, you gain access to all of Effect's combinators, error handling, and resource safety.
Model Optional Values Safely with Option
Rule: Use Option to model values that may be present or absent, making absence explicit and type-safe.
Good Example:
import { Option } from "effect";
// Create an Option from a value
const someValue = Option.some(42); // Option<number>
const noValue = Option.none(); // Option<never>
// Safely convert a nullable value to Option
const fromNullable = Option.fromNullable(Math.random() > 0.5 ? "hello" : null); // Option<string>
// Pattern match on Option
const result = someValue.pipe(
Option.match({
onNone: () => "No value",
onSome: (n) => `Value: ${n}`,
})
); // string
// Use Option in a workflow
function findUser(id: number): Option.Option<{ id: number; name: string }> {
return id === 1 ? Option.some({ id, name: "Alice" }) : Option.none();
}
Explanation:
-
Option.some(value)represents a present value. -
Option.none()represents absence. -
Option.fromNullablesafely lifts nulla
使用示例
查看来源仓库中的使用示例与配置说明。
查看来源 ↗来源历史
- 收录时间
- 2026-01-20
- 索引更新时间
- 2026-01-28
- Branch
- main
收录与同步日期属于本站记录。源码修改历史请查看来源仓库。
GitHub ↗chat Comments (0)
Sign in to join the discussion and leave a comment.
No comments yet. Be the first to share your thoughts!