# @codeforbreakfast/eslint-effect 中文文档

规范地址：https://npmcn.com/package/%40codeforbreakfast/eslint-effect/

版本：0\.8\.5
npm 元数据更新时间：2025-12-11T08:55:28.199Z
中文译文更新时间：2026-11-10T06:40:15.914Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40codeforbreakfast/eslint-effect
原文对照：https://npmcn.com/package/%40codeforbreakfast/eslint-effect/?lang=original
项目主页：https://github.com/CodeForBreakfast/eventsourcing#readme
源码仓库：https://github.com/CodeForBreakfast/eventsourcing

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：149 kB，47 个文件
- 模块格式：ES Module
- TypeScript 类型：未声明
- 运行依赖：0 个
- peer 依赖：eslint \>=8\.0\.0
- 首次发布：2025-10-06T05:56:34.598Z
- 最新版本发布：2025-12-11T08:55:27.808Z
- 近 30 天下载量：2662（2026-10-10 至 2026-11-08，npm 官方下载统计）
- 已发布版本数：12（近 12 个月 2 个）

## 中文简介

执行功能编程最佳做法的效果项目ESLint规则和配置

## 安装

```sh
npm install @codeforbreakfast/eslint-effect
```

也可以使用：`pnpm add @codeforbreakfast/eslint-effect`、`yarn add @codeforbreakfast/eslint-effect`、`bun add @codeforbreakfast/eslint-effect`

## README

# @ codeforbreakfast/ slint 无效

ESLint规则和配置用于执行功能编程最佳做法和平庸效应代码模式的Effect项目.

## 安装

```bash
npm install --save-dev @codeforbreakfast/eslint-effect
# or
bun add --dev @codeforbreakfast/eslint-effect
```

## 特征

本套件提供:

-   **自定义 ESLint 规则** 特定效果模式
-   **语法限制** 执行职能方案拟订原则
-   **预设规则集** 不同背景
-   **功能不可变规则** 适应效果类型

## 自定义规则

### `no-unnecessary-pipe-wrapper`

在单管操作周围检测到不必要的功能包接.

恶:

```typescript
import { pipe } from 'effect';

declare const transform: (x: unknown) => unknown;

const fn = (x: unknown) => pipe(x, transform);
```

不错:

```typescript
declare const transform: (x: unknown) => unknown;

const fn = transform;
```

### `no-eta-expansion`

检测到不必要的函数包(eta-expansion),它只将参数直接传递到另一个函数. 也被称为"更优先的无分地风格"

恶:

```typescript
import { Console } from 'effect';

declare const doSomething: (x: number) => unknown;
declare const processData: (a: string, b: number) => unknown;

const logError = (msg: string) => Console.error(msg);
const transform = (x: number) => doSomething(x);
const handler = (a: string, b: number) => processData(a, b);
```

不错:

```typescript
import { Console } from 'effect';

declare const doSomething: (x: number) => unknown;
declare const processData: (a: string, b: number) => unknown;

const logError = Console.error;
const transform = doSomething;
const handler = processData;
```

**理由**:在功能编程中,去除(Xx.f(x) f)消除了不必要的间接. 当一个函数仅直接传递其参数给另一个函数而没有任何变换时,包裹会不增加值并降低可读性.

### `no-unnecessary-function-alias`

检测到不必要功能别名, 不提供语义值 。 当一个常数被直接指派到另一个函数而不增加清晰度或抽象度时,应当在调用站点被内置.

恶:

```typescript
import { Array, Ref } from 'effect';

declare const ref: Ref.Ref<unknown>;
declare const arr: readonly unknown[];
declare function useOnce(val: unknown): void;
declare function useTwice(val: unknown): void;

const getState = Ref.get;
const transform = Array.map;

// Used only once or twice
useOnce(getState(ref));
useTwice(transform(arr, (x: unknown) => (x as number) * 2));
```

不错:

```typescript
import { Array, Ref, Stream } from 'effect';

declare const ref: Ref.Ref<unknown>;
declare const arr: readonly unknown[];
declare function useOnce(val: unknown): void;
declare function useTwice(val: unknown): void;

// Inline when used infrequently
useOnce(Ref.get(ref));
useTwice(Array.map(arr, (x: unknown) => (x as number) * 2));

// OR keep the alias if it adds semantic value
// eslint-disable-next-line effect/no-unnecessary-function-alias -- Alias clarifies stream processing context
const collectStreamResults = Stream.runCollect;
```

