# Effect Language Service (TSRS, TypeScript-Go and Oxlint)
A wrapper for both [TSRS](https://github.com/oxc-project/tsrs) and [TypeScript-Go](https://github.com/microsoft/TypeScript-Go) that builds the Effect Language Service, providing Effect-TS diagnostics and quick fixes.
<!-- supported-components:start -->
## Supported Package Versions
The following target package versions are supported by `@effect/tsgo@0.67.4`:
| Component | Supported versions |
|---|---|
| TypeScript | `7.0.2`, `7.1.0-beta`, `7.1.0-dev.20261105.1` |
| tsrs | `0.22.0-ts7.1.0-beta` |
| Oxlint | `1.88.0`, `1.89.0`, `1.90.0`, `1.91.0` |
| oxlint-tsgolint | `7.0.2004`, `7.0.2005`, `7.0.2006` |
<!-- supported-components:end -->
## Installation
The setup of the LSP (both tsgo and tsrs) can be performed via the command line interface:
```bash
# Interactive and guided setup for human friends
npx @effect/tsgo setup
# Non-interactive, for LLM friends
npx @effect/tsgo setup --help
```
This will guide you through the installation process, which includes:
1. Adding the `@effect/tsgo` dependency to your project.
2. Configuring your `tsconfig.json` to use the Effect Language Service plugin.
3. Adjusting plugin options to your preference.
4. Hinting at any additional editor configuration needed to ensure the LSP is active.
> [!NOTE]
> At the moment, you still need a native TypeScript install alongside `@effect/tsgo`: `typescript` >= 7 (e.g. `typescript@latest` or `typescript@next`) or an alias such as `@typescript/native`. `effect-tsgo patch` tries `typescript`, then `@typescript/native`, and accepts `--typescript-package <name>` to try a custom package name first.
### Run the patched tools without patching
`effect-tsgo patch` rewrites files inside `node_modules`, which is not possible (or not desirable) with shared or read-only package stores, such as the pnpm global virtual store, Yarn PnP or Nix. Instead, `effect-tsgo` can run the Effect-patched builds it ships directly, leaving `node_modules` untouched:
```sh
effect-tsgo tsc -p tsconfig.json # the Effect-patched tsc
effect-tsgo tsc@7.0.2 --lsp --stdio # a specific TypeScript version
effect-tsgo tsc@next --build # or an upstream tag: latest, beta, next
effect-tsgo tsrs --noEmit # the Effect-patched tsrs (tsrs@<version> and tsrs@latest work too)
effect-tsgo oxlint --type-aware # Oxlint with the Effect rules
effect-tsgo vp check # vite-plus (vp check, vp lint, vp run ...) with the Effect rules
effect-tsgo --tsrs-lint oxlint --type-aware # the type-aware rules on tsrs instead of tsgolint (experimental)
effect-tsgo --tsrs-lint=latest vp lint # with a tsrs version or tag
```
Every argument after the tool is passed through unchanged, so the commands work as drop-in replacements in `package.json` scripts and editor settings that launch `tsc`.
- `tsc` and `tsrs` run the requested version or tag; without one they run the build of the installed `typescript`/`@typescript/native` (>= 7) or `tsrs` version when this release ships it, and otherwise the latest supported version. They do not require TypeScript or tsrs to be installed.
- `oxlint` runs the CLI of the installed `oxlint` package (installed directly or through `vite-plus`) with the Effect-patched native binding and, when `oxlint-tsgolint` is installed, the Effect-patched `tsgolint` of the installed versions. It does not accept a version.
- `vp` runs the CLI of the installed `vite-plus` package, so that the Oxlint it starts (for `vp check`, `vp lint`, and scripts run through `vp run`) uses the Effect-patched binding and `tsgolint` of the oxlint version vite-plus resolves. It does not accept a version.
- `--tsrs-lint[=<version|tag>]`, in front of `oxlint` or `vp`, runs Oxlint's type-aware rules, including the Effect ones, on the Effect-patched `tsrs` (`tsrs --lint`, tsrs's port of tsgolint) instead of the patched `tsgolint`; `oxlint-tsgolint` does not need to be installed. The tsrs version is picked as for `effect-tsgo tsrs`: the requested version or tag, else the installed `tsrs` version when this release ships it, else the latest supported one. tsrs does not support tsgolint's Go profiling variables (`OXLINT_TSGOLINT_TRACE`, `OXLINT_TSGOLINT_CPU`, `OXLINT_TSGOLINT_HEAP`, `OXLINT_TSGOLINT_ALLOCS`).
- `oxlint` and `vp` work under Node.js and Bun: they preload `@effect/tsgo/oxlint-bridge` through `NODE_OPTIONS` and `BUN_OPTIONS`, in front of any options already set there, so every process they start loads the patched Oxlint binding in place of the stock one and every other native addon unchanged.
- As with `patch`, the packaged `tsrs` and `oxlint` builds do not support Linux musl.
Prefer these commands whenever you cannot or do not want to modify `node_modules`; prefer `patch` when other tools must keep launching the stock binaries (for example `npx tsc`, or editor extensions that resolve the TypeScript package). Note that the type augmentation that adds the `effecttsgo` plugin and rules to Oxlint's config types (for `oxlint.config.ts`) is applied only by `patch`.
## LSP-based linter
The Effect LSP doubles as a tool to perform type-aware linting of Effect code, and ships as well a way to emit additional Oxlint Type Aware rules.
Linting can occur either during the `tsc` typecheck phase (with the benefit of running typechecking only once and caching the output), or via a dedicated `npx @effect/tsgo diagnostics --project tsconfig.json` command (with typechecking occurring again), or via the Oxlint Patch.
<a href="https://github.com/Effect-TS/tsgo/blob/main/docs/README.md">See the Oxlint Setup guide</a> for instructions on how to install and configure Oxlint with the Effect LSP.
When running in `tsc` mode, the Effect diagnostics are emitted as standard TypeScript diagnostics, and can be configured to affect the `tsc` exit code through the options `ignoreEffectSuggestionsInTscExitCode`, `ignoreEffectWarningsInTscExitCode`, and `ignoreEffectErrorsInTscExitCode`.
When running in dedicated diagnostics mode, the Effect diagnostics can be emitted in structured formats, which can be further processed by other tools.
## Diagnostic Status
Some diagnostics are off by default or have a default severity of suggestion, but you can always enable them or change their default severity in the plugin options.
<!-- diagnostics-table:start -->
<table>
<thead>
<tr><th>Rule</th><th>Description</th></tr>
</thead>
<tbody>
<tr><td colspan="2"><strong>Correctness</strong> <em>Wrong, unsafe, or structurally invalid code patterns.</em></td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/any-unknown-in-error-context.md"><code>anyUnknownInErrorContext</code></a></td><td>Detects 'any' or 'unknown' types in Effect error or requirements channels</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/class-self-mismatch.md"><code>classSelfMismatch</code></a></td><td>Ensures Self type parameter matches the class name in Context/Service/Tag/Schema classes</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/duplicate-package.md"><code>duplicatePackage</code></a></td><td>Warns when multiple versions of an Effect-related package are detected in the program</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/effect-fn-implicit-any.md"><code>effectFnImplicitAny</code></a></td><td>Mirrors noImplicitAny for unannotated Effect.fn, Effect.fnUntraced, and Effect.fnUntracedEager callback parameters when no outer contextual function type exists. Requires TS's noImplicitAny: true</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/error-payload-shadows-name.md"><code>errorPayloadShadowsName</code></a></td><td>Detects error payload fields named `name` that shadow the error's own name</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/experimental-api-usage.md"><code>experimentalApiUsage</code></a></td><td>Warns when using an API marked @stability experimental</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/floating-effect.md"><code>floatingEffect</code></a></td><td>Detects Effect values that are neither yielded nor assigned</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/floating-effect-in-vitest.md"><code>floatingEffectInVitest</code></a></td><td>Detects Effects returned from non-Effect-aware Vitest callbacks</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/generic-effect-services.md"><code>genericEffectServices</code></a></td><td>Prevents services with type parameters that cannot be discriminated at runtime</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/missing-effect-context.md"><code>missingEffectContext</code></a></td><td>Detects Effect values with unhandled context requirements</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/missing-effect-error.md"><code>missingEffectError</code></a></td><td>Detects Effect values with unhandled error types</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/missing-layer-context.md"><code>missingLayerContext</code></a></td><td>Detects Layer values with unhandled context requirements</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/missing-return-yield-star.md"><code>missingReturnYieldStar</code></a></td><td>Suggests using return yield* for Effects that never succeed</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/missing-star-in-yield-effect-gen.md"><code>missingStarInYieldEffectGen</code></a></td><td>Detects bare yield (without *) inside Effect generator scopes</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/non-object-effect-service-type.md"><code>nonObjectEffectServiceType</code></a></td><td>Ensures Effect.Service types are objects, not primitives</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/obsolete-match-import.md"><code>obsoleteMatchImport</code></a></td><td>Warns when importing @effect/match in projects targeting Effect v4, where Match is included directly in the effect package</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/obsolete-schema-import.md"><code>obsoleteSchemaImport</code></a></td><td>Warns when importing @effect/schema in projects targeting Effect v4, where Schema is included directly in the effect package</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/outdated-api.md"><code>outdatedApi</code></a></td><td>Detects usage of APIs that have been removed or renamed in Effect v4</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/overridden-schema-constructor.md"><code>overriddenSchemaConstructor</code></a></td><td>Prevents overriding constructors in Schema classes which breaks decoding behavior</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/promise-in-effect-success.md"><code>promiseInEffectSuccess</code></a></td><td>Detects Promise types in Effect success channels where they are not awaited</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/schema-class-missing-brand.md"><code>schemaClassMissingBrand</code></a></td><td>Warns when Schema classes, errors, or Opaque classes omit the brand type argument</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/schema-class-object-literal.md"><code>schemaClassObjectLiteral</code></a></td><td>Warns when object literals are checked as Schema class instances without the class prototype</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/schema-literal-non-finite.md"><code>schemaLiteralNonFinite</code></a></td><td>Reports statically known non-finite numbers passed to Schema literal constructors</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/schema-opaque-instance-member.md"><code>schemaOpaqueInstanceMember</code></a></td><td>Disallows instance members in classes extending Schema.Opaque</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/unsafe-effect-type-assertion.md"><code>unsafeEffectTypeAssertion</code></a></td><td>Detects unsafe type assertions that narrow Effect, Stream, or Layer error or requirements channels</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/unstable-api-usage.md"><code>unstableApiUsage</code></a></td><td>Warns when using an API marked @stability unstable</td></tr>
<tr><td colspan="2"><strong>Anti-pattern</strong> <em>Discouraged patterns that often lead to bugs or confusing behavior.</em></td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/catch-unfailable-effect.md"><code>catchUnfailableEffect</code></a></td><td>Warns when using error handling on Effects that never fail</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/effect-fn-iife.md"><code>effectFnIife</code></a></td><td>Effect.fn or Effect.fnUntraced is called as an IIFE; use Effect.gen instead</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/effect-gen-uses-adapter.md"><code>effectGenUsesAdapter</code></a></td><td>Warns when using the deprecated adapter parameter in Effect.gen</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/effect-in-failure.md"><code>effectInFailure</code></a></td><td>Warns when an Effect is used inside an Effect failure channel</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/effect-in-void-success.md"><code>effectInVoidSuccess</code></a></td><td>Detects nested Effects in void success channels that may cause unexecuted effects</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/effect-try-without-catch.md"><code>effectTryWithoutCatch</code></a></td><td>Reports Effect.try and Effect.tryPromise calls without a catch handler, whose failures surface as a generic unknown error</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/global-error-in-effect-catch.md"><code>globalErrorInEffectCatch</code></a></td><td>Warns when catch callbacks return global Error type instead of typed errors</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/global-error-in-effect-failure.md"><code>globalErrorInEffectFailure</code></a></td><td>Warns when the global Error type is used in an Effect failure channel</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/layer-merge-all-with-dependencies.md"><code>layerMergeAllWithDependencies</code></a></td><td>Detects interdependencies in Layer.mergeAll calls where one layer provides a service that another layer requires</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/lazy-effect.md"><code>lazyEffect</code></a></td><td>Suggests avoiding exported zero-argument functions and service members that lazily return Effect or Stream values</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/lazy-promise-in-effect-sync.md"><code>lazyPromiseInEffectSync</code></a></td><td>Warns when Effect.sync lazily returns a Promise instead of using an async Effect constructor</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/leaking-requirements.md"><code>leakingRequirements</code></a></td><td>Detects implementation services leaked in service methods</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/multiple-effect-provide.md"><code>multipleEffectProvide</code></a></td><td>Warns against chaining Effect.provide calls which can cause service lifecycle issues</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/prefer-unsafe-constructor.md"><code>preferUnsafeConstructor</code></a></td><td>Suggests replacing Effect.runSync of a pure effect constructor with the synchronous *Unsafe variant exported by the same module</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/return-effect-in-gen.md"><code>returnEffectInGen</code></a></td><td>Warns when returning an Effect in a generator causes nested Effect<Effect<...>></td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/run-effect-inside-effect.md"><code>runEffectInsideEffect</code></a></td><td>Suggests using Runtime or Effect.run*With methods instead of Effect.run* inside Effect contexts</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/schema-sync-in-effect.md"><code>schemaSyncInEffect</code></a></td><td>Suggests using Effect-based Schema methods instead of sync methods inside Effect generators</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/scope-in-layer-effect.md"><code>scopeInLayerEffect</code></a></td><td>Suggests using Layer.scoped instead of Layer.effect when Scope is in requirements</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/strict-effect-provide.md"><code>strictEffectProvide</code></a></td><td>Warns when using Effect.provide with layers outside of application entry points</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/try-catch-in-effect-gen.md"><code>tryCatchInEffectGen</code></a></td><td>Discourages try/catch in Effect generators in favor of Effect error handling</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/unknown-in-effect-catch.md"><code>unknownInEffectCatch</code></a></td><td>Warns when catch callbacks return unknown instead of typed errors</td></tr>
<tr><td colspan="2"><strong>Effect-native</strong> <em>Prefer Effect-native APIs and abstractions when available.</em></td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/abort-controller-in-effect.md"><code>abortControllerInEffect</code></a></td><td>Warns when manually constructing AbortController inside Effect generators instead of using Effect.abortSignal</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/async-function.md"><code>asyncFunction</code></a></td><td>Warns when declaring async functions and suggests using Effect values and Effect.gen for async control flow</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/crypto-random-uuid.md"><code>cryptoRandomUUID</code></a></td><td>Warns when using crypto.randomUUID() outside Effect generators instead of SecureRandom from effect/crypto</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/crypto-random-uuid-in-effect.md"><code>cryptoRandomUUIDInEffect</code></a></td><td>Warns when using crypto.randomUUID() inside Effect generators instead of SecureRandom from effect/crypto</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/extends-native-error.md"><code>extendsNativeError</code></a></td><td>Warns when a class directly extends the native Error class</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/global-console.md"><code>globalConsole</code></a></td><td>Warns when using console methods outside Effect generators instead of Effect.log/Logger</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/global-console-in-effect.md"><code>globalConsoleInEffect</code></a></td><td>Warns when using console methods inside Effect generators instead of Effect.log/Logger</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/global-date.md"><code>globalDate</code></a></td><td>Warns when using Date.now() or new Date() outside Effect generators instead of Clock/DateTime</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/global-date-in-effect.md"><code>globalDateInEffect</code></a></td><td>Warns when using Date.now() or new Date() inside Effect generators instead of Clock/DateTime</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/global-fetch.md"><code>globalFetch</code></a></td><td>Warns when using the global fetch function outside Effect generators instead of the Effect HTTP client</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/global-fetch-in-effect.md"><code>globalFetchInEffect</code></a></td><td>Warns when using the global fetch function inside Effect generators instead of the Effect HTTP client</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/global-json.md"><code>globalJson</code></a></td><td>Warns when using JSON.parse or JSON.stringify outside Effect generators instead of Effect Schema</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/global-json-in-effect.md"><code>globalJsonInEffect</code></a></td><td>Warns when using JSON.parse or JSON.stringify inside Effect generators instead of Effect Schema</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/global-random.md"><code>globalRandom</code></a></td><td>Warns when using Math.random() outside Effect generators instead of the Random service</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/global-random-in-effect.md"><code>globalRandomInEffect</code></a></td><td>Warns when using Math.random() inside Effect generators instead of the Random service</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/global-timers.md"><code>globalTimers</code></a></td><td>Warns when using setTimeout/setInterval outside Effect generators instead of Effect.sleep/Schedule</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/global-timers-in-effect.md"><code>globalTimersInEffect</code></a></td><td>Warns when using setTimeout/setInterval inside Effect generators instead of Effect.sleep/Schedule</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/instance-of-schema.md"><code>instanceOfSchema</code></a></td><td>Suggests using Schema.is instead of instanceof for Effect Schema types</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/new-promise.md"><code>newPromise</code></a></td><td>Warns when constructing promises with new Promise instead of using Effect APIs</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/node-builtin-import.md"><code>nodeBuiltinImport</code></a></td><td>Warns when importing Node.js built-in modules that have Effect-native counterparts</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/prefer-effect-array.md"><code>preferEffectArray</code></a></td><td>Suggests Effect Array APIs for native array member references, with semantic caveats</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/prefer-effect-record.md"><code>preferEffectRecord</code></a></td><td>Suggests Effect Record APIs for native Object member references, with semantic caveats</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/prefer-effect-string.md"><code>preferEffectString</code></a></td><td>Suggests Effect String APIs for native String method invocations, with semantic caveats</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/prefer-schema-over-json.md"><code>preferSchemaOverJson</code></a></td><td>Deprecated: use globalJsonInEffect and globalJson instead. Suggests using Effect Schema for JSON operations instead of JSON.parse/JSON.stringify inside Effect code</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/process-env.md"><code>processEnv</code></a></td><td>Warns when reading process.env outside Effect generators instead of using Effect Config</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/process-env-in-effect.md"><code>processEnvInEffect</code></a></td><td>Warns when reading process.env inside Effect generators instead of using Effect Config</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/schema-sync.md"><code>schemaSync</code></a></td><td>Suggests Effect-based Schema decoding and encoding instead of synchronous methods</td></tr>
<tr><td colspan="2"><strong>Style</strong> <em>Cleanup, consistency, and idiomatic Effect code.</em></td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/acquire-release-disposable.md"><code>acquireReleaseDisposable</code></a></td><td>Suggests Effect.acquireDisposable when Effect.acquireRelease only invokes the acquired resource's disposal protocol</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/all-of-map-to-for-each.md"><code>allOfMapToForEach</code></a></td><td>Suggests using Effect.forEach instead of Effect.all over an effectful Array#map</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/catch-all-tag-dispatch-to-catch-tag.md"><code>catchAllTagDispatchToCatchTag</code></a></td><td>Suggests Effect.catchTag or Effect.catchTags for catch-all handlers that re-fail unmatched tagged errors</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/catch-all-to-map-error.md"><code>catchAllToMapError</code></a></td><td>Suggests using Effect.mapError instead of Effect.catch + Effect.fail</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/catch-chain-to-first-success-of.md"><code>catchChainToFirstSuccessOf</code></a></td><td>Suggests Effect.firstSuccessOf for consecutive error-independent Effect.catch fallbacks when the error type is preserved</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/catch-conditional-refail-to-catch-if.md"><code>catchConditionalRefailToCatchIf</code></a></td><td>Suggests Effect.catchIf, Effect.catchCauseIf, or Effect.catchTag for conditional catch handlers that re-fail their untouched input</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/catch-die-to-or-die.md"><code>catchDieToOrDie</code></a></td><td>Suggests using Effect.orDie instead of Effect.catch or Effect.catchAll with an identity-forwarding Effect.die handler</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/catch-if-tag-to-catch-tag.md"><code>catchIfTagToCatchTag</code></a></td><td>Suggests Effect.catchTag instead of Effect.catchIf with a _tag equality or Predicate.isTagged predicate</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/catch-refail-to-tap-error.md"><code>catchRefailToTapError</code></a></td><td>Suggests Effect.tapError for catch handlers that sequence an effect and then re-fail the original error</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/catch-tag-to-catch-reason.md"><code>catchTagToCatchReason</code></a></td><td>Suggests Effect.catchReason or Effect.catchReasons for handlers that re-fail unmatched reason._tag branches</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/catch-to-ignore.md"><code>catchToIgnore</code></a></td><td>Suggests using Effect.ignore or Effect.ignoreCause instead of Effect.catch/catchCause returning Effect.void</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/catch-to-or-else-succeed.md"><code>catchToOrElseSucceed</code></a></td><td>Suggests using Effect.orElseSucceed instead of Effect.catch + Effect.succeed</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/deterministic-keys.md"><code>deterministicKeys</code></a></td><td>Enforces deterministic naming for service/tag/error identifiers based on class names</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/effect-do-notation.md"><code>effectDoNotation</code></a></td><td>Suggests using Effect.gen or Effect.fn instead of the Effect.Do notation helpers</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/effect-fn-opportunity.md"><code>effectFnOpportunity</code></a></td><td>Suggests using Effect.fn for functions that return an Effect</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/effect-map-flatten.md"><code>effectMapFlatten</code></a></td><td>Suggests using Effect.flatMap instead of Effect.map followed by Effect.flatten in piping flows</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/effect-map-void.md"><code>effectMapVoid</code></a></td><td>Suggests using Effect.asVoid instead of Effect.map(() => void 0), Effect.map(() => undefined), or Effect.map(() => {})</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/effect-sleep-zero-to-yield-now.md"><code>effectSleepZeroToYieldNow</code></a></td><td>Suggests Effect.yieldNow for cooperative yielding instead of sleeping for zero duration</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/effect-succeed-with-undefined.md"><code>effectSucceedWithUndefined</code></a></td><td>Suggests using Effect.undefined instead of Effect.succeed(undefined) or Effect.succeed(void 0)</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/effect-succeed-with-void.md"><code>effectSucceedWithVoid</code></a></td><td>Suggests using Effect.void instead of Effect.succeed(undefined) or Effect.succeed(void 0)</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/fail-cause-to-constructor.md"><code>failCauseToConstructor</code></a></td><td>Suggests Effect.fail/die/failSync/dieSync instead of failCause/failCauseSync wrapping a single Cause.fail/die</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/flat-map-conditional-to-filter-or-fail.md"><code>flatMapConditionalToFilterOrFail</code></a></td><td>Suggests Effect.filterOrFail or Effect.filterOrElse when Effect.flatMap conditionally passes its input through with Effect.succeed</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/flat-map-identity-to-flatten.md"><code>flatMapIdentityToFlatten</code></a></td><td>Suggests Effect.flatten instead of Effect.flatMap when the callback is Effect's identity export referenced directly or an unannotated function returning its parameter</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/flat-map-ignored-param-to-and-then.md"><code>flatMapIgnoredParamToAndThen</code></a></td><td>Suggests using Effect.andThen instead of Effect.flatMap when a zero-parameter callback returns an existing Effect value</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/flat-map-to-map.md"><code>flatMapToMap</code></a></td><td>Suggests using Effect.map instead of Effect.flatMap when the callback only wraps its result with Effect.succeed</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/flat-map-to-tap.md"><code>flatMapToTap</code></a></td><td>Suggests Effect.tap when a flatMap or andThen callback runs an effect and returns its unchanged parameter</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/manual-metric-tap-to-track.md"><code>manualMetricTapToTrack</code></a></td><td>Suggests Effect.trackSuccesses/trackErrors/trackDefects when an Effect.tap/tapError/tapDefect only updates a metric</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/map-const-to-as.md"><code>mapConstToAs</code></a></td><td>Suggests using Effect.as instead of Effect.map when the callback ignores its input and returns a constant</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/map-map-error-to-map-both.md"><code>mapMapErrorToMapBoth</code></a></td><td>Suggests Effect.mapBoth when Effect.map and Effect.mapError are adjacent steps of a piping flow</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/map-some-catch-no-such-element.md"><code>mapSomeCatchNoSuchElement</code></a></td><td>Suggests Effect.catchNoSuchElement instead of wrapping successes in Option.some and catching NoSuchElementError into Option.none</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/map-some-to-as-some.md"><code>mapSomeToAsSome</code></a></td><td>Suggests using Effect.asSome instead of Effect.map when the mapper only wraps the success value with Option.some</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/match-boolean-to-is-success.md"><code>matchBooleanToIsSuccess</code></a></td><td>Suggests Effect.isSuccess or Effect.isFailure when Effect.match or Effect.matchEager folds to complementary boolean literals</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/match-effect-to-map-both.md"><code>matchEffectToMapBoth</code></a></td><td>Suggests Effect.mapBoth when Effect.matchEffect only transforms the failure and success channels</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/match-effect-to-match.md"><code>matchEffectToMatch</code></a></td><td>Suggests Effect.match or Effect.matchCause when both Effect.matchEffect handlers only return Effect.succeed</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/match-to-result-or-option.md"><code>matchToResultOrOption</code></a></td><td>Suggests Effect.result, Effect.option or Effect.either when match handlers, or a map step followed by a catch step, only reify the outcome</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/missed-pipeable-opportunity.md"><code>missedPipeableOpportunity</code></a></td><td>Suggests using .pipe() for nested function calls</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/missing-effect-service-dependency.md"><code>missingEffectServiceDependency</code></a></td><td>Checks that Effect.Service dependencies satisfy all required layer inputs</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/missing-pipeable-signature.md"><code>missingPipeableSignature</code></a></td><td>Reports exported fixed-arity functions whose call signatures have no corresponding pipeable overload</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/multiple-catch-tag.md"><code>multipleCatchTag</code></a></td><td>Suggests collapsing consecutive Effect.catchTag transformations into a single Effect.catchTags call when semantics stay equivalent</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/nested-effect-gen-yield.md"><code>nestedEffectGenYield</code></a></td><td>Warns when yielding a nested bare Effect.gen inside an existing Effect generator context</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/new-schema-class.md"><code>newSchemaClass</code></a></td><td>Suggests using Schema make instead of new for Schema classes</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/option-match-to-from-option.md"><code>optionMatchToFromOption</code></a></td><td>Suggests Effect.fromOption when Option.match or an Option tag conditional only converts Some to Effect.succeed and None to Effect.fail</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/prefer-barrel-import.md"><code>preferBarrelImport</code></a></td><td>Reports imports of individual modules from packages configured in barrelImportPackages that should be named imports from the package barrel</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/prefer-namespace-import.md"><code>preferNamespaceImport</code></a></td><td>Reports named imports from packages configured in namespaceImportPackages that should be namespace imports</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/prefer-schema-tagged-error.md"><code>preferSchemaTaggedError</code></a></td><td>Suggests using Schema.TaggedError instead of Data.TaggedError</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/prefer-schema-type-property.md"><code>preferSchemaTypeProperty</code></a></td><td>Disallows Schema.Schema.Type<typeof X> and Schema.Codec.Encoded<typeof X>-style helpers in favor of typeof X.Type and typeof X.Encoded</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/prefer-succeed-some-or-none.md"><code>preferSucceedSomeOrNone</code></a></td><td>Suggests using Effect.succeedNone or Effect.succeedSome instead of wrapping Option.none or Option.some with Effect.succeed</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/prefer-typed-schema-decoder.md"><code>preferTypedSchemaDecoder</code></a></td><td>Suggests typed Schema decoders when the input is assignable to the schema's Encoded type</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/provide-layer-succeed-to-provide-service.md"><code>provideLayerSucceedToProvideService</code></a></td><td>Suggests providing inline Layer.succeed and Layer.effect services directly</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/provide-merge-all-to-array.md"><code>provideMergeAllToArray</code></a></td><td>Suggests passing an array of layers to Effect.provide instead of wrapping them in Layer.mergeAll</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/race-first-with-sleep-to-timeout.md"><code>raceFirstWithSleepToTimeout</code></a></td><td>Suggests Effect.timeoutOrElse when Effect.raceFirst has exactly one sleep- or delay-based timer arm</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/redundant-map-error.md"><code>redundantMapError</code></a></td><td>Suggests hoisting a repeated trailing Effect.mapError from every yield in an Effect generator</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/redundant-or-die.md"><code>redundantOrDie</code></a></td><td>Suggests hoisting a repeated trailing Effect.orDie from every yield in an Effect generator</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/redundant-schema-tag-identifier.md"><code>redundantSchemaTagIdentifier</code></a></td><td>Suggests removing redundant identifier argument when it equals the tag value in Schema.TaggedClass/TaggedError/TaggedRequest</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/result-match-to-from-result.md"><code>resultMatchToFromResult</code></a></td><td>Suggests Effect.fromResult when Result.match or a Result guard conditional only converts Success to Effect.succeed and Failure to Effect.fail</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/run-of-exit-to-run-exit.md"><code>runOfExitToRunExit</code></a></td><td>Suggests using Effect.runPromiseExit instead of passing Effect.exit to Effect.runPromise</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/schema-number.md"><code>schemaNumber</code></a></td><td>Suggests Schema.Finite and Schema.FiniteFromString instead of Schema.Number APIs when describing domain numbers</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/schema-struct-with-tag.md"><code>schemaStructWithTag</code></a></td><td>Suggests using Schema.TaggedStruct instead of Schema.Struct with _tag field</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/schema-union-of-literals.md"><code>schemaUnionOfLiterals</code></a></td><td>Suggests combining multiple Schema.Literal calls in Schema.Union into a single Schema.Literal</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/service-not-as-class.md"><code>serviceNotAsClass</code></a></td><td>Warns when Context.Service is used as a variable instead of a class declaration</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/strict-boolean-expressions.md"><code>strictBooleanExpressions</code></a></td><td>Enforces boolean types in conditional expressions for type safety</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/suspend-fail-to-fail-sync.md"><code>suspendFailToFailSync</code></a></td><td>Suggests Effect.failSync/dieSync instead of Effect.suspend wrapping a single Effect.fail/die</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/sync-to-succeed.md"><code>syncToSucceed</code></a></td><td>Suggests using Effect.succeed instead of Effect.sync when the thunk returns a constant value</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/timeout-catch-tag-to-timeout-or-else.md"><code>timeoutCatchTagToTimeoutOrElse</code></a></td><td>Suggests dedicated timeout combinators instead of catching TimeoutError immediately after Effect.timeout</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/type-union-to-schema-union.md"><code>typeUnionToSchemaUnion</code></a></td><td>Suggests composing unions of Schema .Type/.Encoded types with Schema.Union and deriving the type from it</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/unnecessary-arrow-block.md"><code>unnecessaryArrowBlock</code></a></td><td>Suggests using a concise arrow body when the block only returns an expression</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/unnecessary-effect-gen.md"><code>unnecessaryEffectGen</code></a></td><td>Suggests removing Effect.gen when it contains only a single return statement</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/unnecessary-fail-yieldable-error.md"><code>unnecessaryFailYieldableError</code></a></td><td>Suggests yielding yieldable errors directly instead of wrapping with Effect.fail</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/unnecessary-pipe.md"><code>unnecessaryPipe</code></a></td><td>Removes pipe calls with no arguments</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/unnecessary-pipe-chain.md"><code>unnecessaryPipeChain</code></a></td><td>Simplifies chained pipe calls into a single pipe call</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/unnecessary-typeof-type.md"><code>unnecessaryTypeofType</code></a></td><td>Suggests replacing typeof Schema.Type style annotations with the matching named type when available</td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/yield-in-call-argument.md"><code>yieldInCallArgument</code></a></td><td>Suggests yielding into a const before a call instead of passing a yield* directly as a call or new argument in Effect generators</td></tr>
<tr><td colspan="2"><strong>Maintainers</strong> <em>Guard the public API surface and release hygiene of a package.</em></td></tr>
<tr><td><a href="https://github.com/Effect-TS/tsgo/blob/main/docs/rules/api-stability-leak.md"><code>apiStabilityLeak</code></a></td><td>Reports exported APIs whose public surface exposes a less stable type</td></tr>
</tbody>
</table>
<!-- diagnostics-table:end -->
## Refactor Status
| Refactor | V3 | V4 | Notes |
|----------|----|----|-------|
| `asyncAwaitToFn` | โ
| โ
| Convert async/await to Effect.fn |
| `asyncAwaitToFnTryPromise` | โ
| โ
| Convert async/await to Effect.fn with Error ADT + tryPromise |
| `asyncAwaitToGen` | โ
| โ
| Convert async/await to Effect.gen |
| `asyncAwaitToGenTryPromise` | โ
| โ
| Convert async/await to Effect.gen with Error ADT + tryPromise |
| `debugPerformance` | โ | โ | Insert performance timing debug comments |
| `effectGenToFn` | โ
| โ
| Convert Effect.gen to Effect.fn |
| `functionToArrow` | โ
| โ
| Convert function declaration to arrow function |
| `layerMagic` | โ
| โ
| Auto-compose layers with correct merge/provide |
| `makeSchemaOpaque` | โ
| โ
| Convert Schema to opaque type aliases |
| `makeSchemaOpaqueWithNs` | โ
| โ
| Convert Schema to opaque types with namespace |
| `pipeableToDatafirst` | โ
| โ
| Convert pipeable calls to data-first style |
| `removeUnnecessaryEffectGen` | โ
| โ
| Remove redundant Effect.gen wrapper |
| `structuralTypeToSchema` | โ
| โ
| Generate recursive Schema from type alias |
| `toggleLazyConst` | โ
| โ
| Toggle lazy/eager const declarations |
| `togglePipeStyle` | โ
| โ
| Toggle pipe(x, f) vs x.pipe(f) |
| `toggleReturnTypeAnnotation` | โ
| โ
| Add/remove return type annotation |
| `toggleTypeAnnotation` | โ
| โ
| Add/remove variable type annotation |
| `typeToEffectSchema` | โ
| โ
| Generate Effect.Schema from type alias |
| `typeToEffectSchemaClass` | โ
| โ
| Generate Schema.Class from type alias |
| `wrapWithEffectGen` | โ
| โ
| Wrap expression in Effect.gen |
| `wrapWithPipe` | โ | โ
| Wrap selection in pipe(...) |
| `writeTagClassAccessors` | โ
| โ | Generate static accessors for Effect.Service/Tag classes |
### Completion Status
| Completion | V3 | V4 | Notes |
|------------|----|----|-------|
| `contextSelfInClasses` | โ
| โ | Context.Tag self-type snippets in extends clauses (V3-only) |
| `effectDataClasses` | โ
| โ
| Data class constructor snippets in extends clauses |
| `effectSchemaSelfInClasses` | โ
| โ
| Schema/Model class constructor snippets in extends clauses |
| `effectSelfInClasses` | โ
| โ | Effect.Service/Effect.Tag self-type snippets in extends clauses (V3-only) |
| `genFunctionStar` | โ
| โ
| `gen(function*(){})` snippet when dot-accessing `.gen` on objects with callable gen property |
| `effectCodegensComment` | โ
| โ
| `@effect-codegens` directive snippet in comments with codegen name choices |
| `effectDiagnosticsComment` | โ
| โ
| `@effect-diagnostics` / `@effect-diagnostics-next-line` directive snippets in comments |
| `rpcMakeClasses` | โ
| โ | `Rpc.make` constructor snippet in extends clauses (V3-only) |
| `schemaBrand` | โ
| โ | `brand("varName")` snippet when dot-accessing Schema in variable declarations (V3-only) |
| `serviceMapSelfInClasses` | โ
| โ
| Service map self-type snippets in extends clauses |
## Best Practices
### Relationship to Official TypeScript-Go (`tsgo`)
Effect-tsgo is a **superset** of the official [TypeScript-Go](https://github.com/microsoft/TypeScript-Go) โ it embeds a pinned version of `tsgo` with a small patch set on top and adds the Effect language service. This means `effect-tsgo` provides all standard TypeScript-Go functionality plus Effect-specific diagnostics, quick fixes, and refactors.
**Use `effect-tsgo` instead of `tsgo`, not alongside it.** Running both in parallel will produce duplicate diagnostics and degrade editor performance. Configure your editor to use `effect-tsgo` as your sole TypeScript language server.
### Version Pinning
Each release of `effect-tsgo` is built against the versioned components recorded in `_packages/tsgo/upstream.json`. The Nix flake consumes the TypeScript `next` tag directly. When upstream `tsgo` releases new features or fixes, `effect-tsgo` will adopt them in a subsequent release after validating compatibility with the Effect diagnostics layer.
The npm compiler binaries load their TypeScript standard libraries from `lib.*.d.ts` files beside the executable. Each platform package ships the compiler for the latest TypeScript version as `lib/tsc` and other versions under `artifacts/typescript/<version>/`, each with its library files. If you relocate the executable returned by `effect-tsgo get-exe-path`, copy its library files into the same destination directory.
### When to Upgrade
- Upgrade `effect-tsgo` when a new release includes upstream `tsgo` fixes you need or new Effect diagnostics you want.
- There is no need to track upstream `tsgo` releases separately โ `effect-tsgo` is the single binary to manage.
## Plugin Options
<!-- example-config:start -->
```jsonc
{
"compilerOptions": {
"plugins": [
{
"name": "@effect/language-service",
// Controls Effect refactors. (default: true)
"refactors": true,
// Controls Effect diagnostics. (default: true)
"diagnostics": true,
// When false, suggestion-level Effect diagnostics are omitted from tsc CLI output. (default: true)
"includeSuggestionsInTsc": true,
// Controls Effect quickinfo. (default: true)
"quickinfo": true,
// Controls Effect completions. (default: true)
"completions": true,
// Controls Effect goto references support. (default: true)
"goto": true,
// Controls Effect rename helpers. (default: true)
"renames": true,
// When true, suggestion diagnostics do not affect the tsc exit code. (default: true)
"ignoreEffectSuggestionsInTscExitCode": true,
// When true, warning diagnostics do not affect the tsc exit code. (default: false)
"ignoreEffectWarningsInTscExitCode": false,
// When true, error diagnostics do not affect the tsc exit code. (default: false)
"ignoreEffectErrorsInTscExitCode": false,
// When true, disabled diagnostics are still processed so directives can re-enable them. (default: false)
"skipDisabledOptimization": false,
// Mermaid rendering service for layer graph links. Accepts mermaid.live, mermaid.com, or a custom URL. (default: "mermaid.live")
"mermaidProvider": "mermaid.live",
// When true, suppresses external Mermaid links in hover output. (default: false)
"noExternal": false,
// How many levels deep the layer graph extraction follows symbol references. (default: 0)
"layerGraphFollowDepth": 0,
// When true, suppresses redundant return-type inlay hints on supported Effect generator functions. (default: false)
"inlays": false,
// Package names that should prefer namespace imports. (default: [])
"namespaceImportPackages": [],
// Package names that should prefer barrel named imports. (default: [])
"barrelImportPackages": [],
// Package-level import aliases keyed by package name. (default: {})
"importAliases": {},
// Controls whether named reexports are followed at package top-level. (default: "ignore")
"topLevelNamedReexports": "ignore",
// Configures key pattern formulas for the deterministicKeys rule. (default: [{"target":"service","pattern":"default","skipLeadingPath":["src/"]},{"target":"custom","pattern":"default","skipLeadingPath":["src/"]}])
"keyPatterns": [
{
"target": "service",
"pattern": "default",
"skipLeadingPath": [
"src/"
]
},
{
"target": "custom",
"pattern": "default",
"skipLeadingPath": [
"src/"
]
}
],
// Enables matching constructors with @effect-identifier annotations. (default: false)
"extendedKeyDetection": false,
// Minimum number of contiguous pipeable transformations to trigger missedPipeableOpportunity. (default: 2)
"pipeableMinArgCount": 2,
// Unstable APIs allowed by package/module subtree or package/module#export name. (default: [])
"allowedUnstableApis": [],
// Experimental APIs allowed by package/module subtree or package/module#export name. (default: [])
"allowedExperimentalApis": [],
// Package names allowed to have multiple versions without triggering duplicatePackage. (default: [])
"allowedDuplicatedPackages": [],
// Controls which effectFnOpportunity quickfix variants are offered. (default: ["span"])
"effectFn": [
"span"
],
// Schema class kinds that get a nominal brand, used by schemaClassMissingBrand and the Schema class completions. (default: ["Class","TaggedClass","Error","TaggedError","Opaque"])
"brandedSchemaClasses": [
"Class",
"TaggedClass",
"Error",
"TaggedError",
"Opaque"
],
// Maps rule names to severity levels. Use {} to enable diagnostics with rule defaults. (default: {})
"diagnosticSeverity": {},
// Ordered per-file diagnostic option overrides. (default: [{"include":["src/**/*.ts"],"options":{"diagnosticSeverity":{"floatingEffect":"error"}}}])
"overrides": [
{
"include": [
"src/**/*.ts"
],
"options": {
"diagnosticSeverity": {
"floatingEffect": "error"
}
}
}
]
}
]
}
}
```
<!-- example-config:end -->
The `allowedUnstableApis` and `allowedExperimentalApis` options selectively permit
APIs marked `@stability unstable` and `@stability experimental`, respectively:
```json
{
"allowedUnstableApis": [
"effect/http",
"effect/rpc/RpcClient#make"
],
"allowedExperimentalApis": ["my-package/Preview#make"]
}
```
A module entry permits that module and its descendants; an entry ending in
`#exportName` permits only that module's exported API, including renamed imports
and aliases. For example, `effect/http/HttpClient` permits the entire module,
while `effect/http/HttpClient#get` permits only its exported `get` API.
Matching is case-sensitive and respects path segments: `effect/http` does not
permit `effect/http-api`. Per-file `overrides` replace the base list.
The import style options `namespaceImportPackages`, `barrelImportPackages`,
`importAliases`, and `topLevelNamedReexports` can also be set per file in
`overrides`. Auto-import, the import quick fixes, and the `preferNamespaceImport`
and `preferBarrelImport` diagnostics all use the value resolved for the current
file. A scoped value replaces the base value, so this override moves the
`legacy/` folder from namespace imports to barrel imports:
```json
{
"namespaceImportPackages": ["effect"],
"overrides": [{
"include": ["src/legacy/**/*.ts"],
"options": {
"namespaceImportPackages": [],
"barrelImportPackages": ["effect"]
}
}]
}
```
`apiStabilityLeak` ignores exports marked `@internal`. The tag is the compiler's
`stripInternal` declaration-emit marker, and it is honoured wherever it is
written: on an exported declaration, on a named, star or namespace forwarding
declaration, or on a namespace member. An untagged re-export of an internal
target is ignored as well, because the forwarded target is not public API. A
declaration that is not tagged keeps the export checked, so a public overload is
still reported when only its implementation is marked `@internal`. Tagging a
type does not hide it from public signatures: a public export that exposes an
`@internal` type is still reported when that type is less stable. Properties
and methods whose declarations are all marked `@internal` are excluded from
the public surface, including in interfaces, classes, and augmentations. A
merged property with any public declaration remains checked. An internal
property does not exempt other public members of its containing export.
Inherited bases do not contribute to `apiStabilityLeak` when all their public
members, including inherited members, are
optional properties or methods with an explicit `@stability stable`,
`@stability unstable`, or `@stability experimental` tag. This permits optional,
explicitly tagged extensions of existing APIs such as `Error`. Required or
untagged members and call, construct, or index signatures keep the base checked.
Internal members are excluded when deciding whether a base qualifies. A derived
type's own members remain checked independently. Direct references such as a
property or parameter typed as the base still expose its declared stability.