# @enfect/oxlint 中文文档

规范地址：https://npmcn.com/package/%40enfect/oxlint/

版本：0\.10\.0
npm 元数据更新时间：2026-11-02T08:55:50.836Z
中文译文更新时间：2026-11-13T17:09:14.605Z
软件包许可：MIT

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

原始 npm 页面：https://www.npmjs.com/package/%40enfect/oxlint
原文对照：https://npmcn.com/package/%40enfect/oxlint/?lang=original
项目主页：https://github.com/mpsuesser/enfect/tree/main/plugins/oxlint#readme
源码仓库：https://github.com/mpsuesser/enfect

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

- 包体积（解压后）：273 kB，8 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- 运行依赖：3 个
- 首次发布：2026-10-29T14:04:21.079Z
- 最新版本发布：2026-11-02T08:55:50.643Z
- 近 30 天下载量：5950（2026-10-14 至 2026-11-12，npm 官方下载统计）
- 已发布版本数：4（近 12 个月 4 个）

## 中文简介

Oxlint 插件, 执行效果第一开发公约

## 安装

```sh
npm install @enfect/oxlint
```

也可以使用：`pnpm add @enfect/oxlint`、`yarn add @enfect/oxlint`、`bun add @enfect/oxlint`

## README

# @enfect/oxlint (英语)