**配置 :**

-   `maxReferences` (默认 : `2`\- 在别名被认为有正当理由之前最多参考次数

```javascript
{
  rules: {
    'effect/no-unnecessary-function-alias': ['warn', {
      maxReferences: 3,  // Allow aliases used 3+ times
    }]
  }
}
```

**理由**: 仅使用一次或两次的函数别名会增加认知间接费用而无有意义的好处. 它们迫使读者从别名定义到使用网站之间跳出. 直接函数调用更直接. 然而,经常使用(3+次)或通过名称来增加语义清晰度的别名应当保留.

### `prefer-match-tag`

强制执行 `Match.tag()` 结束 `Match.when()` 页:1 `_tag` 歧视者.

恶:

```typescript
import { Match, pipe } from 'effect';

type Tagged = { _tag: 'Success' } | { _tag: 'Error' };
declare const value: Tagged;
declare const handler: (val: { _tag: 'Success' }) => unknown;

pipe(Match.value(value), Match.when({ _tag: 'Success' }, handler));
```

不错:

```typescript
import { Match, pipe } from 'effect';

type Tagged = { _tag: 'Success' } | { _tag: 'Error' };
declare const value: Tagged;
declare const handler: (val: { _tag: 'Success' }) => unknown;

pipe(Match.value(value), Match.tag('Success', handler));
```

### `prefer-match-over-conditionals`

鼓励声明 `Match` 模式相对于必要 `if` 效果回调中的语句.

恶:

```typescript
import { Effect, Match, pipe } from 'effect';

type TaggedValue = { _tag: 'Success' } | { _tag: 'Error' };
declare const handleSuccess: (x: { _tag: 'Success' }) => Effect.Effect<unknown>;
declare const handleError: (x: TaggedValue) => Effect.Effect<unknown>;
declare const effectValue: Effect.Effect<TaggedValue>;

pipe(
  effectValue,
  Effect.flatMap((x: TaggedValue) => {
    if (x._tag === 'Success') return handleSuccess(x);
    return handleError(x);
  })
);
```

不错:

```typescript
import { Effect, Match, pipe } from 'effect';

type TaggedValue = { _tag: 'Success' } | { _tag: 'Error' };
declare const handleSuccess: (x: { _tag: 'Success' }) => Effect.Effect<unknown>;
declare const handleError: (x: TaggedValue) => Effect.Effect<unknown>;
declare const effectValue: Effect.Effect<TaggedValue>;

pipe(
  effectValue,
  Effect.flatMap((x: TaggedValue) =>
    pipe(Match.value(x), Match.tag('Success', handleSuccess), Match.orElse(handleError))
  )
);
```

### `prefer-effect-if-over-match-boolean`

强制执行 `Effect.if` 结束 `Match.value` 对于布尔条件. `Match.value` 应保留在多个值上进行模式匹配,而非简单的真/假分支.

恶:

```typescript
import { Effect, Match, pipe } from 'effect';

declare const isValid: boolean;
declare const user: { isAdmin: boolean };
declare function grantAccess(): Effect.Effect<unknown>;
declare function denyAccess(): Effect.Effect<unknown>;

pipe(
  isValid,
  Match.value,
  Match.when(true, () => Effect.succeed('valid')),
  Match.when(false, () => Effect.fail('invalid')),
  Match.exhaustive
);

pipe(
  user.isAdmin,
  Match.value,
  Match.when(true, () => grantAccess()),
  Match.when(false, () => denyAccess()),
  Match.exhaustive
);
```

不错:

```typescript
import { Effect } from 'effect';

declare const isValid: boolean;
declare const user: { isAdmin: boolean };
declare function grantAccess(): Effect.Effect<unknown>;
declare function denyAccess(): Effect.Effect<unknown>;

Effect.if(isValid, {
  onTrue: () => Effect.succeed('valid'),
  onFalse: () => Effect.fail('invalid'),
});

Effect.if(user.isAdmin, {
  onTrue: () => grantAccess(),
  onFalse: () => denyAccess(),
});
```

**理由**数字 : `Match.value` 旨在对受歧视的工会和多种价值观进行模式匹配。 用它来做简单的布尔条件 是动词和模糊的意图. `Effect.if` 明确、简洁和清晰地传达布尔分支逻辑.

### `prefer-match-over-ternary`

鼓励声明 `Match.value` 当模式匹配非布尔值时,或者在函数调用之间选择时,模式会超越三位运算符.

**说明**: 对于布尔条件返回效果,使用 `Effect.if` 相反(见 `prefer-effect-if-over-match-boolean` (见上文规则).

恶:

```typescript
import { Option, Stream } from 'effect';

type FilterFn = (v: unknown) => boolean;
declare const filter: FilterFn | undefined;
declare const stream: Stream.Stream<unknown>;
declare function processValue(val: number): unknown;
declare function getDefault(): unknown;
declare function finalizeTask(): unknown;
declare function continueTask(): unknown;

const result = filter !== undefined ? Stream.filter(stream, filter) : stream;

const handler = (option: Option.Option<number>) =>
  Option.isSome(option) ? processValue(option.value) : getDefault();

const processStatus = (status: 'pending' | 'active' | 'complete') =>
  status === 'complete' ? finalizeTask() : continueTask();
```

不错:

```typescript
import { Match, Option, pipe, Stream } from 'effect';

type FilterFn = (v: unknown) => boolean;
declare const filter: FilterFn | undefined;
declare const stream: Stream.Stream<unknown>;
declare function processValue(val: number): unknown;
declare function getDefault(): unknown;
declare function finalizeTask(): unknown;
declare function continueTask(): unknown;

const result = pipe(
  filter,
  Match.value,
  Match.when(Match.undefined, () => stream),
  Match.orElse((f) => Stream.filter(stream, f))
);

const handler = (option: Option.Option<number>) =>
  pipe(
    option,
    Match.value,
    Match.when({ _tag: 'Some' }, (opt) => processValue(opt.value)),
    Match.orElse(getDefault)
  );

const processStatus = (status: 'pending' | 'active' | 'complete') =>
  pipe(status, Match.value, Match.when('complete', finalizeTask), Match.orElse(continueTask));
```

**对于带效果的布尔条件,使用 `Effect.if`数字 :**

```typescript
import { Effect } from 'effect';

declare const condition: boolean;

// Boolean condition returning Effects - use Effect.if, NOT Match.value
const result = Effect.if(condition, {
  onTrue: () => Effect.succeed(42),
  onFalse: () => Effect.fail('error'),
});
```

**理由**: 三级操作员是必须的,而且比 `Match` 模式。 使用 `Match.value` 为可选类型、联盟类型或非布尔条件等值的图案匹配提供了更好的可比较性。 但是,对于简单的布尔条件 返回效果, `Effect.if` 因为它更清晰 更安全 纯值之三(不是函数调用)是允许的,因为它们适合简单的值选择.

### `no-switch-statement`

功能效应代码中的禁用交换语句. 切换语句是必须的,不提供详尽无遗的检查. 使用 `Match` 用于类型安全、详尽无遗的模式匹配.

恶:

```typescript
import { Match, pipe } from 'effect';

type Event = { type: 'Created' } | { type: 'Updated' } | { type: 'Other' };
declare const event: Event;
declare function handleCreated(e: Event): unknown;
declare function handleUpdated(e: Event): unknown;
declare function handleUnknown(e: Event): unknown;

function processEvent() {
  switch (event.type) {
    case 'Created':
      return handleCreated(event);
    case 'Updated':
      return handleUpdated(event);
    default:
      return handleUnknown(event);
  }
}
```

不错:

```typescript
import { Match, pipe } from 'effect';

type Event = { type: 'Created' } | { type: 'Updated' } | { type: 'Other' };
declare const event: Event;
declare function handleCreated(e: Event): unknown;
declare function handleUpdated(e: Event): unknown;
declare function handleUnknown(e: Event): unknown;

pipe(
  Match.value(event),
  Match.when({ type: 'Created' }, handleCreated),
  Match.when({ type: 'Updated' }, handleUpdated),
  Match.orElse(handleUnknown)
);
```

**受歧视的工会 `_tag`数字 :**

```typescript
import { Match, pipe } from 'effect';

type TaggedEither = { _tag: 'Right'; value: unknown } | { _tag: 'Left'; error: unknown };
declare const either: TaggedEither;
declare function handleRight(val: { _tag: 'Right'; value: unknown }): unknown;
declare function handleLeft(val: { _tag: 'Left'; error: unknown }): unknown;

pipe(
  Match.value(either),
  Match.tag('Right', handleRight),
  Match.tag('Left', handleLeft),
  Match.exhaustive
);
```

### `no-if-statement`

如果功能效应代码中的语句, 则禁止此语句 。 如果声明是必须的 并且没有很好的构思。 使用 `Effect.if` 对有效果的布尔条件, `Match.value` 用于图案匹配,或用于声明控制流的特定类型匹配器.

恶:

```typescript
import { Effect, Option, pipe } from 'effect';

declare const todoState: { deleted: boolean };
declare const event: { type: string; data: { title: string } };
declare const option: Option.Option<string>;
declare const state: Option.Option<{ deleted: boolean }>;
declare const defaultValue: string;

// Bad pattern 1
function check1() {
  if (todoState.deleted) {
    return Effect.fail(new Error('Cannot complete deleted TODO'));
  }
  return Effect.succeed(todoState);
}

// Bad pattern 2
function check2() {
  if (event.type === 'TodoCreated') {
    return Effect.succeed({ title: event.data.title, completed: false });
  }
  return pipe(state, Option.match({ onNone: () => defaultValue, onSome: (s) => s }));
}

// Bad pattern 3
function check3() {
  if (Option.isSome(option)) {
    return option.value;
  }
  return defaultValue;
}
```

不错:

```typescript
import { Effect, Option, Match, pipe } from 'effect';

declare const todoState: { deleted: boolean };
declare const event: { type: string; data: { title: string } };
declare const option: Option.Option<string>;
declare const state: Option.Option<{ deleted: boolean }>;
declare const defaultValue: string;
declare const condition: boolean;

// Boolean conditionals with Effects
Effect.if(todoState.deleted, {
  onTrue: () => Effect.fail(new Error('Cannot complete deleted TODO')),
  onFalse: () => Effect.succeed(todoState),
});

// Pattern matching on discriminated unions
pipe(
  event,
  Match.value,
  Match.when({ type: 'TodoCreated' }, (e) =>
    Effect.succeed({ title: e.data.title, completed: false })
  ),
  Match.orElse((e) => pipe(state, Option.match({ onNone: () => defaultValue, onSome: (s) => s })))
);

// Option/Either with built-in matchers
pipe(
  option,
  Option.getOrElse(() => defaultValue)
);

// Simple value selection - use ternary operators
const x = condition ? 'yes' : 'no';
```

**理由**:如果语句打破了功能构成,使代码更难解释. 它们没有提供图案匹配的详尽无遗的检查,而且不能轻易地由管子组成. 使用 `Effect.if`, (中文(简体) ), `Match.value`,或者特定类型匹配者喜欢 `Option.match` 提供更好的类型安全、详尽无遗的检查和可容性。 初等运算符仍然被允许进行简单的值选择,因为它们适合纯值.

### `prefer-schema-validation-over-assertions`

Effect recalls中的不鼓励类型断言有利于运行时间验证.

恶:

```typescript
import { Effect } from 'effect';

type MyType = { value: string };
declare function handler(x: MyType): unknown;

Effect.map((x: unknown) => handler(x as MyType));
```

不错:

```typescript
import { Effect, pipe, Schema } from 'effect';

type MyType = { value: string };
declare const MyTypeSchema: Schema.Schema<MyType>;
declare const input: Effect.Effect<unknown>;
declare function handler(x: MyType): unknown;

pipe(input, Effect.flatMap(Schema.decodeUnknown(MyTypeSchema)), Effect.map(handler));
```

### `suggest-currying-opportunity`

建议 curry 用户定义的功能去除管链中的箭头功能包. 默认情况下,仅在参数已经处于正确顺序(不需要重新排序)时才会建议咖喱,并且限制单级咖喱的可读性.

#### QQ 将建议( 好模式 - 已到尾端的参数 ) :

```typescript
import { Effect } from 'effect';

declare const myEffect: Effect.Effect<unknown>;
declare function logError(message: string, error: unknown): Effect.Effect<void>;

// Before
Effect.catchAll(myEffect, (error) => logError('Failed', error));

// After currying (params already in right order)
const logErrorCurried = (message: string) => (error: unknown) =>
  Effect.sync(() => console.error(message, error));

Effect.catchAll(myEffect, logErrorCurried('Failed'));
```

#### QQ 不通过默认建议( 需要参数重排) :

```typescript
import { Effect } from 'effect';

declare const myEffect: Effect.Effect<unknown>;
declare function logError(error: unknown, message: string): Effect.Effect<void>;

// This would break semantic order - error should come before message
Effect.catchAll(myEffect, (error) => logError(error, 'Failed'));

// Would require changing to: logError = (message) => (error) => ...
// But semantically, error should come first in the return object
```

#### {\\fn黑体\\fs22\\bord1\\shad0\\3aHBE\\4aH00\\fscx67\\fscy66\\2cHFFFFFF\\3cH808080}不会以默认的方式提出 {\\fn黑体\\fs22\\bord1\\shad0\\3aHBE\\4aH00\\fscx67\\fscy66\\2cHFFFFFF\\3cH808080}会创造出深层的咖喱声:

```typescript
import { Effect } from 'effect';

declare const myEffect: Effect.Effect<unknown>;
declare function processData(prefix: string, suffix: string, data: unknown): unknown;

// Would create 2-level currying: (prefix) => (suffix) => (data) => ...
Effect.map(myEffect, (data) => processData('prefix', 'suffix', data));

// Too many parentheses at call site: processData('prefix')('suffix')
```

**配置选项 :**

-   `allowReordering` (默认 : `false`\- 即使参数需要重新排序,也允许提出建议
-   `maxCurriedParams` (默认 : `1`,最大值 : `3`) - 可建议的最大曲尾参数数

```javascript
{
  rules: {
    'effect/suggest-currying-opportunity': ['warn', {
      allowReordering: true,    // Allow parameter reordering suggestions
      maxCurriedParams: 2,      // Allow up to 2-level currying
    }]
  }
}
```

**说明:** 此规则只触发用户定义的函数,而不是效果库函数.

### `no-intermediate-effect-variables`

被禁者存储 Effect/Stream/pipe,当它们被内接入管链时会产生中间变量. 允许配置数据,如调度常数、重试政策和作为参数通过的效果值.

坏( 应当内含) :

```typescript
import { Effect, pipe, Schema } from 'effect';

type User = { id: string; name: string };
declare const userId: string;
declare const UserSchema: Schema.Schema<User>;
declare const data: unknown;
declare function fetchUser(id: string): Effect.Effect<User>;
declare function validateUser(u: User): Effect.Effect<User>;
declare function formatUserData(u: User): unknown;
declare function processUser(u: User): User;
declare function saveToDatabase(u: User): Effect.Effect<void>;

// Breaking up the pipe chain for a single use
const userEffect = fetchUser(userId);
const result = pipe(userEffect, Effect.flatMap(validateUser), Effect.map(formatUserData));

// Storing intermediate pipe results used once
function processData() {
  const validated = pipe(data, Schema.decodeUnknown(UserSchema));
  const processed = Effect.map(validated, processUser);
  return Effect.flatMap(processed, saveToDatabase);
}

// Schema defined but only used once
const UserIdSchema = pipe(Schema.String, Schema.nonEmptyString());
export const decodeUserId = Schema.decode(UserIdSchema); // Only usage
```

好( 内置管道值) :

```typescript
import { Effect, pipe, Schema } from 'effect';

type User = { id: string; name: string };
declare const userId: string;
declare const UserSchema: Schema.Schema<User>;
declare const data: unknown;
declare function fetchUser(id: string): Effect.Effect<User>;
declare function validateUser(u: User): Effect.Effect<User>;
declare function formatUserData(u: User): unknown;
declare function processUser(u: User): User;
declare function saveToDatabase(u: User): Effect.Effect<void>;

// Single cohesive pipe chain
const result = pipe(fetchUser(userId), Effect.flatMap(validateUser), Effect.map(formatUserData));

// All transformations in one composition
function processData() {
  return pipe(
    data,
    Schema.decodeUnknown(UserSchema),
    Effect.map(processUser),
    Effect.flatMap(saveToDatabase)
  );
}

// Schema inlined directly
export const decodeUserId = Schema.decode(pipe(Schema.String, Schema.nonEmptyString()));
```

好(配置数据):

```typescript
import { Effect, pipe, Schedule } from 'effect';

declare const operation: Effect.Effect<unknown>;

// Schedule constants used as configuration
const retrySchedule = pipe(
  Schedule.exponential('100 millis'),
  Schedule.union(Schedule.spaced('1 second'))
);
const result = pipe(operation, Effect.retry(retrySchedule));

// Effect values used as parameters
const defaultValue = Effect.succeed(42);
const combined = pipe(
  Effect.succeed(1),
  Effect.zipWith(defaultValue, (a, b) => a + b)
);
```

好(多种用途 -- -- 合法再利用):

```typescript
import { Context, Effect, Layer, pipe } from 'effect';

declare class PgClientService extends Context.Tag('PgClient')<PgClientService, unknown>() {}
declare const createPgClient: Effect.Effect<unknown>;
declare const Migration: { layer: Layer.Layer<unknown> };
declare const EventStore: { layer: Layer.Layer<unknown> };
declare function it(name: string, fn: () => unknown): void;

// Layer reused in multiple compositions
const PgLive = Layer.effect(PgClientService, createPgClient);
const Layer1 = pipe(Migration.layer, Layer.provide(PgLive)); // Use 1
const Layer2 = pipe(EventStore.layer, Layer.provide(PgLive)); // Use 2

// Effect reused across test cases
const setupTest = Effect.gen(function* () {
  yield* Effect.void;
});
it('test 1', () =>
  pipe(
    setupTest,
    Effect.flatMap(() => Effect.void)
  )); // Use 1
it('test 2', () =>
  pipe(
    setupTest,
    Effect.flatMap(() => Effect.void)
  )); // Use 2
```

好( 执行结果为纯值 ) :

```typescript
import { Effect, Either, pipe } from 'effect';

type Request = { token: string };
declare const req: Request;
declare function authenticate(r: Request): Effect.Effect<string, Error>;

// runSync returns a plain value, not an Effect
function handleAuth() {
  const authResult = Effect.runSync(pipe(authenticate(req), Effect.either));
  if (Either.isLeft(authResult)) {
    return { json: () => ({ error: authResult.left }) };
  }
  return { json: () => ({ token: authResult.right }) };
}
```

**理由**: 中间管线变量会断流管组成. 诸如作为Effect 操作参数的调度常数和效应值等配置数据是合法的组成部分,应当提取. 多种用途也证明可变提取是合理的.

**说明:** 这是一条侵略性规则,包含在 `pipeStrict` 相会.

## 规则预设

### 建议的预设

#### `recommended` ⭐

**建议用于大多数项目** - 核心效果最佳做法,没有有争议的规则:

-   所有效果插件规则
-   禁止类(效果标记/错误除外)
-   无效 `Effect.runSync`编号 :`runPromise` 生产
-   强制执行 `Effect.andThen()` 结束 `Effect.flatMap(() => )`
-   强制执行 `Effect.as()` 结束 `Effect.map(() => value)`
-   基于禁药方法 `.pipe()` (单独使用) `pipe()`(中文(简体) )
-   禁止 curried 函数调用( 使用) `pipe` 改为)
-   在转换中禁止身份功能
-   执行适当的管道参数命令

**不包括:**

-   `Effect.gen` 禁用( 选择使用 `noGen`(中文(简体) )
-   `_tag` 访问禁入( 选择 ) `preferMatch`(中文(简体) )
-   严格的管线规则(可选入) `pipeStrict`(中文(简体) )

#### `strict`

**对于狂热者** - 所有东西 `recommended` 加上所有有意见的规则:

-   全体 `recommended` 规则
-   无效 `Effect.gen` (使用时 `pipe` 改为)
-   直接禁止 `_tag` 访问(使用类型守护或 `Match`(中文(简体) )
-   全部禁止 `switch` 语句( 使用 `Match.value` 用于图案匹配)
-   全部禁止 `if` 语句( 使用 `Effect.if`, (中文(简体) ), `Match.value`,或类型特定匹配者)
-   禁忌筑巢 `pipe()` 电话
-   禁止多个 `pipe()` 在一个函数中呼叫

### 选入配置

把这些和 `recommended` 要定制您的规则 :

#### `noGen`

无效 `Effect.gen` 赞成: `pipe` 组成. **有争议** - 有些球队更喜欢金!

#### `preferMatch`

直接禁止 `_tag` 访问, 全部 `switch` 发言,以及所有发言 `if` 发言。 鼓励声明 `Match` 模式, `Effect.if` 用于布尔条件和特定类型匹配者.

#### `pipeStrict`

执行严格的管材构成规则:

-   禁忌筑巢 `pipe()` 电话
-   禁止多个 `pipe()` 每个函数的呼叫
-   禁止将管道/效果储存在单一用途中间变量中

#### `plugin`

插件规则, 没有语法限制 .

### 功能可变性

#### `functionalImmutabilityRules`

积分 `eslint-plugin-functional` 带有效果感知配置 :

-   执行只读类型,但效果类型除外
-   无效 `let` 约束
-   执行不可改变的数据模式
-   禁用循环( 使用) `Effect.forEach`, (中文(简体) ), `Array.map`页:1

## 使用量

### 建议设置

开始 `recommended` 对于合理的默认 :

```javascript
import effectPlugin from '@codeforbreakfast/eslint-effect';

export default [
  {
    ...effectPlugin.configs.recommended,
    files: ['**/*.ts', '**/*.tsx'],
    plugins: {
      effect: effectPlugin,
    },
  },
];
```

### 添加意见规则

必要时选择采用更严格的规则:

```javascript
import effectPlugin from '@codeforbreakfast/eslint-effect';

export default [
  {
    ...effectPlugin.configs.recommended,
    files: ['**/*.ts', '**/*.tsx'],
    plugins: {
      effect: effectPlugin,
    },
  },
  // Forbid Effect.gen
  {
    ...effectPlugin.configs.noGen,
    files: ['src/**/*.ts'],
  },
  // Enforce strict pipe rules
  {
    ...effectPlugin.configs.pipeStrict,
    files: ['src/**/*.ts'],
  },
  // Or just use strict for everything
  {
    ...effectPlugin.configs.strict,
    files: ['src/**/*.ts'],
    plugins: {
      effect: effectPlugin,
    },
  },
];
```

### 有功能可变性

要求数 `eslint-plugin-functional`数字 :

```javascript
import functionalPlugin from 'eslint-plugin-functional';
import effectPlugin from '@codeforbreakfast/eslint-effect';

export default [
  {
    files: ['**/*.ts'],
    plugins: {
      functional: functionalPlugin,
    },
    rules: effectPlugin.configs.functionalImmutabilityRules,
  },
  {
    ...effectPlugin.configs.recommended,
    files: ['**/*.ts'],
    plugins: {
      effect: effectPlugin,
    },
  },
];
```

### 禁用个别规则

所有语法限制规则都作为命名为ESLint的规则被曝光,从而容易禁用特定规则:

```javascript
import effectPlugin from '@codeforbreakfast/eslint-effect';

export default [
  {
    ...effectPlugin.configs.recommended,
    files: ['scripts/**/*.ts'],
    plugins: {
      effect: effectPlugin,
    },
    rules: {
      // Allow runPromise/runSync in scripts (application entry points)
      'effect/no-runPromise': 'off',
      'effect/no-runSync': 'off',
    },
  },
];
```

**可用的命名规则 :**

-   `effect/no-classes` - 无效类别,但效果标记/错误除外
-   `effect/no-runSync` - 无效效应. runSync
-   `effect/no-runPromise` - 无效效果. 运行保证
-   `effect/prefer-andThen` - 使用然后在平面图上使用(( ())...)
-   `effect/prefer-as` - 使用超度地图( () QQ值)
-   `effect/no-gen` - 强制效应.gen(通过 `noGen` 配置( c)
-   `effect/no-unnecessary-pipe-wrapper` - 检测不必要的管子包装器
-   `effect/no-eta-expansion` - 检测不必要的函数包装( 偏好无点样式)
-   `effect/no-unnecessary-function-alias` - 检测不必要的函数别名
-   `effect/prefer-match-tag` - 使用 Match.tag 代替 Match. when for tag
-   `effect/prefer-match-over-conditionals` - 如果声明使用匹配
-   `effect/prefer-effect-if-over-match-boolean` - 对布尔条件使用Effect.如果超过Match.值
-   `effect/prefer-match-over-ternary` - 使用 Match. value 超过三元运算符进行非布尔模式匹配
-   `effect/no-switch-statement` - 禁止所有开关语句(使用Match.value代替)
-   `effect/no-if-statement` - 如果语句(使用Effect.if、Match.value或类型特定匹配者代替),则全部禁止
-   `effect/prefer-schema-validation-over-assertions` - 使用Schema来代替类型断言
-   `effect/suggest-currying-opportunity` - 建议咖喱去除箭头功能包
-   `effect/no-intermediate-effect-variables` - 禁止储存管/影响结果,产生单用中间变量(通过 `pipeStrict` 配置( c)

## 可用出口

### 默认导出( 建议)

```typescript
// @ts-nocheck - Package types available at runtime
import effectPlugin from '@codeforbreakfast/eslint-effect';

effectPlugin.rules; // All custom rules
effectPlugin.meta; // Plugin metadata

// Configs
effectPlugin.configs.recommended; // ⭐ Recommended for most projects
effectPlugin.configs.strict; // All rules including opinionated ones
effectPlugin.configs.noGen; // Opt-in: forbid Effect.gen
effectPlugin.configs.preferMatch; // Opt-in: forbid _tag access
effectPlugin.configs.pipeStrict; // Opt-in: strict pipe rules
effectPlugin.configs.plugin; // Plugin rules only
effectPlugin.configs.functionalImmutabilityRules; // Functional immutability rules object
```

每个配置( 除 `functionalImmutabilityRules`)是一个完整的ESLint平面配置对象,有:

-   `name`: 配置标识符
-   `rules`: 规则配置
-   `plugins`: 需要的插件(如适用)

### 已命名的出口

```typescript
// @ts-nocheck - Package types available at runtime
import {
  rules, // All custom rules (for plugin registration)
  functionalImmutabilityRules, // Functional immutability rules object
} from '@codeforbreakfast/eslint-effect';
```

### 范围导入

```javascript
import rules from '@codeforbreakfast/eslint-effect/rules';
```

## 哲学

这个软件包执行严格的功能编程风格,并带有效果:

1.  **代际组成**页:1 `pipe` 组成情况 `Effect.gen`
2.  **类型安全**: 使用运行时间验证(Schema)而不是类型断言
3.  **声明模式**: 使用 `Match` 超过必要条件
4.  **可变性**: 执行只读类型和永久数据模式
5.  **边界执行**: 只在应用程序边界运行效果

## 许可证

麻省理工学院

## 常见问题

### @codeforbreakfast/eslint-effect 是什么？

执行功能编程最佳做法的效果项目ESLint规则和配置

### 如何安装 @codeforbreakfast/eslint-effect？

在项目目录运行 npm install @codeforbreakfast/eslint-effect，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：eslint（\>=8\.0\.0）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @codeforbreakfast/eslint-effect 支持 TypeScript 吗？

该包的 package\.json 没有声明类型入口。需要类型提示时，可以在 npm 上查找社区维护的 @types/codeforbreakfast\_\_eslint-effect 是否存在。

### @codeforbreakfast/eslint-effect 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @codeforbreakfast/eslint-effect 可以商用吗？

@codeforbreakfast/eslint-effect 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @codeforbreakfast/eslint-effect 的下载量有多少？

根据 npm 官方下载统计，@codeforbreakfast/eslint-effect 在 2026/10/10 – 2026/11/08 这 30 天内被下载 2,662 次，日均约 89 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @codeforbreakfast/eslint-effect 还在维护吗？

最新版本 0\.8\.5 发布于 2025/12/11（10 个月前）；至今共发布 12 个版本，其中过去 12 个月发布了 2 个；首次发布于 2025/10/06。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

