Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

@effect/language-service

Effect-TS1.2mMIT0.48.0

A Language-Service Plugin to Refactor and Diagnostic effect-ts projects

typescript, algebraic-data-types, functional-programming

readme

language-service

This package implements a TypeScript language service plugin that allows additional refactors and diagnostics with your VSCode editor (or any editor that supports TypeScript's LSP).

Installation

  1. npm install @effect/language-service --save-dev in your project
  2. Inside your tsconfig.json, you should add the plugin configuration as follows:

    {
    "compilerOptions": {
     "plugins": [
       // ... other LSPs (if any) and as last
       {
         "name": "@effect/language-service"
       }
     ]
    }
    }
  3. Ensure that you have installed TypeScript locally in your project and set your editor to use your workspace TypeScript version.

    • In VSCode you can do this by pressing "F1" and typing "TypeScript: Select TypeScript version". Then select "Use workspace version". If that option does not appear, TypeScript is not installed locally in your node_modules.
      • Not required, but to remember the user to do so, you can update your .vscode/settings.json
        {
          "typescript.tsdk": "./node_modules/typescript/lib",
          "typescript.enablePromptUseWorkspaceTsdk": true
        }
    • In JetBrains you may have to disable the Vue language service, and choose the workspace version of TypeScript in the settings from the dropdown.
    • In NVim with nvim-vtsls you should refer to how to enable TypeScript plugins in vtsls
    • In Emacs, additional steps are required to enable LSPs, step by step instructions can be found here

And you're done! You'll now be able to use a set of refactors and diagnostics that target Effect!

Provided functionalities

Quickinfo

  • Show the extended type of the current Effect
  • Hovering yield* of Effect.gen will show the Effect type parameters
  • Hovering a variable assignment of a type Layer, will show info on how each service got involved
  • Hovering a layer, will attempt to produce a graph

Diagnostics

  • Better error readability when you're missing errors or service types in your Effect definitions
  • Floating Effects that are not yielded or run
  • Wrong usage of yield inside Effect.gen
  • Multiple versions of Effect in your project
  • Warn on leaking requirements in Effect services
  • Warn on Scope as requirement of a Layer
  • Warn on subsequent Effect.provide anti-pattern
  • Detect wrong Self type parameter for APIs like Effect.Service or Schema.TaggedError and similar
  • Unnecessary usages of Effect.gen or pipe()
  • Warn when using Effect.gen with the old generator adapter pattern
  • Warn when importing from a barrel file instead of from the module directly
  • Warn on usage of try/catch inside Effect.gen and family
  • Detect unnecessary pipe chains like X.pipe(Y).pipe(Z)
  • Warn when using Effect.Service with accessors: true but methods have generics or multiple signatures
  • Warn on missing service dependencies in Effect.Service declarations
  • Warn when Effect.Service is used with a primitive type instead of an object type
  • Warn when schema classes override the default constructor behavior
  • Warn when @effect-diagnostics-next-line comments have no effect (i.e., they don't suppress any diagnostic)

Completions

  • Autocomplete 'Self' in Effect.Service, Context.Tag, Schema.TaggedClass, Schema.TaggedRequest and family
  • Autocomplete Effect.gen with function*(){}
  • Autocomplete Effect.fn with the span name given by the exported member
  • Completions for DurationInput string millis/seconds/etc...
  • Allow to configure packages to be imported with namespace style import * as Effect from "effect"
  • Suggest brand when using Schema.brand
  • Effect comment directives

Refactors

  • Transform an async function definition, into an Effect by using Effect.gen.
  • Transform an async function definition, into an Effect by using Effect.gen, and generating a tagged error for each promise call.
  • Transform an async function definition, into an Effect by using Effect.fn.
  • Transform an async function definition, into an Effect by using Effect.fn, and generating a tagged error for each promise call.
  • Transform a function returning an Effect.gen into a Effect.fn
  • Implement Service accessors in an Effect.Service, Context.Tag or Effect.Tag declaration
  • Function calls to pipe: Transform a set of function calls to a pipe() call.
  • Pipe to datafirst: Transform a pipe() call into a series of datafirst function calls (where available).
  • Toggle return type signature: With a single refactor, adds or removes type annotations from the definition.
  • Remove unnecessary Effect.gen definitions that contains a single yield statement.
  • Wrap an Effect expression with Effect.gen
  • Toggle between pipe styles X.pipe(Y) and pipe(X, Y)
  • Layer Magic: Automatically compose and build layers based on service dependencies

Miscellaneous

  • Renaming a class name, will rename the identifier as well for TaggedError, TaggedClass, etc...
  • "Go to definition" for RpcClient will resolve to the Rpc definition

Options

Few options can be provided alongside the initialization of the Language Service Plugin.

{
  "compilerOptions": {
    "plugins": [
      {
        "name": "@effect/language-service",
        "refactors": true, // controls Effect refactors (default: true)
        "diagnostics": true, // controls Effect diagnostics (default: true)
        "diagnosticSeverity": { // allows to change per-rule default severity of the diagnostic in the whole project
          "floatingEffect": "warning" // example for a rule, allowed values are off,error,warning,message,suggestion
        },
        "diagnosticsName": true, // controls whether to include the rule name in diagnostic messages (default: true)
        "missingDiagnosticNextLine": "warning", // controls the severity of warnings for unused @effect-diagnostics-next-line comments (default: "warning", allowed values: off,error,warning,message,suggestion)
        "quickinfo": true, // controls Effect quickinfo (default: true)
        "quickinfoEffectParameters": "whenTruncated", // (default: "whenTruncated") controls when to display effect type parameters always,never,whenTruncated
        "quickinfoMaximumLength": -1, // controls how long can be the types in the quickinfo hover (helps with very long type to improve perfs, defaults to -1 for no truncation, can be any number eg. 1000 and TS will try to fit as much as possible in that budget, higher number means more info.)
        "completions": true, // controls Effect completions (default: true)
        "goto": true, // controls Effect goto references (default: true)
        "inlays": true, // controls Effect provided inlayHints (default: true)
        "allowedDuplicatedPackages": [], // list of package names that have effect in peer dependencies and are allowed to be duplicated (default: [])
        "barrelImportPackages": [], // package names that should be preferred as imported from the top level barrel file (default: [])
        "namespaceImportPackages": [], // package names that should be preferred as imported with namespace imports e.g. ["effect", "@effect/*"] (default: [])
        "topLevelNamedReexports": "ignore", // for namespaceImportPackages, how should top level named re-exports (e.g. {pipe} from "effect") be treated? "ignore" will leave them as is, "follow" will rewrite them to the re-exported module (e.g. {pipe} from "effect/Function")
        "importAliases": { "Array": "Arr" }, // allows to chose some different names for import name aliases (only when not chosing to import the whole module) (default: {})
        "noExternal": false, // disables features that provides links to external websites (such as links to mermaidchart.com) (default: false)
        "keyPatterns": [{ "target": "service", "pattern": "default", "skipLeadingPath": ["src/"] }] // configure the key patterns; recommended reading more on the section "Configuring Key Patterns"
      }
    ]
  }
}

DiagnosticSeverty properties list

The full list can be found in the diagnostics folder.

Why do diagnostics not appear at compile time?

TypeScript LSPs are loaded only while editing your files. That means that if you run tsc in your project, the plugin won't be loaded and you'll miss out on the Effect diagnostics.

We provide two approaches to solve this scenario.

This option works by modifing directly the source code of the tsc compiler and the typescript library in your project node_modules. This allows to get effect's diagnostics even when noEmit is enabled, for composite and incremental projects as well.

After having installed and configured the LSP for editor usage, you can run the following command inside the folder that contains your local project typescript installation:

effect-language-service patch

If everything goes smoothly, something along these lines should be printed out:

/node_modules/typescript/lib/typescript.js patched successfully.
/node_modules/typescript/lib/_tsc.js patched successfully.

Now the CLI has patched the tsc binary and the typescript library to raise Effect diagnostics even at build time if the plugin is configured in your tsconfig!

As the command output suggests, you may need to delete your tsbuildinfo files or perform a full rebuild in order to re-check previously existing files.

To make the patch persistent across package installations and updates, we recommend adding the patch command to your package.json prepare scripts:

  "scripts": {
    "prepare": "effect-language-service patch"
  }

so that across updates the patch will be re-applied again.

Option B - Using ts-patch

if you use ts-patch you can enable the transform as well to get the diagnostics also at compile time. Your tsconfig.json should look like this:

{
  "compilerOptions": {
    "plugins": [
      {
        "name": "@effect/language-service",
        "transform": "@effect/language-service/transform" // enables diagnostics at compile time when using ts-patch
      }
    ]
  }
}

To get diagnostics you need to install ts-patch which will make it possible to run tspc.

Running tspc in your project will now also run the plugin and give you the error diagnostics at compile time. Effect error diagnostics will be shown only after standard TypeScript diagnostics have been satisfied. Beware that setting noEmit will completely skip the effect diagnostics, and projects using incremental builds may encounter some issues.

$ npx tspc
index.ts:3:1 - error TS3: Effect must be yielded or assigned to a variable.

3 Effect.succeed(1)
  ~~~~~~~~~~~~~~~~~

Found 1 error in index.ts:3 

Effect-Language-Service CLI

The effect language service plugin comes with a builtin CLI tool that can be used to perform various utilities, checks and setups. Since it relies on typescript, we recommend to install it locally and run it locally to ensure it loads the same typescript version of your project rather than a global installation that may resolve to use a different TS version from the one of your project.

effect-language-service diagnostics

Provides a way to get through a CLI the list of Effect specific diagnostics; without patching your typescript installation. A --file option may be used to get diagnostics for a specific file, or --project with a tsconfig file to get an entire project.

effect-language-service check

This command runs a check of the setup of the patching mechanism of the LSP, to understand if typescript has been patched or not.

effect-language-service patch

Patches (or re-patches) your local TypeScript installation to provide Effect diagnostics at build time.

effect-language-service unpatch

Revery any previously applied patch to the local TypeScript installation.

Configuring diagnostics

You can either disable or change the severity of specific diagnostics by using comments in your code.

// @effect-diagnostics effect/floatingEffect:off
Effect.succeed(1); // This will not be reported as a floating Effect

// @effect-diagnostics effect/floatingEffect:error
Effect.succeed(1); // This will be reported as a floating effect

or you can set the severity for the entire project in the global plugin configuration

{
  "compilerOptions": {
    "plugins": [
      {
        // ...
        "diagnosticSeverity": { // allows to change per-rule default severity of the diagnostic in the whole project
          "floatingEffect": "warning" // example for a rule, allowed values are off,error,warning,message,suggestion
        },
        // ...
      }
    ]
  }
}

Configuring Key Patterns

Effect uses string keys for Services, Error Tags, RPC Methods, and more. It can happen that sometimes, after some refactors or copy/paste, you may end up having wrong or non unique keys in your services.

To avoid that, the LSP suggests deterministic patterns for keys; that can be configured by the "keyPatterns" option.

To enable reporting of wrong or outdated keys, the rule "deterministicKeys" must be enabled first (off by default). To do so, adjust its diagnosticSeverity to error.

The keyPatterns key can then contain an array of the configured patterns.

{
  "compilerOptions": {
    "plugins": [
      {
        "name": "@effect/language-service",
        // ...
        "diagnosticSeverity": {
          "deterministicKeys": "error" // enables reporting of wrong keys
          // ...
        },
        "keyPatterns": [
          {
            "target": "service", // what key type to target between service|error
            "pattern": "default", // the chosen pattern
            "skipLeadingPath": ["src/"] // other pattern specific configs
          }
        ]

      }
    ]
  }
}

Pattern: default

This pattern constructs keys by chaining package name + file path + class identifier.

E.g. @effect/package/subpath-relative-to-package-root/FileName/ClassIdentifier

If the filename and the class identifier are the same, they won't be repeated, but used only once.

The skipLeadingPath array can contain a set of prefixes to remove from the subpath part of the path. By default "src/" is removed for example.

Pattern: default-hashed

If you are concerned potentially showing service names in builds, this pattern is the same as default; but the string will be then hashed.

Pattern: package-identifier

This pattern uses the package name + identifier. This usually works great if you have a flat structure, with one file per service/error.

Using Key Patterns in custom API definitions

You can enforce and take advantage of the deterministicKeys rule also in your own custom API that provide an extends MyApi("identifier")-like experience, so basically only in extends clause of class declarations.

To do so, first you need to enable extendedKeyDetection: true in plugin options to enable slower detection of this custom patterns.

And then you'll need to add a JSDoc /** @effect-identifier */ to the parameter where you expect to receive string identifier.

Let's say for example that you want to provide a Repository() API that is basically the same of Context.Tag, but prefixes the key identifier with 'Repository/'; the definition of the Resource API would be something like this:

export function Repository(/** @effect-identifier */ identifier: string) {
  return Context.Tag("Repository/" + identifier)
}

and will be used as follows:

export class UserRepo extends Repository("Hello")<UserRepo, { /** ... */ }>() {}

Known gotchas

Svelte VSCode extension and SvelteKit

The Svelte LSP does not properly compose with other LSPs when using SvelteKit. So the Effect LSP should be loaded as last entry to ensure proper composition.

If you did not install the Svelte LSP into your local project but instead through the Svelte VSCode extension, we recommend instead to install it locally and add it as the first entry. That way it won't be applied by the VSCode extension.

Your tsconfig.json should look like this:

{
  "compilerOptions": {
    "plugins": [
      { "name": "typescript-svelte-plugin" },
      { "name": "@effect/language-service" }
    ]
  }
}

changelog

@effect/language-service

0.48.0

Minor Changes

  • #441 ed1db9e Thanks @mattiamanzati! - Add default-hashed pattern for deterministic keys

    A new default-hashed pattern option is now available for service and error key patterns. This pattern works like the default pattern but hashes the resulting string, which is useful when you want deterministic keys but are concerned about potentially exposing service names in builds.

    Example configuration:

    {
      "keyPatterns": [
        { "target": "service", "pattern": "default-hashed" },
        { "target": "error", "pattern": "default-hashed" }
      ]
    }

Patch Changes

  • #442 44f4304 Thanks @mattiamanzati! - Tone down try/catch message to ignore try/finally blocks

  • #439 b73c231 Thanks @mattiamanzati! - Fix regression in type unification for union types and prevent infinite recursion in layerMagic refactor

    • Fixed toggleTypeAnnotation refactor to properly unify boolean types instead of expanding them to true | false
    • Fixed infinite recursion issue in layerMagic refactor's adjustedNode function when processing variable and property declarations

0.47.3

Patch Changes

  • #437 e583192 Thanks @mattiamanzati! - In toggle return type refactors, skip type parameters if they are the same as the function default in some cases.

0.47.2

Patch Changes

0.47.1

Patch Changes

  • #431 acbbc55 Thanks @mattiamanzati! - Fix nested project references relative paths in CLI diagnostics command

    The CLI diagnostics command now correctly resolves paths for nested project references by:

    • Using absolute paths when parsing tsconfig files
    • Correctly resolving the base directory for relative paths in project references
    • Processing files in batches to improve memory usage and prevent leaks

0.47.0

Minor Changes

  • #429 351d7fb Thanks @mattiamanzati! - Add new diagnostics CLI command to check Effect-specific diagnostics for files or projects

    The new effect-language-service diagnostics command provides a way to get Effect-specific diagnostics through the CLI without patching your TypeScript installation. It supports:

    • --file option to get diagnostics for a specific file
    • --project option with a tsconfig file to check an entire project

    The command outputs diagnostics in the same format as the TypeScript compiler, showing errors, warnings, and messages with their locations and descriptions.

0.46.0

Minor Changes

  • #424 4bbfdb0 Thanks @mattiamanzati! - Add support to mark a service as "leakable" via JSDoc tag. Services marked with @effect-leakable-service will be excluded from the leaking requirements diagnostic, allowing requirements that are expected to be provided per method invocation (e.g. HttpServerRequest).

    Example:

    /**
     * @effect-leakable-service
     */
    export class FileSystem extends Context.Tag("FileSystem")<
      FileSystem,
      {
        writeFile: (content: string) => Effect.Effect<void>;
      }
    >() {}
  • #428 ebaa8e8 Thanks @mattiamanzati! - Add diagnostic to warn when @effect-diagnostics-next-line comments have no effect. This helps identify unused suppression comments that don't actually suppress any diagnostics, improving code cleanliness.

    The new missingDiagnosticNextLine option controls the severity of this diagnostic (default: "warning"). Set to "off" to disable.

    Example:

    // This comment will trigger a warning because it doesn't suppress any diagnostic
    // @effect-diagnostics-next-line effect/floatingEffect:off
    const x = 1;
    
    // This comment is correctly suppressing a diagnostic
    // @effect-diagnostics-next-line effect/floatingEffect:off
    Effect.succeed(1);

Patch Changes

  • #426 22717bd Thanks @mattiamanzati! - Improve Layer Magic refactor with enhanced dependency sorting and cycle detection

    The Layer Magic refactor now includes:

    • Better handling of complex layer composition scenarios
    • Support for detecting missing layer implementations with helpful error messages

0.45.1

Patch Changes

  • #423 70d8734 Thanks @mattiamanzati! - Add code fix to rewrite Schema class constructor overrides as static 'new' methods

    When detecting constructor overrides in Schema classes, the diagnostic now provides a new code fix option that automatically rewrites the constructor as a static 'new' method. This preserves the custom initialization logic while maintaining Schema's decoding behavior.

    Example:

    // Before (with constructor override)
    class MyClass extends Schema.Class<MyClass>("MyClass")({ a: Schema.Number }) {
      b: number;
      constructor() {
        super({ a: 42 });
        this.b = 56;
      }
    }
    
    // After (using static 'new' method)
    class MyClass extends Schema.Class<MyClass>("MyClass")({ a: Schema.Number }) {
      b: number;
      public static new() {
        const _this = new this({ a: 42 });
        _this.b = 56;
        return _this;
      }
    }
  • #421 8c455ed Thanks @mattiamanzati! - Update dependencies to their latest versions including Effect 3.18.4, TypeScript 5.9.3, and various ESLint and build tooling packages

0.45.0

Minor Changes

  • #419 7cd7216 Thanks @mattiamanzati! - Add support for custom APIs in deterministicKeys diagnostic using the @effect-identifier JSDoc tag.

    You can now enforce deterministic keys in custom APIs that follow an extends MyApi("identifier") pattern by:

    • Adding extendedKeyDetection: true to plugin options to enable detection
    • Marking the identifier parameter with /** @effect-identifier */ JSDoc tag

    Example:

    export function Repository(/** @effect-identifier */ identifier: string) {
      return Context.Tag("Repository/" + identifier);
    }
    
    export class UserRepo extends Repository("user-repo")<
      UserRepo,
      {
        /** ... */
      }
    >() {}

0.44.1

Patch Changes

0.44.0

Minor Changes

  • #415 42c66a1 Thanks @mattiamanzati! - Add diagnosticsName option to include rule names in diagnostic messages. When enabled (default: true), diagnostic messages will display the rule name at the end, e.g., "Effect must be yielded or assigned to a variable. effect(floatingEffect)"

0.43.2

Patch Changes

0.43.1

Patch Changes

0.43.0

Minor Changes

  • #407 6590590 Thanks @mattiamanzati! - Add deterministicKeys diagnostic to enforce consistent key patterns for Services and Errors

    This new diagnostic helps maintain consistent and unique keys for Effect Services and Tagged Errors by validating them against configurable patterns. The diagnostic is disabled by default and can be enabled via the deterministicKeys diagnosticSeverity setting.

    Two patterns are supported:

    • default: Constructs keys from package name + file path + class identifier (e.g., @effect/package/FileName/ClassIdentifier)
    • package-identifier: Uses package name + identifier for flat project structures

    Example configuration:

    {
      "diagnosticSeverity": {
        "deterministicKeys": "error"
      },
      "keyPatterns": [
        {
          "target": "service",
          "pattern": "default",
          "skipLeadingPath": ["src/"]
        }
      ]
    }

    The diagnostic also provides auto-fix code actions to update keys to match the configured patterns.

Patch Changes

  • #405 f43b3ab Thanks @mattiamanzati! - Fix wrapWithEffectGen refactor not working on class heritage clauses

    The wrapWithEffectGen refactor now correctly skips expressions in heritage clauses (e.g., extends clauses in class declarations) to avoid wrapping them inappropriately.

0.42.0

Minor Changes

  • #403 dc3f7e9 Thanks @mattiamanzati! - Add quickinfoMaximumLength option to control the maximum length of types displayed in quickinfo hover. This helps improve performance when dealing with very long types by allowing TypeScript to truncate them to a specified budget. Defaults to -1 (no truncation), but can be set to any positive number (e.g., 1000) to limit type display length.

0.41.1

Patch Changes

  • #401 394fa8d Thanks @mattiamanzati! - Add Effect.Tag completion for classes extending Effect

    When typing Effect. in a class that extends Effect, the completion now also suggests Effect.Tag alongside the existing Effect.Service completion. This provides an additional way to define tagged services using the Effect.Tag pattern.

  • #398 ae323d7 Thanks @mattiamanzati! - Refactor internal TypeScript API wrappers to TypeScriptApi module for better code organization

  • #400 6537461 Thanks @mattiamanzati! - Reuse program package json info cache if available

0.41.0

Minor Changes

  • #396 744de40 Thanks @mattiamanzati! - Add new diagnostic to warn when Effect.Service is used with a primitive type instead of an object type. This diagnostic helps prevent common mistakes where developers try to use primitive values (strings, numbers, etc.) as service types, which is not supported by Effect.Service. The diagnostic suggests wrapping the value in an object or manually using Context.Tag or Effect.Tag for primitive types.

0.40.1

Patch Changes

0.40.0

Minor Changes

  • #384 62b9829 Thanks @mattiamanzati! - Add new diagnostic: effectGenUsesAdapter - warns when using Effect.gen with the generator adapter pattern (function*(_)) instead of using pipe()

    The generator adapter pattern function*(_) is an old pattern. Users should use pipe() for composing effects or Effect.gen(function*()) without the adapter for generator-based code.

    Example that will trigger the warning:

    const example = Effect.gen(function* (_) {
      const result = yield* _(Effect.succeed(42));
      return result;
    });

Patch Changes

0.39.0

Minor Changes

0.38.4

Patch Changes

  • #378 2f9bc51 Thanks @mattiamanzati! - Add support for Effect.Tag in writeTagClassAccessors refactor

    The writeTagClassAccessors refactor now supports Effect.Tag classes in addition to Effect.Service and Context.Tag. This allows users to generate accessor methods for services created with Effect.Tag, maintaining consistency across all tag-based service patterns.

0.38.3

Patch Changes

  • #375 74696fd Thanks @mattiamanzati! - Fix resolveModulePattern to use fallback mechanism for package scope resolution when primary method is unavailable

0.38.2

Patch Changes

  • #374 9d66c1e Thanks @mattiamanzati! - Fix Mermaid graph generation for layers with generic types

    Properly escape angle brackets (< and >) in Mermaid diagrams to prevent rendering issues when displaying layer names containing generic type parameters.

  • #370 0e25fbc Thanks @mattiamanzati! - Layer Magic refactor now shows previously provided layers as a comment in the generated type annotation.

    When using the Layer Magic "Prepare for reuse" refactor, layers that were already provided at the location are now shown as a trailing comment (e.g., /* Foo | Bar */) next to the newly introduced layer types. This helps developers understand which layers were already available and which ones are being newly introduced.

  • #372 172363c Thanks @mattiamanzati! - Add general support for Effect.Tag in various diagnostics/refactors

0.38.1

Patch Changes

0.38.0

Minor Changes

  • #365 3b418c5 Thanks @mattiamanzati! - Add Layer Magic refactor for automatic layer composition and building

    This refactor allows you to automatically compose and build layers based on service dependencies. It helps simplify complex layer constructions by:

    • Analyzing service dependencies
    • Automatically composing layers in the correct order
    • Building final layer structures with proper dependency resolution

    Example: When working with services that have dependencies, the refactor can transform your layer setup code into a properly composed layer structure that respects all service requirements.

Patch Changes

0.37.0

Minor Changes

Patch Changes

  • #356 8c906e1 Thanks @mattiamanzati! - Add helper for renames, so that triggering a rename will include the identifier of a class as well

  • #360 331051d Thanks @mattiamanzati! - Some minor perf improvements

  • #358 03cfa73 Thanks @mattiamanzati! - Refactor TypeChecker utilities to improve code organization by moving utility functions from TypeCheckerApi.ts to TypeCheckerUtils.ts

  • #364 358f323 Thanks @mattiamanzati! - Replace direct .text property access with TypeScript API helper ts.idText() for getting identifier text from nodes. This is a more robust approach that properly handles escaped identifiers and follows TypeScript's recommended practices.

0.36.0

Minor Changes

Patch Changes

  • #353 790d4d0 Thanks @mattiamanzati! - Fix CLI and LSP improvements:

    • Remove deprecated check command from CLI
    • Fix unpatch command to default to both typescript and tsc modules when no modules specified
    • Add concatDiagnostics utility to prevent duplicate diagnostics in LSP
  • #351 be5d851 Thanks @mattiamanzati! - Fix TypeScript module reference in patch utility to use correct module name when patching TypeScript directly

  • #349 46a1ef2 Thanks @mattiamanzati! - Introduce ts-patch less mode

0.35.2

Patch Changes

  • #346 5a37be2 Thanks @mattiamanzati! - Fix auto-import barrel-to-barrel mapping for top-level named re-exports

    When topLevelNamedReexports is set to "follow", the auto-import provider now correctly maps barrel exports to their barrel modules, ensuring proper import suggestions for re-exported functions like pipe from effect/Function.

0.35.1

Patch Changes

  • #345 92ee0ff Thanks @mattiamanzati! - Fix async/await to Effect.gen.tryPromise and Effect.fn.tryPromise refactors to use Data.TaggedError for error handling instead of inline objects

  • #343 0570ccf Thanks @mattiamanzati! - Fix async/await to Effect.fn refactor to use correct function name

    Previously, the refactor would incorrectly use the function's own name instead of Effect.fn when transforming async functions. This patch fixes the issue to properly generate Effect.fn("functionName") in the refactored code.

0.35.0

Minor Changes

  • #339 ef70757 Thanks @mattiamanzati! - Add new refactors to transform async/await functions to Effect.fn

    • Transform an async function definition into an Effect by using Effect.fn
    • Transform an async function definition into an Effect by using Effect.fn with tagged errors for each promise call

    These refactors complement the existing Effect.gen refactors by providing an alternative transformation using Effect.fn.

Patch Changes

0.34.0

Minor Changes

  • #335 81a090a Thanks @mattiamanzati! - Add new diagnostic to warn when schema classes override the default constructor behavior

    The new diagnostic helps catch cases where schema classes define custom constructors that might break the expected schema behavior. Example:

    import { Schema } from "effect";
    
    class MySchema extends Schema.Class<MySchema>("MySchema")({
      value: Schema.String,
    }) {
      // This will trigger a warning
      constructor(props: { value: string }) {
        super(props);
      }
    }

    The diagnostic provides quickfixes to either:

    • Remove the constructor
    • Suppress the warning for the current line
    • Suppress the warning for the entire file

Patch Changes

  • #337 d72b1b4 Thanks @mattiamanzati! - Improve effectGenToFn refactor to preserve function names

    The effectGenToFn refactor now extracts and preserves the original function name when converting from Effect.gen to Effect.fn. For example:

    // Before refactor
    export const programWithPipes = (fa: number, fb: number) =>
      Eff.gen(
        function* () {
          const a = yield* Eff.succeed(fa);
          const b = yield* Eff.succeed(fb);
          return a + b;
        },
        Eff.map((a) => a + 1)
      );
    
    // After refactor (now preserves "programWithPipes" name)
    export const programWithPipes = Eff.fn("programWithPipes")(
      function* (fa: number, fb: number) {
        const a = yield* Eff.succeed(fa);
        const b = yield* Eff.succeed(fb);
        return a + b;
      },
      Eff.map((a) => a + 1)
    );

0.33.2

Patch Changes

  • #331 d862c23 Thanks @mattiamanzati! - Fix diagnostics not running for all source files in transform

    Previously, diagnostics were only running on the current file being transformed instead of all root files in the TypeScript program. This could cause some diagnostics to be missed during compilation.

    Also updated README with important notes about ts-patch limitations:

    • Effect diagnostics in watch mode with noEmit enabled are not supported
    • Incremental builds may require a full rebuild after enabling ts-patch to invalidate the previous diagnostics cache

0.33.1

Patch Changes

  • #328 e25a3f9 Thanks @mattiamanzati! - feat: add inlay hints for Effect.gen-like middleware functions

    Improved inlay hints for Effect.gen-like middleware functions to reduce visual clutter by omitting redundant type annotations that TypeScript already provides.

0.33.0

Minor Changes

  • #327 52de365 Thanks @mattiamanzati! - Add support for inlay hints in Effect.gen-like middleware functions

    This feature provides TypeScript inlay hints for generator functions used with Effect.gen, Effect.fn.gen, and Effect.fn.untraced.gen. When enabled, it shows the inferred return type directly in the editor, making it easier to understand the types without hovering over the function.

    Example:

    const myEffect = Effect.gen(function* () /* : Effect<number> */ {
      yield* Effect.succeed(42);
    });
  • #325 cbea35a Thanks @mattiamanzati! - Add quickinfoEffectParameters configuration option to control when Effect type parameters are displayed in quickinfo

    This new option allows users to configure when Effect type parameters are shown in hover information:

    • "always": Always show type parameters
    • "never": Never show type parameters
    • "whenTruncated" (default): Only show when TypeScript truncates the type display

    Example configuration:

    {
      "effectLanguageService": {
        "quickinfoEffectParameters": "whenTruncated"
      }
    }

0.32.0

Minor Changes

  • #323 b584cde Thanks @mattiamanzati! - Added support for topLevelNamedReexports configuration option to control how top-level named re-exports are handled when using namespaceImportPackages.

    • "ignore" (default): Named re-exports like import { pipe } from "effect" are left as-is
    • "follow": Named re-exports are rewritten to their original module, e.g., import { pipe } from "effect/Function"

    This allows users to have more control over their import style preferences when using namespace imports.

Patch Changes

  • #321 022956a Thanks @mattiamanzati! - Improve diagnostic message for missingReturnYieldStar to better explain why return yield* is recommended for Effects that never succeed

  • #324 8271284 Thanks @mattiamanzati! - Improve floating effect diagnostic message to specify the actual type being flagged. When detecting floating Stream or other Effect subtypes, the error message now shows "Effect-able Stream<...>" instead of just "Effect", making it clearer what type needs to be handled.

0.31.2

Patch Changes

  • #318 9928704 Thanks @mattiamanzati! - Improve missing Effect service dependency diagnostic

    • Enhanced TypeParser to better handle service dependencies detection
    • Fixed ValidService5 example in test files to properly demonstrate valid service usage
    • Updated test snapshots to reflect the corrected behavior

0.31.1

Patch Changes

0.31.0

Minor Changes

  • #312 5d4f5c6 Thanks @mattiamanzati! - Add missingEffectServiceDependency diagnostic

    This diagnostic warns when an Effect.Service declaration has missing service dependencies. It checks if all services used within the service's effect are properly declared in the dependencies array.

    Example:

    // This will show a warning because SampleService1 is used but not declared in dependencies
    export class InvalidService extends Effect.Service<InvalidService>()(
      "InvalidService",
      {
        effect: Effect.gen(function* () {
          const sampleService1 = yield* SampleService1;
          return {
            constant: Effect.succeed(sampleService1.value),
          };
        }),
        // Missing: dependencies: [SampleService1.Default]
      }
    ) {}

0.30.0

Minor Changes

  • #311 f2dc3c4 Thanks @mattiamanzati! - Add unsupportedServiceAccessors diagnostic that warns when using Effect.Service with accessors: true but methods have generics or multiple signatures

  • #309 949d5eb Thanks @mattiamanzati! - Add classSelfMismatch diagnostic rule

    This new diagnostic rule checks that the Self type parameter in Effect.Service, Context.Tag, and Schema classes matches the actual class name.

    Example:

    // ❌ Error: Self type parameter should be 'MyService'
    class MyService extends Effect.Service<WrongName>()("MyService", {
      succeed: { value: 1 },
    }) {}
    
    // ✅ Correct
    class MyService extends Effect.Service<MyService>()("MyService", {
      succeed: { value: 1 },
    }) {}

    The diagnostic includes a quick fix to automatically correct the mismatch.

0.29.0

Minor Changes

  • #306 7f3facc Thanks @mattiamanzati! - Extract TypeScript utilities into a dedicated TypeScriptUtils module

    This refactoring improves code organization by consolidating TypeScript-related utilities into a separate TypeScriptUtils module. The changes include:

    • Created new src/core/TypeScriptUtils.ts module containing all TypeScript utility functions
    • Removed the old src/core/AST.ts file which contained scattered utilities
    • Updated all imports across the codebase to use the new module structure
    • Improved type safety and consistency in TypeScript API interactions
    • Enhanced modularity by using the Nano dependency injection pattern

    This change maintains backward compatibility while providing better separation of concerns and easier maintenance of TypeScript-related functionality.

  • #308 e649978 Thanks @mattiamanzati! - Add codegen functionality including:

    • New completion provider for Effect codegens via comments
    • New diagnostic for outdated Effect codegen with quickfixes
    • Improved tag class accessors refactor with better formatting
    • Enhanced TypeScript utilities and type parsing capabilities

0.28.3

Patch Changes

  • #303 e603a89 Thanks @mattiamanzati! - Refactor AutoImport provider and add sortText support

  • #304 5885afe Thanks @mattiamanzati! - Add middleware for auto-import quickfixes

    • Extracted auto-import logic into a reusable AutoImport core module
    • Refactored existing middleware auto-import completion to use the new shared AutoImport provider
    • This enables consistent auto-import behavior across both completions and quickfixes
  • #301 d6b36f8 Thanks @mattiamanzati! - Update message for multiple Effect.provide diagnostic

0.28.2

Patch Changes

0.28.1

Patch Changes

0.28.0

Minor Changes

Patch Changes

0.27.2

Patch Changes

0.27.1

Patch Changes

0.27.0

Minor Changes

0.26.0

Minor Changes

0.25.1

Patch Changes

0.25.0

Minor Changes

Patch Changes

0.24.2

Patch Changes

0.24.1

Patch Changes

0.24.0

Minor Changes

Patch Changes

  • #257 d875f85 Thanks @mattiamanzati! - Add quickfixes to missingEffectError to implement catchAll or catchTags based on the missing errors context

0.23.5

Patch Changes

0.23.4

Patch Changes

  • #251 19dcecf Thanks @mattiamanzati! - Allow wildcard * at end of ImportPackages settings to match all packages starting with a prefix

0.23.3

Patch Changes

  • #247 b7abbdf Thanks @mattiamanzati! - Add exclusion rules for barrel style so pipe will be imported from "effect" instead of "effect/Function"

0.23.2

Patch Changes

0.23.1

Patch Changes

0.23.0

Minor Changes

0.22.3

Patch Changes

0.22.2

Patch Changes

0.22.1

Patch Changes

0.22.0

Minor Changes

Patch Changes

0.21.8

Patch Changes

0.21.7

Patch Changes

0.21.6

Patch Changes

0.21.5

Patch Changes

0.21.4

Patch Changes

0.21.3

Patch Changes

0.21.2

Patch Changes

0.21.1

Patch Changes

0.21.0

Minor Changes

Patch Changes

0.20.1

Patch Changes

0.20.0

Minor Changes

Patch Changes

0.19.0

Minor Changes

0.18.1

Patch Changes

  • #179 a170bfc Thanks @mattiamanzati! - Handle unnecessary Effect.gen even when yielded expression is not returned

    export const shouldRaiseForSingle = Effect.gen(function* () {
      yield* Effect.succeed(42);
    });
    // ^- this will become Effect.asVoid(Effect.succeed(42))
    
    export const shouldRaiseForSingleReturnVoid = Effect.gen(function* () {
      yield* Effect.void;
    });
    // ^- this will become Effect.void

0.18.0

Minor Changes

Patch Changes

0.17.1

Patch Changes

0.17.0

Minor Changes

0.16.7

Patch Changes

0.16.6

Patch Changes

0.16.5

Patch Changes

0.16.4

Patch Changes

0.16.3

Patch Changes

0.16.2

Patch Changes

0.16.1

Patch Changes

0.16.0

Minor Changes

0.15.1

Patch Changes

0.15.0

Minor Changes

0.14.0

Minor Changes

0.13.0

Minor Changes

Patch Changes

0.12.2

Patch Changes

0.12.1

Patch Changes

0.12.0

Minor Changes

0.11.0

Minor Changes

0.10.2

Patch Changes

0.10.1

Patch Changes

0.10.0

Minor Changes

0.9.2

Patch Changes

  • #109 c325568 Thanks @mattiamanzati! - Add support for completions for Data.TaggedClass and Data.TaggedError

  • #106 63cc227 Thanks @wmaurer! - Fixed a bug where certain refactors were not available when the cursor was position at the start of a node

0.9.1

Patch Changes

0.9.0

Minor Changes

0.8.1

Patch Changes

0.8.0

Minor Changes

Patch Changes

0.7.1

Patch Changes

0.7.0

Minor Changes

  • #88 c3944ce Thanks @wmaurer! - Add refactor remove-unnecessary-effect-gen. This removes unnecessary Effect.gen calls by simplifying generator functions that only wrap a single yield* statement returning an Effect. This refactor replaces the Effect.gen wrapper with the inner Effect directly, making the code more concise and readable.

0.6.2

Patch Changes

0.6.1

Patch Changes

0.6.0

Minor Changes

Patch Changes

0.5.1

Patch Changes

  • #73 3c9c1ba Thanks @mattiamanzati! - Avoid to bail-out type generation when imports are missing, show instead partial signature

0.5.0

Minor Changes

  • #71 8d309ab Thanks @mattiamanzati! - Detect unnecessary usages of Effect.gen

  • #68 79ce0b1 Thanks @mattiamanzati! - Adds support for quickinfo for effect

    They can be disabled by the LSP option "quickinfo": false.

    Once you hover a truncated type, you'll see additional information about the Effect type arguments like Success, Failure and Requirements.

Patch Changes

0.4.0

Minor Changes

Patch Changes

0.3.2

Patch Changes

0.3.1

Patch Changes

0.3.0

Minor Changes

  • #54 19e5a77 Thanks @mattiamanzati! - - Update internal version of effect from 2.x beta to 3.12.5

    • Remove adapter from gen refactors
  • #56 5b2b27c Thanks @mattiamanzati! - Add support for Effect diagnostics

    With this release of the language service plugin, we aim to improve the overall Effect experience by providing additional diagnostics that tries to fix misleading or hard to read TypeScript errors.

    All of the diagnostics provided by the language service are available only in editor-mode, that means that they won't show up when using tsc.

    Diagnostics are enabled by default, but you can opt-out of them by changing the language service configuration and provide diagnostics: false.

    {
      "plugins": [
        {
          "name": "@effect/language-service",
          "diagnostics": false
        }
      ]
    }

    Please report any false positive or missing diagnostic you encounter over the Github repository.

    Missing Errors and Services in Effects

    Additionally to the standard TypeScript error that may be cryptic at first:

    Argument of type 'Effect<number, never, ServiceB | ServiceA | ServiceC>' is not assignable to parameter of type 'Effect<number, never, ServiceB | ServiceA>' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of the target's properties.
      Type 'ServiceB | ServiceA | ServiceC' is not assignable to type 'ServiceB | ServiceA'.
        Type 'ServiceC' is not assignable to type 'ServiceB | ServiceA'.
          Type 'ServiceC' is not assignable to type 'ServiceA'.
            Types of property 'a' are incompatible.
              Type '3' is not assignable to type '1'.ts(2379)

    you'll now receive an additional error:

    Missing 'ServiceC' in the expected Effect context.

    Floating Effect

    In some situation you may not receive any compile error at all, but that's because you may have forgot to yield your effects inside gen!

    Floating Effects that are not assigned to a variable will be reported into the Effect diagnostics.

    Effect.runPromise(
      Effect.gen(function* () {
        Effect.sync(() => console.log("Hello!"));
        // ^- Effect must be yielded or assigned to a variable.
      })
    );

    Used yield instead of yield*

    Similarly, yield instead of yield* won't result in a type error by itself, but is not the intended usage.

    This yield will be reported in the effect diagnostics.

    Effect.runPromise(
      Effect.gen(function* () {
        yield Effect.sync(() => console.log("Hello!"));
        // ^- When yielding Effects inside Effect.gen, you should use yield* instead of yield.
      })
    );

0.2.0

Minor Changes

0.1.0

Minor Changes

  • #48 9bb0011 Thanks @wmaurer! - Improve Effect imports to work with current effect npm package

  • #48 9bb0011 Thanks @wmaurer! - Modernise build setup. Fix asyncWaitToGen problem for TS5. Refactor asyncWaitToGen to work with current Effect API. Add config option preferredEffectGenAdapterName.

0.0.21

Patch Changes

0.0.20

Patch Changes

0.0.19

Patch Changes

0.0.18

Patch Changes

0.0.17

Patch Changes

0.0.16

Patch Changes

0.0.15

Patch Changes

0.0.14

Patch Changes

0.0.13

Patch Changes

0.0.12

Patch Changes

0.0.11

Patch Changes

0.0.10

Patch Changes

0.0.9

Patch Changes

0.0.8

Patch Changes

0.0.7

Patch Changes

0.0.6

Patch Changes

0.0.5

Patch Changes

0.0.4

Patch Changes

0.0.3

Patch Changes

0.0.2

Patch Changes

0.0.1

Patch Changes

  • #2 8915f80 Thanks @mattiamanzati! - Fixed type annotation removal in both toggle return type and toggle type annotation