[![npm](https://img.shields.io/npm/v/@enfect/oxlint)](https://www.npmjs.com/package/@enfect/oxlint) [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://npmcn.com/package/%40enfect/oxlint/LICENSE)

有意见 [奥克林特](https://oxc.rs/docs/guide/usage/linter) 用于 [效果 v4](https://effect.website/) 驱动每个模块向Effect服务,打出出错误通道,以及功能组成. 它会标出必须的图案,原始节点 API,未打字出错, 以及其他非平面外形 在林特层,所以它们永远不会被审查.

插件飞船 **74条** 名称间距 `effect/`,包括来自 [`dmmulroy/anti-slop`](https://github.com/dmmulroy/anti-slop). 规则与 [`effect-oxlint`](https://github.com/mpsuesser/effect-oxlint) SDK并运行为标准的克克林特自定义规则.

运行时间和建议目标 **效果 4.1.0(稳定)**区域进口用途 `effect/http`, (中文(简体) ), `effect/http-api`, (中文(简体) ), `effect/process`等; 旧的 `unstable` 路径 被删除。 已标记 API `@stability unstable` 微量释放仍然可以改变. 在同一发行版本上保留直接使用的效果-家庭包.

已公布的插件被检查为oxlint 1.85. 这是其中的一部分 [感染](https://github.com/mpsuesser/enfect),该出版物还出版 克劳德代码和OpenCode的插件.

## 安装

```sh
npm install --save-dev oxlint @enfect/oxlint
# or
bun add -D oxlint @enfect/oxlint
```

TypeScript来源也作为 [`@enfect/oxlint`](https://jsr.io/@enfect/oxlint)。 。 。 .

使用生成的推荐配置 `oxlint.config.ts`数字 :

```ts
import { defineConfig } from 'oxlint';
import effect from '@enfect/oxlint';

export default defineConfig({
    extends: [effect.configs.recommended]
});
```

`configs.recommended` 通过克林特记录软件包 `jsPlugins` 并启用所有74条规则 `error` 严重. `configs.all` 也包括所有规则.

要推翻个别规则,请添加 `rules` 条目 `extends` 块 :

```ts
import { defineConfig } from 'oxlint';
import effect from '@enfect/oxlint';

export default defineConfig({
    extends: [effect.configs.recommended],
    rules: {
        'effect/avoid-native-object-helpers': 'off',
        'effect/avoid-direct-json': 'warn'
    }
});
```

如果您使用 `.oxlintrc.json`,oxlint 无法导入软件包配置对象。 配置 JS 插件和您想要的任何规则 :

```jsonc
{
    "jsPlugins": ["@enfect/oxlint"],
    "rules": {
        "effect/avoid-direct-json": "error"
    }
}
```

使用 `oxlint.config.ts` 当您想要完整生成推荐配置时.

## 规则一览

### 反斜坡规则

这些规则适用于JavaScript和TypeScript,独立于Effect导入, 建筑政策除外 `no-service-constructor-imports`。 。 。 . 他们是同一个人 `effect/` 命名空间和同时生成预设 .

| 规则 | 渔获物/例外 |
| --- | --- |
| `no-chained-type-assertions` | 嵌入 `as` 或角度-括号断言,包括括号式链条. 仅由 `as const` 被允许. |
| `no-conditional-empty-object-spread` | 以有条件的空对象分支展开对象。 无自定义 : 省略一个属性与指定不同 `undefined`。 。 。 . |
| `no-known-value-widening` | 已知的表达式流出到显式 `unknown`, (中文(简体) ), `object`,匿名对象,或开放词典目标,包括已知的传递给本地的参数 `unknown` 类型上游。 空词典累积器和有限键 `Record` 目标被允许. |
| `no-module-mocking` | 测试/测试 `mock`, (中文(简体) ), `doMock`,以及 `unstable_mockModule` 调用,包括别名进口和计算方法名称。 允许本地阴影框架名称 . |
| `no-object-parameters` | `object` 输入、含有此种内容的联盟以及范围大/透明的通用别名. |
| `no-reflect-apply` | 全球 `Reflect.apply`,包括计算访问。 本地阴影 `Reflect` 约束是允许的. |
| `no-reflect-get` | 全球 `Reflect.get`,包括计算访问。 本地阴影 `Reflect` 约束是允许的. |
| `no-runtime-typeof` | 运行时间 `typeof` 缩小。 与字符串的比较 `"undefined"` ; 可用选项启用类型保护检查。 类型级别 `typeof` 不受影响. |
| `no-service-constructor-imports` | 名称 `make<CapitalizedName>` 从 `./` 或者说 `../` 外部模块 `*.test.*` 财务报告和审定财务报表 `*.spec.*`包/路由别名的进口、默认进口和静态构造器不在它的范围内. |
| `no-shape-in-symbol-names` | 不区分大小写 `shape` 在本地拥有的识别资料中,包括私人和JSX名称。 静态成员访问诸如 `schema.shape` 允许. |
| `no-unknown-parameters` | 明确 `unknown` 参数和包含它的结合。 命名的参数 `cause` 并且允许精确的 类型上游对象. |
| `no-unknown-returns` | 向 `unknown`, (中文(简体) ), `Promise<unknown>`,或 `PromiseLike<unknown>`,包括范围/透明通用别名. |
| `no-unknown-type-aliases` | 范围/透明通用别名 `unknown`。 。 。 . |
| `no-unsafe-dictionary-type` | 基于 `unknown`, (中文(简体) ), `any`, (中文(简体) ), `object`, (中文(简体) ), `{}`,或语义等同. 一般性制约因素,例如: `T extends Record<string, unknown>` 被允许. |
| `no-widen-then-assert` | 无法改变的当地流动,将已知证据扩大到 `unknown`, (中文(简体) ), `any`, (中文(简体) ), `object`或广义的记录,然后将它恢复到较窄的类型. |
| `require-safety-comment-for-type-assertion` | 无前有后无后无后无后无后无后无后无后无后无后无后无后无后无后无后无后无后无后无后无后无后无后无后无后无后无后无后无后无后无后无后无后无后无后无后无后无后无后无后无后无后无后无后无后无后无后无后无后无后无后无后无后无后无后无后无后无后无后无. 默认标记是 `SAFETY:`。 。 。 . |

分析使用了 Oxlint 的 ESTree 和 lexical 范围, 而非 TypeScript 类型 检查器。 同一文件的别名、前置参考、语法阴影和 透明通用别名在有文件记录的情况下解决。 进口类型和 交叉文件调用签名不推断. `no-widen-then-assert` 蓄意 限制其值流分析,使其在函数边界内具有不可改变的约束.

### 替换反斜体安装

删除旧的 `anti-slop` 财务报告和审定财务报表 `anti-slop-effect` 登记日期: `jsPlugins`。 。 。 . 将两个规则名前缀替换为 `effect/`,保持现有严重程度 选项值。 登记册 `@enfect/oxlint` 一次,或使用 上面推荐的配置,以启用整个个人规则。 没有 运行时间依赖反斜坡,没有单独的效应入站点进行注册.

例如,现有的定制配置变成:

```ts
import { defineConfig } from 'oxlint';
import effect from '@enfect/oxlint';

export default defineConfig({
    extends: [effect.configs.recommended],
    rules: {
        'effect/no-runtime-typeof': ['error', { allowInTypeGuards: true }],
        'effect/require-safety-comment-for-type-assertion': [
            'error',
            { markers: ['INVARIANT', 'SAFETY'] }
        ]
    }
});
```

`allowInTypeGuards` 默认为 `false` 并允许在类型范围内直接进行检查 上位/上位函数,不是嵌入普通函数. `markers` 默认为 `['SAFETY']`; 标记为字面字符串( regex puntuation 为 ),在相配前被修剪后,必须随行 `:` 和一无所有 说明理由。 确认出口申报前的评论;评论 未经证实.

```ts
// Rejected: assertions fabricate evidence in two steps.
const user = input as unknown as User;

// Rejected: the known "start" key is erased.
const handlers: Record<string, Handler> = { start: startHandler };

// Preserve known keys while checking their values.
const preciseHandlers = { start: startHandler } satisfies Record<string, Handler>;

// Accepted by require-safety-comment-for-type-assertion:
// SAFETY: parseUserId checked the identifier before branding it.
const userId = parsedId as UserId;
```

一些现行规则有意更严格或重叠. `casting-awareness` 即使有安全评论,仍会报告断言;如果有正当理由,将关闭 断言是你的选择政策. `prefer-effect-is` 仍然可以报告 `typeof` 内部守卫,即使 `no-runtime-typeof` 允许他们. `avoid-any` 重叠 以连锁说法 `avoid-object-type` 地址 `Object`编号 :`{}` 相当 比小写 `object` 参数合同。 各独立配置.

### 尾风规则

| 规则 | 渔获物/例外 |
| --- | --- |
| `no-unsupported-tailwind-spacing` | 尾风 v4 间隔类, 以字符串和模板字元表示, 其数值不等于0. 25 的相克倍数, 例如 `gap-1.125` 或者说 `p-1.50`尾风不会给他们带来CSS,所以他们默默无闻。 消息建议在默认的0.25rem步骤上具有等同的任意值. 允许将任意值、分数和符号粘贴在模板插入上. |

覆盖的公用事业:铺垫、边距及其滚动变体; `gap`· ; `space-x`编号 :`space-y`· ; `w`, (中文(简体) ), `h`, (中文(简体) ), `size`,以及他们的 `min-`编号 :`max-` 表单; `inset` 编辑 `top`编号 :`right`编号 :`bottom`编号 :`left`编号 :`start`编号 :`end` (a) 减少员额经费; `translate-x`编号 :`-y`编号 :`-z`· ; `indent`· ; `basis`· ; `leading`; 和 : `border-spacing`备选案文前缀, 负值,以及正向或后向 `!` 已确认.

### 第一效力规则

| 规则 | 捕获到的 |
| --- | --- |
| [`avoid-any`](https://npmcn.com/package/%40enfect/oxlint/#readme-avoid-any) | `as any` 财务报告和审定财务报表 `as unknown as T` 铸造 |
| [`avoid-data-tagged-error`](https://npmcn.com/package/%40enfect/oxlint/#readme-avoid-data-tagged-error) | `Data.TaggedError` ——使用 `Schema.TaggedError` |
| [`avoid-direct-json`](https://npmcn.com/package/%40enfect/oxlint/#readme-avoid-direct-json) | `JSON.parse` 编号 : `JSON.stringify` ——使用 `Schema.fromJsonString` |
| [`avoid-direct-tag-checks`](https://npmcn.com/package/%40enfect/oxlint/#readme-avoid-direct-tag-checks) | `x._tag === "..."` 检查 - 使用 `$is` 编号 : `$match` 编号 : `Match` |
| [`avoid-expect-in-if`](https://npmcn.com/package/%40enfect/oxlint/#readme-avoid-expect-in-if) | `expect(...)` 窝在里面 `if` 测试中的块 |
| [`avoid-mutable-state`](https://npmcn.com/package/%40enfect/oxlint/#readme-avoid-mutable-state) | `let` 服务/层工厂内部装订 |
| [`avoid-native-fetch`](https://npmcn.com/package/%40enfect/oxlint/#readme-avoid-native-fetch) | 土著 `fetch()` - 使用效果 `HttpClient` |
| [`avoid-native-object-helpers`](https://npmcn.com/package/%40enfect/oxlint/#readme-avoid-native-object-helpers) | `Object.keys` 编号 : `Object.entries` 编号 : `Object.fromEntries` 包括:. |
| [`avoid-node-imports`](https://npmcn.com/package/%40enfect/oxlint/#readme-avoid-node-imports) | 裸体 `node:*` 以平台不可识别代码导入 |
| [`avoid-non-null-assertion`](https://npmcn.com/package/%40enfect/oxlint/#readme-avoid-non-null-assertion) | 这个 `!` 非虚拟断言运算符 |
| [`avoid-object-type`](https://npmcn.com/package/%40enfect/oxlint/#readme-avoid-object-type) | `Object` 财务报告和审定财务报表 `{}` 作为类型 |
| [`avoid-option-getorthrow`](https://npmcn.com/package/%40enfect/oxlint/#readme-avoid-option-getorthrow) | `.getOrThrow` 打开 `Option` 编号 : `Either` 编号 : `Result` |
| [`avoid-platform-coupling`](https://npmcn.com/package/%40enfect/oxlint/#readme-avoid-platform-coupling) | `@effect/platform-bun` 装订包中的进口 |
| [`avoid-process-env`](https://npmcn.com/package/%40enfect/oxlint/#readme-avoid-process-env) | `process.env` - 使用一个 `Config` 服务 |
| [`avoid-react-hooks`](https://npmcn.com/package/%40enfect/oxlint/#readme-avoid-react-hooks) | `useState` 编号 : `useEffect` 编号 : `useReducer` - 使用 Effect Atom VM |
| [`avoid-schema-suffix`](https://npmcn.com/package/%40enfect/oxlint/#readme-avoid-schema-suffix) | Schema 常数后缀为 `Schema` |
| [`avoid-sync-fs`](https://npmcn.com/package/%40enfect/oxlint/#readme-avoid-sync-fs) | `fs.readFileSync` 和其他同步 `fs` 电话 |
| [`avoid-try-catch`](https://npmcn.com/package/%40enfect/oxlint/#readme-avoid-try-catch) | `try` 编号 : `catch` 效果代码 |
| [`avoid-ts-ignore`](https://npmcn.com/package/%40enfect/oxlint/#readme-avoid-ts-ignore) | `@ts-ignore` 编号 : `@ts-expect-error` 评论 |
| [`avoid-untagged-errors`](https://npmcn.com/package/%40enfect/oxlint/#readme-avoid-untagged-errors) | `new Error(...)` 财务报告和审定财务报表 `instanceof Error` 可收回的失败 |
| [`avoid-yield-ref`](https://npmcn.com/package/%40enfect/oxlint/#readme-avoid-yield-ref) | `yield* ref` 编号 : `yield* deferred` 编号 : `yield* fiber` (在v4中删除) |
| [`casting-awareness`](https://npmcn.com/package/%40enfect/oxlint/#readme-casting-awareness) | `as T` 断言(不包括 `as const` 编号 : `as never`(中文(简体) ) |
| [`context-tag-extends`](https://npmcn.com/package/%40enfect/oxlint/#readme-context-tag-extends) | `Context.Tag` 编号 : `Context.GenericTag` 编号 : `Effect.Service` 遗产 `ServiceMap.*` |
| [`effect-catchall-default`](https://npmcn.com/package/%40enfect/oxlint/#readme-effect-catchall-default) | 块 `Effect.catch` 编号 : `catchCause` 吞下所有错误 |
| [`effect-promise-vs-trypromise`](https://npmcn.com/package/%40enfect/oxlint/#readme-effect-promise-vs-trypromise) | `Effect.promise` - 喜欢 `Effect.tryPromise` |
| [`effect-run-in-body`](https://npmcn.com/package/%40enfect/oxlint/#readme-effect-run-in-body) | `Effect.runSync` 编号 : `runPromise` 编号 : `runFork` 外部切入点 |
| [`imperative-loops`](https://npmcn.com/package/%40enfect/oxlint/#readme-imperative-loops) | `for` 编号 : `while` 编号 : `do…while` 域码 |
| [`maybe-prefix-requires-option`](https://npmcn.com/package/%40enfect/oxlint/#readme-maybe-prefix-requires-option) | `maybe*` 名称字段不是 `Option<T>` |
| [`no-barrel-imports`](https://npmcn.com/package/%40enfect/oxlint/#readme-no-barrel-imports) | 命名自 `effect` 桶套装 |
| [`no-cause-in-http-response`](https://npmcn.com/package/%40enfect/oxlint/#readme-no-cause-in-http-response) | `Cause.pretty`编号 :`Cause.squash`/发生原因或出错流入反应机构 |
| [`no-effect-ignore-then-as`](https://npmcn.com/package/%40enfect/oxlint/#readme-no-effect-ignore-then-as) | 冗余 `Effect.ignore` 在此之前 `Effect.as`,或者在已知的不可失的原始人上 |
| [`no-length-comparison`](https://npmcn.com/package/%40enfect/oxlint/#readme-no-length-comparison) | `.length === 0` 和朋友——使用命名的字符串/阵列上游 |
| [`no-opaque-instance-fields`](https://npmcn.com/package/%40enfect/oxlint/#readme-no-opaque-instance-fields) | 诉讼成员 `Schema.Opaque` 类 |
| [`prefer-arr-match`](https://npmcn.com/package/%40enfect/oxlint/#readme-prefer-arr-match) | 手动空/ 非空分枝—— 使用 `Arr.match` |
| [`prefer-arr-sort`](https://npmcn.com/package/%40enfect/oxlint/#readme-prefer-arr-sort) | `Array.prototype.sort` ——使用 `Arr.sort` 带有 `Order` |
| [`prefer-array-fromoption-over-option-match-empty`](https://npmcn.com/package/%40enfect/oxlint/#readme-prefer-array-fromoption-over-option-match-empty) | `Option.match` 产生 `[]` 编号 : `[v]` |
| [`prefer-duration-constructors`](https://npmcn.com/package/%40enfect/oxlint/#readme-prefer-duration-constructors) | 原始毫秒数字传递到效果计时 API |
| [`prefer-effect-fn`](https://npmcn.com/package/%40enfect/oxlint/#readme-prefer-effect-fn) | `Effect.gen` 捆绑在接地上或用于服务方法 |
| [`prefer-effect-is`](https://npmcn.com/package/%40enfect/oxlint/#readme-prefer-effect-is) | `typeof x === "string"` ——使用 `P.isString` 朋友们 |
| [`prefer-match-over-switch`](https://npmcn.com/package/%40enfect/oxlint/#readme-prefer-match-over-switch) | `switch` 语句——使用 `Match.value` |
| [`prefer-namespace-imports`](https://npmcn.com/package/%40enfect/oxlint/#readme-prefer-namespace-imports) | 从 Effect 子模块命名的进口 – 使用命名空间导入 |
| [`prefer-option-over-null`](https://npmcn.com/package/%40enfect/oxlint/#readme-prefer-option-over-null) | `T | null` 编号 : `T | undefined` 工会类型 |
| [`prefer-redacted-config`](https://npmcn.com/package/%40enfect/oxlint/#readme-prefer-redacted-config) | `Config.String("apiKey")` 密钥等 |
| [`require-effect-concurrency`](https://npmcn.com/package/%40enfect/oxlint/#readme-require-effect-concurrency) | `Effect.all` 编号 : `forEach` 编号 : `validate` 没有明确 `concurrency` |
| [`require-filter-metadata`](https://npmcn.com/package/%40enfect/oxlint/#readme-require-filter-metadata) | `Schema.makeFilter` 编号 : `makeFilterGroup` 缺少标识符/ 标题/ 描述 |
| [`require-is-prefix-for-boolean-schema-field`](https://npmcn.com/package/%40enfect/oxlint/#readme-require-is-prefix-for-boolean-schema-field) | `Schema.Boolean` 字段没有布尔上游前缀 |
| [`require-schema-type-alias`](https://npmcn.com/package/%40enfect/oxlint/#readme-require-schema-type-alias) | 不匹配导出计划常数 `export type` 别名 |
| [`throw-in-effect-gen`](https://npmcn.com/package/%40enfect/oxlint/#readme-throw-in-effect-gen) | `throw` 内部 `Effect.gen` 编号 : `Effect.fn` 编号 : `Effect.fnUntraced` |
| [`use-clock-service`](https://npmcn.com/package/%40enfect/oxlint/#readme-use-clock-service) | `new Date()` 编号 : `Date.now()` 编号 : `Date.UTC()` ——使用 `Clock` 编号 : `DateTime` |
| [`use-command-executor-service`](https://npmcn.com/package/%40enfect/oxlint/#readme-use-command-executor-service) | `child_process` 编号 : `node:child_process` 进口 |
| [`use-console-service`](https://npmcn.com/package/%40enfect/oxlint/#readme-use-console-service) | `console.*` ——使用 `Effect.log*` 编号 : `Console` |
| [`use-filesystem-service`](https://npmcn.com/package/%40enfect/oxlint/#readme-use-filesystem-service) | `fs` 编号 : `node:fs` 编号 : `fs/promises` 进口 |
| [`use-http-client-service`](https://npmcn.com/package/%40enfect/oxlint/#readme-use-http-client-service) | `http` 编号 : `https` 编号 : `node:http` 编号 : `node:https` 进口 |
| [`use-path-service`](https://npmcn.com/package/%40enfect/oxlint/#readme-use-path-service) | `path` 编号 : `node:path` 进口 |
| [`use-random-service`](https://npmcn.com/package/%40enfect/oxlint/#readme-use-random-service) | `Math.random()` - 使用 `Random` 服务 |
| [`use-temp-file-scoped`](https://npmcn.com/package/%40enfect/oxlint/#readme-use-temp-file-scoped) | `os.tmpdir()` / 无范围 `makeTempFile` 编号 : `makeTempDirectory` |
| [`vm-in-wrong-file`](https://npmcn.com/package/%40enfect/oxlint/#readme-vm-in-wrong-file) | 查看外部的模型接口和层 `.vm.ts` 文件 |
| [`yield-in-for-loop`](https://npmcn.com/package/%40enfect/oxlint/#readme-yield-in-for-loop) | `yield*` 内部 `for` 循环——使用 `Effect.forEach` |

* * *

### `avoid-any`

`as any` 财务报告和审定财务报表 `as unknown as T` 清除类型安全。 验证未知数据 `Schema.decodeUnknown*`,用通称保存类型,或固定上游类型.

```ts
// ❌
const user = data as any;
const config = JSON.parse(raw) as unknown as Config;

// ✅
const user = yield* Schema.decodeUnknownEffect(User)(data);
const config = yield* Schema.decodeUnknownEffect(Schema.fromJsonString(AppConfig))(raw);
```

### `avoid-data-tagged-error`

`Data.TaggedError` 不与 Schema 编码/ 解码管道合并。 使用 `Schema.TaggedError` 用于需要解码、编码或RPC运输的公共错误.

```ts
// ❌
class NotFound extends Data.TaggedError('NotFound')<{ id: string }> {}
```

```ts
import * as Schema from 'effect/Schema';

class NotFound extends Schema.TaggedError<NotFound>()(
    'NotFound',
    { id: Schema.String }
) {}
```

### `avoid-direct-json`

`JSON.parse` 生产 `any`· ; `JSON.stringify` 不验证域名合同。 使用 `Schema.fromJsonString(MySchema)` 键入边框或 `Schema.fromJsonString(Schema.Unknown)` 对于未知的有效载荷.

```ts
// ❌
const user: User = JSON.parse(raw);
const body = JSON.stringify(payload);
```

```ts
import * as Schema from 'effect/Schema';

class User extends Schema.Class<User>('User')({ id: Schema.String }) {}
const decodeUser = Schema.decodeUnknownEffect(Schema.fromJsonString(User));
const encodeUser = Schema.encodeEffect(Schema.fromJsonString(User));
const decodeUnknownJson = Schema.decodeUnknownEffect(Schema.fromJsonString(Schema.Unknown));
```

### `avoid-direct-tag-checks`

阅读 `_tag` 直接的情侣将网站呼叫歧视的弦。 使用自动生成 `$is` 编号 : `$match` 帮助者或 `Match.value` 因此重命名一个变体是一个被打入重构的.

```ts
// ❌
if (result._tag === 'Success') return result.value;
switch (msg._tag) {
    case 'Loaded':
        /* ... */
}

// ✅
if (Result.isSuccess(result)) return result.success;
return Match.value(msg).pipe(
    Match.tag('Loaded', (m) => /* ... */),
    Match.exhaustive
);
```

### `avoid-expect-in-if`

`expect(...)` 嵌入一个 `if` 当条件不实时, 屏蔽默默通过。 紧紧的先说.

```ts
// ❌
if (result) {
    expect(result.id).toBe('abc');
}

// ✅
expect(result).toBeDefined();
expect(result.id).toBe('abc');
```

### `avoid-mutable-state`

`let` 服务或层工厂内部的束缚 隐藏纤维可见状态和生命周期行为。 使用 `Ref`, (中文(简体) ), `SynchronizedRef`,或 `Effect.cached` 因此,并行访问是明确的. `let` 纯洁的助手和狭长的瞄准镜是好的.

```ts
// ❌
export const CounterLive = Layer.effect(
    Counter,
    Effect.gen(function* () {
        let count = 0;
        return Counter.of({ inc: () => Effect.sync(() => count++) });
    })
);

// ✅
export const CounterLive = Layer.effect(
    Counter,
    Effect.gen(function* () {
        const count = yield* Ref.make(0);
        return Counter.of({ inc: () => Ref.update(count, (n) => n + 1) });
    })
);
```

### `avoid-native-fetch`

土著 `fetch()` 返回 a `Promise<Response>` 带有未类型错误。 效应 `HttpClient` 给您输入错误, 请求/ 响应计划, 以及可测试的层替换 .

```ts
// ❌
const res = await fetch('/api/users');
const users = await res.json();

// ✅
const client = yield* HttpClient.HttpClient;
const users =
    yield* client
        .get('/api/users')
        .pipe(Effect.flatMap(HttpClientResponse.schemaBodyJson(UserList)));
```

### `avoid-native-object-helpers`

`Object.keys` 返回时 `string[]` (无) `keyof T`(三); `Object.entries` 丢失值类型。 使用 `effect/Record` 类型安全等同物的助手.

```ts
// ❌
const keys = Object.keys(user);
const entries = Object.entries(config);
const obj = Object.fromEntries(pairs);

// ✅
import * as R from 'effect/Record';
const keys = R.keys(user);
const entries = R.toEntries(config);
const obj = R.fromEntries(pairs);
```

### `avoid-node-imports`

`node:*` 导入将域码绑定为单个运行时间。 使用抽象服务 `effect` 并提供运行时边界的平台执行。 专门规则涵盖最常见的案件`use-filesystem-service`, (中文(简体) ), `use-path-service`, (中文(简体) ), `use-command-executor-service`, (中文(简体) ), `use-http-client-service`)),这个规则是"包罗万象".

```ts
// ❌
import { createHash } from 'node:crypto';
import { Readable } from 'node:stream';

// ✅  Provide the platform layer at the runtime boundary
import { Digest, SecureRandom } from 'effect/crypto';
import * as Stream from 'effect/Stream';
```

### `avoid-non-null-assertion`

`!` 告诉编译器"相信我",错误时会崩溃. 模式缺席 `Option`,解码未知形状通过 `Schema.decodeUnknown*`,或与 `?.` 编号 : `??` 编号 : `Option.fromNullishOr`。 。 。 .

```ts
// ❌
const name = user!.profile!.displayName!;

// ✅
const name = Option.fromNullishOr(user).pipe(
    Option.flatMapNullishOr((u) => u.profile?.displayName),
    Option.getOrElse(() => 'Anonymous')
);
```

### `avoid-object-type`

`Object` 不提供类型安全,以及 `{}` 匹配任何非nullish 值(包括 `42` 财务报告和审定财务报表 `"hi"`) (中文(简体) ). 使用特定的接口, `Record<string, unknown>`,或一个 `Schema.Class`。 。 。 .

```ts
// ❌
function merge(a: object, b: {}): object { ... }

// ✅
function merge<A extends Record<string, unknown>>(a: A, b: Partial<A>): A { ... }
```

### `avoid-option-getorthrow`

`.getOrThrow` 击败点 `Option` 编号 : `Either` 编号 : `Result` 扔到那个类型 承诺一个完全处理者。 使用 `match`, (中文(简体) ), `getOrElse`,或 `map`。 。 。 .

```ts
// ❌
const value = Option.getOrThrow(maybeUser);

// ✅
const value = Option.match(maybeUser, {
    onNone: () => defaultUser,
    onSome: (u) => u
});
```

### `avoid-platform-coupling`

软件包 `packages/*/binding/` 使用抽象服务来包裹外部系统. 此规则拒绝混凝土 Bun平台在那里的导入;在应用程序的运行时间切入点提供平台层.

```ts
// ❌  packages/myapp/binding/index.ts
import { BunHttpServer } from '@effect/platform-bun';

// ✅  packages/myapp/src/main.ts
import { BunHttpServer } from '@effect/platform-bun';
```

### `avoid-process-env`

`process.env` 是无类型、未经测试和全球性的. `Config.*` 以默认值和验证来构建打字,分层,可编辑的配置.

```ts
// ❌
const apiKey = process.env.API_KEY!;
const port = parseInt(process.env.PORT ?? '3000');

// ✅
const apiKey = yield* Config.Redacted('API_KEY');
const port = yield* Config.Int('PORT').pipe(Config.withDefault(3000));
```

### `avoid-react-hooks`

反应钩会分散状态、效果和渲染 跨越单个部件 具有效应原子的VMs保持原子状态,作用,组件作为纯成像器.

```ts
// ❌
function Profile({ id }: Props) {
    const [user, setUser] = useState<User>();
    useEffect(() => { fetchUser(id).then(setUser); }, [id]);
    return <div>{user?.name}</div>;
}

// ✅
// profile.vm.ts
export const userAtom = Atom.family((id: string) =>
    Atom.fn(Effect.fn('fetchUser')(function* () { ... }))
);

// profile.tsx
function Profile({ id }: Props) {
    const user = useAtomValue(userAtom(id));
    return <div>{user.name}</div>;
}
```

### `avoid-schema-suffix`

Schema常数代表一个域类型,而不是"一个类型的一个计划". 以概念命名( E)`User`而不是建筑(`UserSchema`)——这与如何 `Schema.Class` 名称并保留类型和实例.

```ts
// ❌
const UserSchema = Schema.Struct({ id: Schema.String });

// ✅
const User = Schema.Struct({ id: Schema.String });
export type User = typeof User.Type;
```

### `avoid-sync-fs`

同步 `fs` 呼叫屏蔽事件循环。 使用 `FileSystem` 从 `effect/FileSystem` 用于ASync,可相容,可测试的文件一/O.

```ts
// ❌
const text = fs.readFileSync(path, 'utf8');
fs.writeFileSync(path, data);

// ✅
const fs = yield* FileSystem.FileSystem;
const text = yield* fs.readFileString(path);
yield* fs.writeFileString(path, data);
```

### `avoid-try-catch`

`try` 编号 : `catch` 不显示函数返回类型的失败。 使用 `Effect.try` 或者说 `Effect.tryPromise` 与 `Schema.TaggedError` 以保留输入频道中的预期错误.

```ts
// ❌
try {
    return JSON.parse(raw);
} catch (e) {
    return null;
}

// ✅
return (
    yield* Effect.try({
        try: () => externalParser(raw),
        catch: (cause) => new ParseFailed({ cause })
    })
);
```

### `avoid-ts-ignore`

`@ts-ignore` 财务报告和审定财务报表 `@ts-expect-error` 遮盖真实的bug,当基础类型改变时会静静地腐烂. 在源头修正类型.

```ts
// ❌
// @ts-ignore
const result = someApi.experimental.method();

// ✅
// Augment the third-party type or wrap in a typed adapter
declare module 'some-api' {
    interface ExperimentalApi {
        method(): Result;
    }
}
```

### `avoid-untagged-errors`

`Schema.TaggedError` 给每个域失败模式一个标记 `catchTag` 编号 : `catchTags` 可在类型层面加以歧视。 使用 `Schema.isSchemaError` 用于解码器故障; 诸如 `makeEffect` 直接失败 `SchemaIssue.Issue`。 。 。 .

```ts
// ❌
throw new Error('User not found');
if (err instanceof Error) return null;

// ✅
class UserNotFound extends Schema.TaggedError<UserNotFound>()(
    'UserNotFound', { id: Schema.String }
) {}

yield* Effect.fail(new UserNotFound({ id }));
yield* effect.pipe(Effect.catchTag('UserNotFound', () => Effect.succeed(null)));
```

### `avoid-yield-ref`

直接 `yield* ref` 编号 : `yield* deferred` 编号 : `yield* fiber` 编号 : `yield* latch` 在Effect v4中被删除. 使用明确的方法调用.

```ts
// ❌
const value = yield* counter;
const result = yield* deferred;

// ✅
const value = yield* Ref.get(counter);
const result = yield* Deferred.await(deferred);
const exit = yield* Fiber.join(fiber);
yield* Latch.await(latch);
```

### `casting-awareness`

每个 `as T` 断言是检查点:铸造是否多余? 通用软件或 `Schema.decodeUnknownEffect` 换掉? 上游型号需要修理吗? 规则豁免 `as const` 财务报告和审定财务报表 `as never`;这种豁免并不表示没有限制的断言.

```ts
// ❌
const items = (data as Array<User>).filter((u) => u.active);

// ✅
const items =
    yield* Schema.decodeUnknownEffect(Schema.Array(User))(data).pipe(
        Effect.map(Arr.filter((u) => u.active))
    );

// ✅  as const is fine
const STATUSES = ['Pending', 'Active', 'Closed'] as const;
```

### `context-tag-extends`

`class FooTag extends Context.Tag(...)`, (中文(简体) ), `Context.GenericTag`, (中文(简体) ), `Effect.Service`和遗产 `ServiceMap.*` 在Effect v4中别名全部被删除或被取代. 定义服务 `Context.Service` 并直接命名它们——否 `*Tag` 后缀.

```ts
// ❌
class UserRepoTag extends Context.Tag('UserRepo')<UserRepoTag, Service>() {}
const UserRepo = Context.GenericTag<Service>('UserRepo');
class UserRepo extends Effect.Service<Service>()('UserRepo', { ... }) {}

// ✅
class UserRepo extends Context.Service<UserRepo, Service>()('UserRepo') {}
```

### `effect-catchall-default`

块 `Effect.catch` 编号 : `Effect.catchCause` 返回默认值会悄悄地吞入每一个失败模式——包括那些你不知道的模式. 使用 `catchTag` 编号 : `catchTags` 目标恢复.

```ts
// ❌
effect.pipe(Effect.catch(() => Effect.succeed(defaultUser)));

// ✅
effect.pipe(
    Effect.catchTags({
        UserNotFound: () => Effect.succeed(defaultUser),
        NetworkError: (e) => Effect.fail(e) // re-raise the rest
    })
);
```

### `effect-promise-vs-trypromise`

`Effect.promise` 将拒绝视为输入出错通道以外的缺陷。 缺陷/因为处理者仍然可以观察到它们. 使用 `Effect.tryPromise` 对于预期的拒绝,所以呼叫者可以用 `catchTag`。 。 。 .

```ts
// ❌
const user = yield* Effect.promise(() => fetchUser(id));

// ✅
const user =
    yield* Effect.tryPromise({
        try: () => fetchUser(id),
        catch: (cause) => new FetchFailed({ cause })
    });
```

### `effect-run-in-body`

`Effect.runSync` 编号 : `runPromise` 编号 : `runFork` 将程序崩溃到一个具体值。 让他们留在边界`main.ts`,测试带, HTTP 路由处理器)并返回 `Effect` 其他任何地方的价值.

```ts
// ❌  inside a service method
const get = (id: string) => {
    const user = Effect.runSync(fetchUser(id));
    return user;
};

// ✅
const get = (id: string) => fetchUser(id);
```

### `imperative-loops`

`for`, (中文(简体) ), `while`,以及 `do…while` 隐藏着转变的意图 使用 `Arr.map`, (中文(简体) ), `Arr.filter`, (中文(简体) ), `Arr.filterMap`, (中文(简体) ), `Arr.reduce`,或 `Effect.forEach` 所以操作在页面上.

```ts
// ❌
const names: Array<string> = [];
for (const user of users) {
    if (user.active) names.push(user.name);
}
```

```ts
import * as Arr from 'effect/Array';
import * as Result from 'effect/Result';

declare const users: ReadonlyArray<{ readonly active: boolean; readonly name: string }>;
const names = Arr.filterMap(users, (u) =>
    u.active ? Result.succeed(u.name) : Result.fail(undefined)
);
```

### `no-barrel-imports`

这种更严格的进口政策明确了每个依赖者的自有模块。 从子模块导入命名空间; 根函数导出, 如 `pipe` 财务报告和审定财务报表 `flow` 属于 `effect/Function`。这是一种风格政策,而不是对进口进行命名的主张.

```ts
// ❌
import { Effect, Array as Arr, Option } from 'effect';

// ✅
import * as Effect from 'effect/Effect';
import * as Arr from 'effect/Array';
import * as Option from 'effect/Option';
```

### `no-opaque-instance-fields`

`Schema.Opaque` 类是纯粹的类型级包装器——它们除了基本计划之外没有运行时间特征. 添加实例方法或字段会把它们变成某种系统无法再视为不透明的东西.

```ts
// ❌
class UserId extends Schema.Opaque<UserId>()(Schema.String) {
    greet() {
        return `Hello ${this.toString()}`;
    }
}

// ✅
class UserId extends Schema.Opaque<UserId>()(Schema.String) {}
const greet = (id: UserId) => `Hello ${id}`;
```

### `prefer-arr-match`

手动 `.length === 0` 编号 : `.length > 0` 分支模糊了空对非空意图. `Arr.match` 使两个分支都清晰,并给你身体中非空阵列的见证.

```ts
// ❌
if (items.length === 0) return placeholder;
return list(items);

// ✅
return Arr.match(items, {
    onEmpty: () => placeholder,
    onNonEmpty: (xs) => list(xs)
});
```

### `prefer-arr-sort`

`Array.prototype.sort` 变异在原地, 排序词典默认, 没有概念的 `Order`。 。 。 . `Arr.sort` 不可改变,用 `Order` 组合器 .

```ts
// ❌
const sorted = [...users].sort((a, b) => a.age - b.age);

// ✅
const sorted = Arr.sort(
    users,
    Order.mapInput(Order.Number, (u: User) => u.age)
);
```

### `prefer-duration-constructors`

原始毫秒升为 `Effect.sleep`, (中文(简体) ), `Schedule.spaced`等,读取差. `Duration.seconds`, (中文(简体) ), `Duration.minutes`, (中文(简体) ), `Duration.millis` 保持单位在呼叫地点.

```ts
// ❌
yield* Effect.sleep(5000);
const sched = Schedule.spaced(60_000);

// ✅
yield* Effect.sleep(Duration.seconds(5));
const sched = Schedule.spaced(Duration.minutes(1));
```

### `prefer-effect-fn`

`Effect.gen(function*() { ... })` 分配给一个 `const`,或作为一种服务方法,缺乏所附的跨度名称. `Effect.fn("name")(function*() { ... })` 增加了自动追踪.

```ts
// ❌
const getUser = (id: string) => Effect.gen(function* () { ... });

const make = Effect.gen(function* () {
    return UserRepo.of({
        get: (id) => Effect.gen(function* () { ... })
    });
});

// ✅
const getUser = Effect.fn('getUser')(function* (id: string) { ... });

const make = Effect.gen(function* () {
    return UserRepo.of({
        get: Effect.fn('UserRepo.get')(function* (id) { ... })
    });
});
```

### `prefer-effect-is`

`typeof x === "string"` 是不可分的 而且不会像Effect那样 将结合类型缩小 `Predicate` 帮手.

```ts
// ❌
if (typeof value === 'string') return value;
if (typeof n === 'number' && n > 0) return n;

// ✅
import * as P from 'effect/Predicate';
if (P.isString(value)) return value;
if (P.isNumber(n) && n > 0) return n;
```

### `prefer-match-over-switch`

`switch` 并非详尽无遗(TypeScript无法证明每个案件都得到处理),也不用管子作曲. `Match.value` 是详尽无遗的,表现层面的,和管道友好的.

```ts
// ❌
switch (status) {
    case 'Pending':
        return spinner();
    case 'Active':
        return view();
    case 'Closed':
        return summary();
}

// ✅
return Match.value(status).pipe(
    Match.when('Pending', () => spinner()),
    Match.when('Active', () => view()),
    Match.when('Closed', () => summary()),
    Match.exhaustive
);
```

### `prefer-namespace-imports`

使用命名空间导入用于带有 Canonic 化名的助手模块( Name`Arr` 页:1 `effect/Array`, (中文(简体) ), `Option`, (中文(简体) ), `R` 页:1 `effect/Record`(见A/C.5/49/70,附件)。 命名区域进口, 如 `import { HttpClient } from 'effect/http'` 继续有效.

```ts
// ❌
import { map, filter } from 'effect/Array';
import { Array } from 'effect';

// ✅
import * as Arr from 'effect/Array';
import * as Effect from 'effect/Effect';
```

### `prefer-option-over-null`

`T | null` 编号 : `T | undefined` 不作曲:每个呼叫者必须重复无效检查. `Option<T>` 船舶 `map`, (中文(简体) ), `flatMap`, (中文(简体) ), `match`, (中文(简体) ), `getOrElse`还有朋友.

```ts
// ❌
function find(id: string): User | null { ... }

// ✅
function find(id: string): Option.Option<User> { ... }
```

### `prefer-redacted-config`

配置密钥, 其名称通常会识别一个密钥( N)`apiKey`, (中文(简体) ), `authToken`, (中文(简体) ), `password`, (中文(简体) ), `privateKey`, (中文(简体) ), `dsn`应使用 `Config.Redacted(...)` 或者说 `Schema.Redacted` 内部 `Config.schema`用于 `Config.NonEmptyString`中,保留约束 `Config.schema(Schema.Redacted(Schema.NonEmptyString), key)`。还检测出后遗症小写装载器。 校正口罩记录和检查;它并不妨碍有意解围或所有编码.

```ts
// ❌
const apiKey = yield* Config.String('apiKey');
const cfg =
    yield* Config.schema(
        Schema.Struct({
            apiKey: Schema.String
        })
    );
```

```ts
import * as Config from 'effect/Config';
import * as Schema from 'effect/Schema';

const apiKey = Config.Redacted('apiKey');
const nonEmptyToken = Config.schema(Schema.Redacted(Schema.NonEmptyString), 'TOKEN');
const cfg = Config.schema(
    Schema.Struct({
        apiKey: Schema.Redacted(Schema.String)
    })
);
```

### `require-effect-concurrency`

`Effect.all`, (中文(简体) ), `Effect.forEach`, (中文(简体) ), `Effect.validate`,朋友默默地默认顺序执行. 顺序有时是正确的——但它是一个货币决定,因此应该在呼叫站点进行复核.

```ts
// ❌
yield* Effect.forEach(ids, fetchUser);

// ✅
yield* Effect.forEach(ids, fetchUser, { concurrency: 'unbounded' });
yield* Effect.forEach(ids, fetchUser, { concurrency: 4 });
yield* Effect.forEach(ids, fetchUser, { concurrency: 1 }); // explicit sequential
```

### `require-filter-metadata`

`Schema.makeFilter` 财务报告和审定财务报表 `Schema.makeFilterGroup` 生成可重复使用的验证器。 无 `identifier`, (中文(简体) ), `title`,以及 `description` 它们在错误消息和 OpenAPI 文件中作为不透明的blobs 出现.

```ts
// ❌
const PositiveInt = Schema.makeFilter((n: number) => n > 0);

// ✅
const PositiveInt = Schema.makeFilter((n: number) => n > 0, {
    identifier: 'PositiveInt',
    title: 'Positive integer',
    description: 'A whole number strictly greater than zero.'
});
```

### `require-schema-type-alias`

导出 `Schema.Struct` 编号 : `Schema.TaggedStruct` 编号 : `Schema.Literals` 常数在值名时不带类型脚本。 和他们配对 `export type Foo = typeof Foo.Type` 因此,进口商可以指推断出的类型.

警卫,检查`Schema.isIncluding`, (中文(简体) ), `Schema.isBetweenLength`过滤器, 等同,格式化器不是计划值,不需要这个别名.

```ts
// ❌
export const User = Schema.Struct({ id: Schema.String });

// ✅
export const User = Schema.Struct({ id: Schema.String });
export type User = typeof User.Type;
```

### `throw-in-effect-gen`

`throw` 内部 `Effect.gen` 编号 : `Effect.fn` 编号 : `Effect.fnUntraced` 成为输入错误通道外的缺陷。 使用 `yield* Effect.fail(new MyError(...))` (或 `yield* new MyTaggedError({ ... })`对预期的失败。 直击和 `try:` 双臂 `Effect.tryPromise` 编号 : `Effect.try` 被排除在外,因为这些界限 捕捉掷出.

```ts
// ❌
Effect.gen(function* () {
    if (!user) throw new Error('User missing');
    return user;
});

// ✅
Effect.gen(function* () {
    if (!user) return yield* Effect.fail(new UserMissing({ id }));
    return user;
});
```

### `use-clock-service`

`new Date()` 编号 : `Date.now()` 编号 : `Date.UTC()` 是非决定性的和不可测试的。 使用 `Clock` 服务或服务 `DateTime` 模块,使测试可以冻结时间.

```ts
// ❌
const now = new Date();
const ms = Date.now();

// ✅
const now = yield* DateTime.now;
const ms = yield* Clock.currentTimeMillis;
```

### `use-command-executor-service`

`child_process` 编号 : `node:child_process` 链接代码与节点进程模型并生成未打出的错误. 使用 `ChildProcessSpawner` + 键 `ChildProcess` 从 `effect/process` 用于打出、放出、可混合过程产卵。 提供运行时边界的平台产能层.

```ts
// ❌
import { spawn } from 'node:child_process';
const proc = spawn('git', ['status']);
```

```ts
import * as Effect from 'effect/Effect';
import { ChildProcess, ChildProcessSpawner } from 'effect/process';

const status = Effect.gen(function* () {
    const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;
    return yield* spawner.string(ChildProcess.make('git', ['status']));
});
```

### `use-console-service`

`console.*` 写到 stdout / stderr 不包含跨度、结构化字段或测试捕获 。 使用 `Effect.logInfo` 编号 : `logError` 编号 : `logWarning` 编号 : `logDebug` (首选),或 `Console` 服务.

```ts
// ❌
console.log('Fetched user', user.id);
console.error('Failed', err);

// ✅
yield* Effect.logInfo('Fetched user').pipe(
    Effect.annotateLogs('userId', user.id)
);
yield* Effect.logError('Failed').pipe(Effect.annotateLogs('cause', err));
```

### `use-filesystem-service`

`fs`, (中文(简体) ), `node:fs`,以及 `fs/promises` 给节点的运行时间绑上代码 这个 `FileSystem` 服务从 `effect/FileSystem` 可移植、可分层替换,并与 `Stream`, (中文(简体) ), `Scope`,其余的效应.

```ts
// ❌
import * as fs from 'node:fs/promises';
const text = await fs.readFile(path, 'utf8');

// ✅
import * as FileSystem from 'effect/FileSystem';
const fs = yield* FileSystem.FileSystem;
const text = yield* fs.readFileString(path);
```

### `use-http-client-service`

直接 `http` 编号 : `https` 进口暴露出低水平运输装卸。 使用 `HttpClient`, (中文(简体) ), `HttpClientRequest`,以及 `HttpClientResponse` 从 `effect/http` 用于输入响应和可测试层替换。 明确添加重试,并仅用于经证明具有能力的行动.

```ts
// ❌
import * as https from 'node:https';
https.get(url, (res) => { ... });

// ✅
const client = yield* HttpClient.HttpClient;
const json = yield* client.get(url).pipe(
    Effect.flatMap(HttpClientResponse.schemaBodyJson(Payload))
);
```

### `use-path-service`

`node:path` 视运行时间而定,是Posix-or-Windows的口味。 这个 `Path` 服务从 `effect/Path` 明确了您使用的哪一种变体 可测试/可嘲弄.

```ts
// ❌
import * as path from 'node:path';
const full = path.join(dir, name);

// ✅
import * as Path from 'effect/Path';
const path_ = yield* Path.Path;
const full = path_.join(dir, name);
```

### `use-random-service`

`Math.random()` 绕过 Effect 的随机服务。 使用 `Random.withSeed` 为可重复序列. `Random.nextIntBetween(min, max)` 默认情况下包含两个终点; 使用 `{ halfOpen: true }` 排除上层界限.

```ts
// ❌
const n = Math.floor(Math.random() * 100);
```

```ts
import * as Random from 'effect/Random';

const n = Random.nextIntBetween(0, 100, { halfOpen: true }).pipe(
    Random.withSeed('example')
);
```

### `use-temp-file-scoped`

`os.tmpdir()` 和无范围 `FileSystem.makeTempFile` 编号 : `makeTempDirectory` 程序崩溃时会泄露临时文件 。 使用 `FileSystem.makeTempFileScoped` 编号 : `makeTempDirectoryScoped` 所以,清理是绑在 `Scope`。 。 。 .

```ts
// ❌
import { tmpdir } from 'node:os';
const dir = path.join(tmpdir(), 'work');

// ✅
const fs = yield* FileSystem.FileSystem;
const dir = yield* fs.makeTempDirectoryScoped();
```

### `vm-in-wrong-file`

查看模型界面及其层属于 `.vm.ts` 文档。 与构件并排使渲染和状态管理之间的接合平平分——接合是VM图案的整体点.

```ts
// ❌  profile.tsx
export interface ProfileVM { ... }
export const ProfileVMLive = Layer.effect(...);

// ✅  profile.vm.ts
export interface ProfileVM { ... }
export const ProfileVMLive = Layer.effect(...);
```

### `yield-in-for-loop`

`yield*` 内置 a `for` 循环强制顺序执行并隐藏迭代意图. `Effect.forEach` 是宣说和平行的.

```ts
// ❌
for (const id of ids) {
    yield* fetchUser(id);
}

// ✅
yield* Effect.forEach(ids, fetchUser, { concurrency: 'unbounded' });
```

* * *

### `maybe-prefix-requires-option`

命名的字段 `maybeX` 承诺 `Option<X>`。使用平原前缀 `T | null`, (中文(简体) ), `T | undefined`,或 Schema 可选/可忽略字段打破读者的期望.

`maybe*` 名称应打入为 `Option<T>` 在类型脚本中 `Schema.Option(...)` 编号 : `Schema.OptionFromNullishOr(...)` 在司马结构。 如果该值真的无效而非可选,则重命名为 `nullableX`。 。 。 .

### `no-effect-ignore-then-as`

`Effect.ignore` 丢弃成功值和错误通道。 当它出现之前 `Effect.as(...)`,则 `as` 已丢弃成功值, 因此 `ignore` 只能悄悄地消除失败.

规则也是旗帜 `Effect.ignore` 在已知的不可倒计时原始物上,没有可以忽略的错误通道.

### `no-length-comparison`

手动 `.length === 0`, (中文(简体) ), `.length > 0`,而相关的检查则隐藏该值是字符串还是数组。 首选命名的上游,例如 `Str.isEmpty`, (中文(简体) ), `Str.isNonEmpty`, (中文(简体) ), `Arr.isReadonlyArrayEmpty`, (中文(简体) ), `Arr.isReadonlyArrayNonEmpty`,或与 `Arr.match`。 。 。 .

### `prefer-array-fromoption-over-option-match-empty`

`Option<A>` 改为 `ReadonlyArray<A>` 实值 `Array.fromOption`。拼写为 `Option.match({ onNone: () => [], onSome: (v) => [v] })` 掩盖了意图.

### `require-is-prefix-for-boolean-schema-field`

Boolean Schema 字段应读作呼叫站点的上游. 使用诸如 `is*`, (中文(简体) ), `has*`, (中文(简体) ), `can*`, (中文(简体) ), `should*`, (中文(简体) ), `was*`,或 `will*` 页:1 `Schema.Boolean` 字段.

### `no-cause-in-http-response`

`Cause.pretty`编号 :`Cause.squash` 使全部失败细节——缺陷堆栈痕迹,解码内部——成为文本. 直接通过 `.message`, (中文(简体) ), `String(...)`,或模板插值)入HTTP响应机构将内部故障变为信息披露. 登录源服务器侧并返回一个通用正文 .

```ts
// ❌
const failureResponse = (cause: Cause.Cause<unknown>) =>
    HttpServerResponse.text(Cause.pretty(cause), { status: 500 });

// ✅
const failureResponse = (cause: Cause.Cause<unknown>) =>
    Effect.logError(`Request failed: ${Cause.pretty(cause)}`).pipe(
        Effect.as(HttpServerResponse.text('Internal error.', { status: 500 }))
    );
```

## 取缔

所有规则都尊重克林特的标准禁用指令:

```ts
// oxlint-disable-next-line effect/<rule-name> -- reason

/* oxlint-disable effect/<rule-name> -- reason */
// ... block ...
/* oxlint-enable effect/<rule-name> */
```

尾声 `-- <reason>` 任何超过单一公关审查的抑制措施都受到鼓励.

## 发展

从寄存器根 :

```sh
bun install
bun run --filter @enfect/oxlint test   # Vitest on Node; oxlint's RuleTester refuses Bun
bun run check                          # format, lint, and typecheck
```

每一个规则都生活在 `src/rules/<rule-name>.ts` 有兄弟的测试 `test/rules/<rule-name>.test.ts`规则SDK在 [`effect-oxlint`](https://github.com/mpsuesser/effect-oxlint)。 。 。 .

许多规则都有Ast -grep对应的 [`@enfect/patterns`](https://npmcn.com/package/packages/patterns),代理插件在之后运行 每个写.

## 许可证

麻省理工学院. 反自流规则和固定装置在 [`licenses/anti-slop.txt`](https://npmcn.com/package/%40enfect/oxlint/licenses/anti-slop.txt); 见 [`licenses/README.md`](https://npmcn.com/package/%40enfect/oxlint/licenses/README.md) 因为来源.

## 常见问题

### @enfect/oxlint 是什么？

Oxlint 插件, 执行效果第一开发公约

### 如何安装 @enfect/oxlint？

在项目目录运行 npm install @enfect/oxlint，或使用 pnpm add / yarn add / bun add。

### @enfect/oxlint 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @enfect/oxlint 支持 ESM 还是 CommonJS？

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

### @enfect/oxlint 可以商用吗？

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

### @enfect/oxlint 的下载量有多少？

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

### @enfect/oxlint 还在维护吗？

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

