> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/Effect-TS/tsgo/llms.txt
> Use this file to discover all available pages before exploring further.

# Migrating from V3

> Understand what changes between Effect V3 and V4 in terms of diagnostics, and how to configure effect-tsgo for a V4 project.

Effect V4 (codename "smol") introduces a redesigned service system and removes several APIs that existed in V3. The Effect Language Service detects which version of Effect you have installed and adjusts its diagnostics accordingly — some rules apply only to V3 projects, others only to V4 projects, and many apply to both.

## How version detection works

The language service reads your installed `effect` package version from `node_modules` at startup. You do not need to set any option manually — if `effect@4.x` is detected, V4-only rules activate and V3-only rules are silently disabled. The reverse applies for V3 projects.

<Note>
  If you are working in a monorepo where different packages use different Effect versions, the version is resolved per `tsconfig.json` root.
</Note>

## Rules that are V3-only

The following diagnostics and completions are disabled automatically when a V4 project is detected. If you see them mentioned in the changelog or documentation, they do not apply to your V4 codebase.

### Diagnostics

| Rule                             | Category     | Description                                                                                         |
| -------------------------------- | ------------ | --------------------------------------------------------------------------------------------------- |
| `nonObjectEffectServiceType`     | Correctness  | Ensures `Effect.Service` types are objects, not primitives                                          |
| `runEffectInsideEffect`          | Anti-pattern | Suggests using `Runtime` methods instead of `Effect.run*` inside Effect contexts                    |
| `schemaSyncInEffect`             | Anti-pattern | Suggests using Effect-based Schema methods instead of sync methods inside Effect generators         |
| `scopeInLayerEffect`             | Anti-pattern | Suggests using `Layer.scoped` instead of `Layer.effect` when `Scope` is in requirements             |
| `missingEffectServiceDependency` | Style        | Checks that `Effect.Service` dependencies satisfy all required layer inputs                         |
| `schemaUnionOfLiterals`          | Style        | Suggests combining multiple `Schema.Literal` calls in `Schema.Union` into a single `Schema.Literal` |

### Completions

| Completion             | Description                                                                     |
| ---------------------- | ------------------------------------------------------------------------------- |
| `contextSelfInClasses` | `Context.Tag` self-type snippets in `extends` clauses                           |
| `effectSelfInClasses`  | `Effect.Service` / `Effect.Tag` self-type snippets in `extends` clauses         |
| `rpcMakeClasses`       | `Rpc.make` constructor snippet in `extends` clauses                             |
| `schemaBrand`          | `brand("varName")` snippet when dot-accessing `Schema` in variable declarations |

## Rules that are V4-only

### `outdatedApi` — detect renamed or removed APIs

**Severity:** warning (enabled by default for V4 projects)

The `outdatedApi` diagnostic scans your code for APIs that existed in Effect V3 but have been removed or renamed in V4. When triggered, it identifies the outdated call site and, where possible, suggests the replacement.

```typescript theme={null}
import { Effect } from "effect"

// Example: an API that was renamed in V4
const program = Effect.someV3Api() // [!code --]
const program = Effect.someV4Replacement() // [!code ++]
```

<Info>
  The exact set of APIs flagged by `outdatedApi` grows as V4 stabilises. Check the [CHANGELOG](/guides/version-pinning) for additions in each release.
</Info>

### `serviceNotAsClass` — enforce class-based service declarations

**Severity:** off by default (`➖`), quick fix available

In Effect V4, services are declared using `ServiceMap.Service` as a **class**, not as a variable assignment. The `serviceNotAsClass` diagnostic warns when the variable style is used and offers a quick fix to convert it.

```typescript theme={null}
import { ServiceMap } from "effect"

// V3-style variable declaration (flagged in V4 projects)
const MyService = ServiceMap.Service<MyService>()("MyService", { // [!code --]
  accessors: true, // [!code --]
}) // [!code --]

// V4-style class declaration (correct)
class MyService extends ServiceMap.Service<MyService>()("MyService", { // [!code ++]
  accessors: true, // [!code ++]
}) {} // [!code ++]
```

You can enable this rule at warning or error level in your plugin options:

```jsonc theme={null}
{
  "compilerOptions": {
    "plugins": [
      {
        "name": "@effect/language-service",
        "diagnosticSeverity": {
          "serviceNotAsClass": "warning"
        }
      }
    ]
  }
}
```

## Configuring for a V4 project

<Steps>
  <Step title="Install effect-tsgo">
    Run the guided setup to install and configure `@effect/tsgo`:

    ```bash theme={null}
    npx @effect/tsgo setup
    ```

    This adds the plugin entry to your `tsconfig.json` and installs the binary.
  </Step>

  <Step title="Verify Effect V4 is installed">
    Make sure your project depends on `effect@4.x`:

    ```bash theme={null}
    npm ls effect
    ```

    The language service reads this version automatically — no additional configuration is needed to switch between V3 and V4 rule sets.
  </Step>

  <Step title="Enable serviceNotAsClass (optional)">
    The `serviceNotAsClass` rule is off by default. To surface it as a warning across your project, add it to `diagnosticSeverity` in your `tsconfig.json`:

    ```jsonc theme={null}
    {
      "compilerOptions": {
        "plugins": [
          {
            "name": "@effect/language-service",
            "diagnosticSeverity": {
              "serviceNotAsClass": "warning",
              "outdatedApi": "warning"
            }
          }
        ]
      }
    }
    ```
  </Step>

  <Step title="Address outdatedApi warnings">
    After enabling the plugin, open your editor and look for `outdatedApi` warnings (yellow underlines). Each warning indicates a V3 API that must be updated. Use the hover tooltip to see the recommended replacement, then apply the change.
  </Step>
</Steps>

## Common migration patterns

### Service declarations

The most common change when moving from V3 to V4 is converting service variable assignments to class declarations.

```typescript theme={null}
import { ServiceMap, Effect, Layer } from "effect"

// Before: V3 variable style
interface HttpClient { // [!code --]
  get: (url: string) => Effect.Effect<Response> // [!code --]
} // [!code --]
const HttpClient = ServiceMap.Service<HttpClient>()( // [!code --]
  "HttpClient", // [!code --]
  { accessors: true } // [!code --]
) // [!code --]

// After: V4 class style
class HttpClient extends ServiceMap.Service<HttpClient>()( // [!code ++]
  "HttpClient", // [!code ++]
  { accessors: true } // [!code ++]
) { // [!code ++]
  get(url: string): Effect.Effect<Response> { // [!code ++]
    return Effect.die("not implemented") // [!code ++]
  } // [!code ++]
} // [!code ++]
```

### Checking for missing V3-only rules

If you relied on rules like `scopeInLayerEffect` or `runEffectInsideEffect` in a V3 project and now want similar protection in V4, check the [diagnostics overview](/diagnostics/overview) for the equivalent V4 rules or patterns.

<Tip>
  Most correctness rules (`missingEffectContext`, `missingEffectError`, `floatingEffect`, etc.) work identically in both V3 and V4 — your existing rule configuration carries over automatically.
</Tip>
