@effect/tsgo
0.56.0 · 21 Oct 2026MIT587.3k / weekRepositoryHomepagenpmAtom feed
125 stable releases, newest first, by release line. Notes are quoted as the maintainers published them.
- 0.56.x · latest line
0.56.0
21 Oct 202697d3c56: Track the
typescript@betadist-tag alongsidetypescript@latestandtypescript@next.repoctl upstream updatenow resolves the beta tag intoupstream.json, so the TypeScript beta compiler (currently7.1.0-beta) is built, tested in CI under thebetachannel, and shipped with the platform packages.eb044ca: Update the TypeScript next tag to
typescript@next, which shipstypescript-gocommit28534d7609062699a68b1b66e2367f8d95dbf290, update the TypeScript beta tag totypescript@beta, and update the TypeScript latest tag totypescript@latest.
- 0.55.x
0.55.0
20 Oct 2026d53a707: Add the opt-in
preferEffectStringdiagnostic ineffectNativefor native String method invocations. It suggests 32effect/Stringcounterparts, includingtrimLefttoString.trimStartandtrimRighttoString.trimEnd.Each suggestion explains typing or runtime differences. For example,
email.indexOf("@")suggestsString.indexOf, which returns Option with None replacing -1.The rule defaults to off and the
effect-nativepreset enables it as a warning. Both Effect v3 and v4 are supported. Only suppression quick fixes are available.
- 0.54.x
0.54.1
20 Oct 202670bb791: Update the TypeScript next tag to
typescript@next, which shipstypescript-gocommit5237fd46890956e4bb8177a1a05dcd69e4166560, and update the TypeScript latest tag totypescript@latest. Refresh the Oxlint configuration schema from the selected package.
0.54.0
19 Oct 2026e00f33c: Add the
schemaClassObjectLiteraldiagnostic. It warns when an object literal is checked as a Schema class instance. A plain object has no class prototype, soinstanceof, class methods, and Schema encoding fail at runtime. A Schema brand does not help, because a spread copies the brand property.class User extends Schema.Class<User, { readonly brand: unique symbol }>("User")({ name: Schema.String }) {} const copy: User = { ...user } // warning: build it with User.make({ ...user }) const renamed = User.make({ ...user, name: "b" }) // okIn Effect v4, the rule skips objects nested inside a Schema constructor call, such as
Parent.make({ child: { ...child } }), because v4 builds the nested class instance from the plain object.
- 0.53.x
0.53.5
19 Oct 2026c83ee4d:
runEffectInsideEffectnow reportsEffect.runSyncExitandEffect.runPromiseExit, the same asEffect.runSyncandEffect.runPromise. The quick fix rewrites them toEffect.runSyncExitWithandEffect.runPromiseExitWithin Effect v4, and toRuntime.runSyncExitandRuntime.runPromiseExitin Effect v3.export const nested = Effect.gen(function*() { yield* Effect.void setTimeout(() => { Effect.runPromiseExit(child) // ^- `Effect.runPromiseExit` is called inside an Effect with a separate services invocation. }, 0) })de42db0: Update the TypeScript next tag to
typescript@next, which shipstypescript-gocommit5237fd46890956e4bb8177a1a05dcd69e4166560, and update the TypeScript latest tag totypescript@latest.
0.53.4
17 Oct 2026f57afb9: Update the TypeScript next tag to
typescript@next, which shipstypescript-gocommitabcbb2e69d2a86d9ffee66582a0dd0339b674733, and update the TypeScript latest tag totypescript@latest.
0.53.3
16 Oct 20261ab5264:
effect-tsgo diagnosticsnow reports a diagnostic's related locations. They used to be dropped in every format, somissingEffectContextnever showed which layer could provide the missing service andapiStabilityLeaknever showed where the unstable declaration lives.With
--format json, each diagnostic that has related locations gets arelatedInformationarray. Each entry has the same location fields as the diagnostic, plus its owncodeandmessage. Diagnostics without related locations are unchanged.{ "line": 23, "column": 3, "code": 377004, "name": "missingEffectContext", "message": "This Effect requires a service that is missing from the expected Effect context: `Db | Fs`.", "relatedInformation": [ { "file": ".../src/index.ts", "start": 662, "length": 14, "line": 22, "column": 3, "endLine": 22, "endColumn": 17, "code": 377059, "message": "Adjusting this layer composition could provide the missing service." } ] }With
--format pretty, the related locations are printed under the diagnostic, each with its own code snippet, astsc --prettydoes:src/index.ts:23:3 - error effect(missingEffectContext): This Effect requires a service that is missing from the expected Effect context: `Db | Fs`. 23 Effect.runPromise ~~~~~~~~~~~~~~~~~ src/index.ts:22:3 - Adjusting this layer composition could provide the missing service. 22 Effect.provide(live), ~~~~~~~~~~~~~~The
~markers in pretty output are also aligned again on lines 10 and above. They used to sit one column to the left of the code.4672ba1: Make
globalDateandglobalDateInEffectdo less work per file. Their shared walker used to look up the Effect context flags of every node it visited, although only call expressions (Date.now()) andnewexpressions (new Date()) can produce a diagnostic. It now looks up the flags only on those two node kinds, likeglobalFetch,globalConsole,globalTimers,globalRandomandcryptoRandomUUIDalready do.Reported diagnostics are unchanged.
b5df4e9: Speed up
apiStabilityLeakby reusing one stability analysis per file.The rule used to allocate a fresh analysis, with its maps and work queues, for every export of a file. It now keeps one analysis per file and resets it before each export. The reset analysis behaves exactly like a fresh one, so the reported diagnostics are unchanged. A published surface that a later export reads from the shared cache is no longer queued for publication again, and a published surface without retained findings no longer allocates a findings map.
On
packages/effectof effect 4.0.5 with every rule enabled, the rule allocates 252 MB → 140 MB.
Patch Changes
1ab5264:
effect-tsgo diagnosticsnow reports a diagnostic's related locations. They used to be dropped in every format, somissingEffectContextnever showed which layer could provide the missing service andapiStabilityLeaknever showed where the unstable declaration lives.With
--format json, each diagnostic that has related locations gets arelatedInformationarray. Each entry has the same location fields as the diagnostic, plus its owncodeandmessage. Diagnostics without related locations are unchanged.{ "line": 23, "column": 3, "code": 377004, "name": "missingEffectContext", "message": "This Effect requires a service that is missing from the expected Effect context: `Db | Fs`.", "relatedInformation": [ { "file": ".../src/index.ts", "start": 662, "length": 14, "line": 22, "column": 3, "endLine": 22, "endColumn": 17, "code": 377059, "message": "Adjusting this layer composition could provide the missing service." } ] }With
--format pretty, the related locations are printed under the diagnostic, each with its own code snippet, astsc --prettydoes:src/index.ts:23:3 - error effect(missingEffectContext): This Effect requires a service that is missing from the expected Effect context: `Db | Fs`. 23 Effect.runPromise ~~~~~~~~~~~~~~~~~ src/index.ts:22:3 - Adjusting this layer composition could provide the missing service. 22 Effect.provide(live), ~~~~~~~~~~~~~~The
~markers in pretty output are also aligned again on lines 10 and above. They used to sit one column to the left of the code.4672ba1: Make
globalDateandglobalDateInEffectdo less work per file. Their shared walker used to look up the Effect context flags of every node it visited, although only call expressions (Date.now()) andnewexpressions (new Date()) can produce a diagnostic. It now looks up the flags only on those two node kinds, likeglobalFetch,globalConsole,globalTimers,globalRandomandcryptoRandomUUIDalready do.Reported diagnostics are unchanged.
b5df4e9: Speed up
apiStabilityLeakby reusing one stability analysis per file.The rule used to allocate a fresh analysis, with its maps and work queues, for every export of a file. It now keeps one analysis per file and resets it before each export. The reset analysis behaves exactly like a fresh one, so the reported diagnostics are unchanged. A published surface that a later export reads from the shared cache is no longer queued for publication again, and a published surface without retained findings no longer allocates a findings map.
On
packages/effectof effect 4.0.5 with every rule enabled, the rule allocates 252 MB → 140 MB.d3b53a7: Make the Effect diagnostics write less to the checker's per-node caches. Rules run on the checker goroutine right after each file is checked, and on the Effect monorepo most of their cost was cache traffic (map misses, nil inserts, map growth) and the garbage collection it caused, not type computation.
Reference checks such as "is this node
Effect.gen?" no longer probe or fill the symbol cache for statements, blocks, clauses and tokens, which can never resolve to a symbol.The analysis that tracks whether code runs inside
Effect.gen,Effect.fnor an Effect thunk stores an entry only where the answer changes, about 2% of nodes, instead of two entries for every node of every file.Type lookups reject nodes that can never have a type before touching the cache, the strict Effect type check caches only types named
Effect, and whether a file has been checked is asked once per file instead of on every query.
Reported diagnostics are unchanged.
0.53.2
16 Oct 2026c75c219: Make
apiStabilityLeakallocate less. The rule used to create an empty findings map for every type, signature and symbol it inspected, and to copy the stored findings into a new map every time it re-checked an unresolved result. Most results never get a finding, and most re-checks add nothing. A result's map is now created when it gets its first finding, and a re-check that adds nothing keeps the stored map instead of copying it.For example, on the Effect monorepo the rule allocated 605 MB in 5.3 M objects before and 496 MB in 3.4 M objects after. Its CPU went from 3.4 s to 3.2 s.
Reported diagnostics are unchanged.
0076e24: Make
apiStabilityLeakfaster on namespace exports. The rule checks each member of a namespace export in one shared analysis, and every member used to re-check every unresolved result that earlier members left behind. A namespace with thousands of members did millions of repeated checks. Each member now re-checks only the results its own check reached.For example, on the Effect monorepo the
Generatednamespace export of@effect/ai-openaihas 3,603 members. Across the whole repository the rule used 22.8 s of CPU before and 3.4 s after.Reported diagnostics are unchanged.
410f21e: Rules now read the type the checker computed for an expression while it checked the file, instead of asking the checker again afterwards. Asking again repeated work, such as flow analysis, and in a few cases gave a different type than the check used. For example, a return literal checked while its enclosing generic call was still resolving:
export const takeWhileDefined = dual(2, <A>(self: Iterable<A>, f: (input: A) => A | undefined) => ({ [Symbol.iterator]() { const iterator = self[Symbol.iterator]() return { next() { const result = iterator.next() if (result.done) { // the check typed this as { done: boolean; value: undefined } // asking again gave { done: true; value: undefined } return { done: true, value: undefined } } return { done: false, value: f(result.value) } } } } }))Rules now see
{ done: boolean; value: undefined }, the type the rest of the check is based on.
Patch Changes
c75c219: Make
apiStabilityLeakallocate less. The rule used to create an empty findings map for every type, signature and symbol it inspected, and to copy the stored findings into a new map every time it re-checked an unresolved result. Most results never get a finding, and most re-checks add nothing. A result's map is now created when it gets its first finding, and a re-check that adds nothing keeps the stored map instead of copying it.For example, on the Effect monorepo the rule allocated 605 MB in 5.3 M objects before and 496 MB in 3.4 M objects after. Its CPU went from 3.4 s to 3.2 s.
Reported diagnostics are unchanged.
0076e24: Make
apiStabilityLeakfaster on namespace exports. The rule checks each member of a namespace export in one shared analysis, and every member used to re-check every unresolved result that earlier members left behind. A namespace with thousands of members did millions of repeated checks. Each member now re-checks only the results its own check reached.For example, on the Effect monorepo the
Generatednamespace export of@effect/ai-openaihas 3,603 members. Across the whole repository the rule used 22.8 s of CPU before and 3.4 s after.Reported diagnostics are unchanged.
410f21e: Rules now read the type the checker computed for an expression while it checked the file, instead of asking the checker again afterwards. Asking again repeated work, such as flow analysis, and in a few cases gave a different type than the check used. For example, a return literal checked while its enclosing generic call was still resolving:
export const takeWhileDefined = dual(2, <A>(self: Iterable<A>, f: (input: A) => A | undefined) => ({ [Symbol.iterator]() { const iterator = self[Symbol.iterator]() return { next() { const result = iterator.next() if (result.done) { // the check typed this as { done: boolean; value: undefined } // asking again gave { done: true; value: undefined } return { done: true, value: undefined } } return { done: false, value: f(result.value) } } } } }))Rules now see
{ done: boolean; value: undefined }, the type the rest of the check is based on.c5d3d7a: Resolve Effect API references once per symbol.
IsNodeReferenceToModuleExportused to answer "is this symbol exported asgen?" one member name at a time, caching each answer in a per-symbol map. It now computes, once per symbol, the names its declaring module exports it under, from a per-module index of exports keyed the way the checker compares symbols, and answers every member name from that list.export =modules keep the direct lookup.For example, checking whether a callee is
Effect.gen,Effect.fnorEffect.syncnow reads one cached list (["gen"]forEffect.gen) instead of hashing three cache keys.With 125 rules enabled on the Effect monorepo, wall time, CPU time and peak memory are unchanged within noise, and the reported diagnostics are unchanged.
f02bf75: Skip Effect type queries for more expressions that always produce a primitive or a
RegExp.NodeCannotBeEffectLibraryTypenow also rules outtrue,false,null, regular expression literals, prefix unary expressions such as!xand-x,void xandtypeof x. Theundefinedidentifier still goes through the checker, because a local binding can shadow it.For example, for
return trueinsideEffect.gen,returnEffectInGenno longer asks the checker for the type oftrue.Reported diagnostics are unchanged.
67d58fc: Add a Perf workflow that compares each pull request against its base for every supported TypeScript channel. Each job runs stock and Effect-patched tsgo on a pinned Effect checkout with every rule executing, and a sticky PR comment reports the change in symbols, types, instantiations, allocations, and check and total time over stock. Run it locally with
repoctl perf ciandrepoctl perf report.01f337a: Report each problem once in
effectInFailure,anyUnknownInErrorContextandpromiseInEffectSuccess. These rules check the type of every node in a file, and the checker gives some pairs of nodes the same type. A declaration and its name share a type, and so doa.band its nameb. The rules now check one node of each pair.A variable whose initializer has the problem used to get two warnings, one on the variable name and one on the initializer. Now only the initializer is reported:
// before: warnings on `shouldReport` and on `Effect.try(...)` // after: one warning on `Effect.try(...)` export const shouldReport = Effect.try({ try: () => JSON.parse("{"), catch: (e) => Effect.log(e) })A property access is now reported over the whole expression
promiseEffectHolder.currentinstead of the namecurrent.anyUnknownInErrorContextkeeps only the innermost warning when nested expressions report the same problem. It used to drop an outer warning whenever any warning inside it reported something. Now it drops the outer warning only when an inner warning reports every channel the outer one does, with the sameanyorunknown. An outerunknownerror channel that comes from an explicit type argument is still reported when the inner expressions only haveany:declare const anyFailure: Effect.Effect<number, any> // warnings on `Effect.withFiber(...)` (unknown in the error channel) and on `anyFailure` (any) export const keepsDifferentKind = Effect.withFiber<number, unknown>(() => anyFailure)
0.53.1
15 Oct 202606f7842: Stop
experimentalApiUsageandunstableApiUsagefrom causing TS2589 and follow-on type errors in generic calls such asMatch.when({ kind: "A0" }, ...)over a wide union.When a generic call infers a property back to the object literal, the rules look up the type the literal would get without its own inferences. They used to resolve the call again with inference blocked, which could instantiate types the original check never built. They now replay the checker's type-argument inference on the signature it already resolved and leave out the literal's argument, so return type inferences, inferences from the other arguments, defaults, and constraints apply as before. When that type has no matching property, the rules use the type parameters' constraints.
These cases are now reported too:
f4b49a4: Update the TypeScript next tag to
typescript@next, which shipstypescript-gocommit9eedcb0dd7257f8a1a175adbef28f3b6d3492d7a, and update the TypeScript latest tag totypescript@latest.
0.53.0
14 Oct 202613a46c9: The
deterministicKeysrule and the key completions now compute a key for files without apackage.json, or whose nearestpackage.jsonhas noname. The key is built as usual, but without the package name. The sub-directory segment is relative to thepackage.jsondirectory if one is found, otherwise to thetsconfig.jsondirectory, otherwise to the program's common source directory.Projects that enabled
deterministicKeyswithout apackage.jsonwill now see reports. This differs from the upstream@effect/language-service, which skips these files.{ "name": "@effect/language-service", "keyPatterns": [{ "target": "service", "pattern": "default" }] }// src/services/AuthService.ts, no package.json, tsconfig.json at the project root // reports: the expected key is `services/AuthService/MyService` export class MyService extends Context.Service<MyService, {}>()("MyService") {}d8c489b: Add
errorPayloadShadowsNameto detect inlinenamepayload fields on Effect error classes. For example,Data.TaggedError("ToolNotFound")<{ name: string }>copies the payload'snameonto the error instance and hides the error type in logs. Rename the field totoolName. The rule inspects inline payloads only and allows a field whose value is the literal the error already uses as its name.13a46c9: Add an
"identifier"pattern tokeyPatternsfor thedeterministicKeysrule. With it, the expected key is the class name alone.{ "name": "@effect/language-service", "keyPatterns": [{ "target": "error", "pattern": "identifier" }] }// reports: the expected key is `KeybindingsConfigError` export class KeybindingsConfigError extends Data.TaggedError("KeybindingsConfigParseError")<{}> {}
Minor Changes
13a46c9: The
deterministicKeysrule and the key completions now compute a key for files without apackage.json, or whose nearestpackage.jsonhas noname. The key is built as usual, but without the package name. The sub-directory segment is relative to thepackage.jsondirectory if one is found, otherwise to thetsconfig.jsondirectory, otherwise to the program's common source directory.Projects that enabled
deterministicKeyswithout apackage.jsonwill now see reports. This differs from the upstream@effect/language-service, which skips these files.{ "name": "@effect/language-service", "keyPatterns": [{ "target": "service", "pattern": "default" }] }// src/services/AuthService.ts, no package.json, tsconfig.json at the project root // reports: the expected key is `services/AuthService/MyService` export class MyService extends Context.Service<MyService, {}>()("MyService") {}d8c489b: Add
errorPayloadShadowsNameto detect inlinenamepayload fields on Effect error classes. For example,Data.TaggedError("ToolNotFound")<{ name: string }>copies the payload'snameonto the error instance and hides the error type in logs. Rename the field totoolName. The rule inspects inline payloads only and allows a field whose value is the literal the error already uses as its name.13a46c9: Add an
"identifier"pattern tokeyPatternsfor thedeterministicKeysrule. With it, the expected key is the class name alone.{ "name": "@effect/language-service", "keyPatterns": [{ "target": "error", "pattern": "identifier" }] }// reports: the expected key is `KeybindingsConfigError` export class KeybindingsConfigError extends Data.TaggedError("KeybindingsConfigParseError")<{}> {}b1ed4ba: Add
preferNamespaceImportandpreferBarrelImport, two diagnostics that report existing imports that contradict the import style configured withnamespaceImportPackagesandbarrelImportPackages. Auto-import already follows these options; the new rules also cover imports written by hand. Both are off by default and have no quick fix.preferNamespaceImportreports named imports from packages innamespaceImportPackages:// "namespaceImportPackages": ["effect"] import { Effect } from "effect" // expected: import * as Effect from "effect/Effect" import { map } from "effect/Array" // expected: import * as Array from "effect/Array" import { pipe } from "effect" // reported only with "topLevelNamedReexports": "follow"preferBarrelImportreports imports of individual modules from packages inbarrelImportPackages:// "barrelImportPackages": ["effect"] import * as Record from "effect/Record" // expected: import { Record } from "effect" import * as HttpClient from "effect/http/HttpClient" // expected: import { HttpClient } from "effect/http"Both the rules and auto-import find a barrel from the package files, for any package, instead of from a built-in list of Effect paths. A module's barrel is the nearest
indexmodule above it that forwards it withexport * as Name, andNameis the import name used. Barrel files are read from disk when no file in the program imports them yet. Auto-import withbarrelImportPackagesuses the same lookup, so it no longer rewrites a module that no barrel forwards, and no longer rewrites an import that already comes from a barrel (such aspipefrom"effect") intoimport { effect } from "effect".b1ed4ba: Allow
namespaceImportPackages,barrelImportPackages,importAliases, andtopLevelNamedReexportsin per-fileoverrides. Auto-import, the import quick fixes, and thepreferNamespaceImportandpreferBarrelImportdiagnostics use the value resolved for the current file, and a scoped value replaces the base value.{ "namespaceImportPackages": ["effect"], "overrides": [{ "include": ["src/legacy/**/*.ts"], "options": { "namespaceImportPackages": [], "barrelImportPackages": ["effect"] } }] }
Patch Changes
61eb79c: Compute Effect diagnostics with less work. Rules and the type parser now test node kinds, shapes and argument counts before they query types, symbols or signatures, and they compute types only for steps that can still report:
IsNodeReferenceToModuleExportanswers symbols with no declaration in the requested module from a per-symbol bitmask instead of a per-symbol map.DataFirstOrLastCallchecks the cached signature shape before it types call arguments, and caches its result per call.missedPipeableOpportunity,catchDieToOrDieandpreferTypedSchemaDecodertype piping-flow steps only when a step matches.The
experimentalApiUsageandunstableApiUsagerules reuse their own symbol lookup instead of repeating it.
With every rule enabled,
tsc -bof the Effect monorepo drops from 33.9s to 32.1s (stock TypeScript-Go: 20.4s). The reported diagnostics are unchanged.cb5739d: Update the TypeScript next tag to
typescript@next, which shipstypescript-gocommitb5c34ba0c61a756c8abaf133236dddf982c27f45, and update the TypeScript latest tag totypescript@latest. Refresh the Oxlint configuration schema from the selected package.
- 0.52.x
0.52.0
13 Oct 2026- removed
7450a52: Remove the
debugplugin option and the debug-onlyFlowsgroup from the document outline. 3e4a55d: Route Effect contextual-type queries through
TypeParser.GetContextualTypeand enforce the wrapper with customlint. For example, usetp.GetContextualType(node, checker.ContextFlagsNone)instead of the checker method. Query behavior stays unchanged, with one place to add contextual-type safety guards in future changes.0269634: Add
effectSleepZeroToYieldNow, a style suggestion with a quick fix for zero-durationEffect.sleepcalls.For example,
Effect.sleep(0)becomesEffect.yieldNow()in Effect v3 andEffect.yieldNowin Effect v4. The rule also recognizes safe zero-duration strings, tuples, and Duration constructors. The replacement yields through the fiber scheduler instead of the Clock service.
Minor Changes
3e4a55d: Route Effect contextual-type queries through
TypeParser.GetContextualTypeand enforce the wrapper with customlint. For example, usetp.GetContextualType(node, checker.ContextFlagsNone)instead of the checker method. Query behavior stays unchanged, with one place to add contextual-type safety guards in future changes.0269634: Add
effectSleepZeroToYieldNow, a style suggestion with a quick fix for zero-durationEffect.sleepcalls.For example,
Effect.sleep(0)becomesEffect.yieldNow()in Effect v3 andEffect.yieldNowin Effect v4. The rule also recognizes safe zero-duration strings, tuples, and Duration constructors. The replacement yields through the fiber scheduler instead of the Clock service.181b2b3: Add the
flatMapToTapstyle suggestion and quick fix for Effect v3 and v4. Callbacks that run an effect and restore their unchanged parameter with terminalEffect.asorEffect.mapcan useEffect.tapinstead. The fix preserves callback statements and earlier effect transformations.7d051dd: Route internal symbol and type location queries through TypeParser and enforce this with customlint. Reuse the existing TypeParser throughout pipeable signature comparison.
Prevent false TS2790 diagnostics for valid index-signature deletes such as
declare const map: { [key: string]: number }; delete map.x;. Symbol queries skip deleted property accesses and their names, including parenthesized and optional targets. Receiver and computed-key queries remain available, and invalid required-property and readonly deletes still report compiler errors.f178ff2: Add the opt-in
preferEffectArraydiagnostic ineffectNativefor native Array method calls and references. It suggests 16 corresponding Effect Array APIs and explains migration differences, such asvalues.find(predicate)becomingArray.findFirst(values, predicate)with anOptionresult.The rule is disabled by default and enabled as a warning by the
effect-nativepreset. It supports readonly arrays, tuples, aliases, and literal bracket access. Native Array recognition uses a lazy cache shared per checker. Conversion autofixes are not included.f59b4b8: Add the opt-in
preferEffectRecorddiagnostic ineffectNativefor native Object calls and references. It suggestsRecord.keys,Record.values,Record.toEntries,Record.fromEntries, andRecord.has, including nativehasOwnPropertyreferences.Each suggestion explains input typing or runtime differences. For example,
Object.entries(data)suggestsRecord.toEntries(data)with typed keys and a caveat about getter or proxy mutations.data.hasOwnProperty(key)suggests passing the receiver explicitly toRecord.has(data, key).The rule defaults to off and the
effect-nativepreset enables it as a warning. Both Effect v3 and v4 are supported. Only suppression quick fixes are available.2672190: Add the opt-in
preferSchemaTaggedErrordiagnostic for Effect v3 and v4. It suggestsSchema.TaggedErrorfor class declarations that extendData.TaggedError, including anonymous default exports. For example,class NotFound extends Data.TaggedError("NotFound")<{ id: string }> {}reports a warning when the rule is enabled.ab20f55: Expose parser results through getters and readonly collection views. For Go consumers,
result.Abecomesresult.A(), andflow.Transformations[i]becomesflow.Transformations().At(i). Collection views support iteration and explicit owned copies. Compiler AST and type pointers remain borrowed.c4aa628: Include
{ readonly brand: unique symbol }in Effect v4 Schema class completions forClass,TaggedClass,Error, andTaggedError. Add a branded completion forSchema.Opaque.For example, the
Class<Person>completion insertsSchema.Class<Person, { readonly brand: unique symbol }>("Person"). Effect v3 andModel.Classcompletions keep their existing type arguments.22f6106: Add
schemaClassMissingBrand, a correctness suggestion enabled by default for Effect v4 schema classes, errors, and opaque classes.The diagnostic suggests adding a brand when the second brand type argument is omitted. For example,
Schema.Class<Person>("Person")triggers a suggestion, whileSchema.Class<Person, { readonly brand: unique symbol }>("Person")supplies a nominal brand. An explicit{}keeps structural typing and suppresses the suggestion. Effect v3 is excluded.d565ab8: Recognize
Predicate.isTagged(value, "Foo")andPredicate.isTagged("Foo")(value)as tag comparisons in dispatch analysis. Existing catch-tag diagnostics and quick fixes now handle both forms in Effect v3 and v4.
Patch Changes
4ceb27f: Reduce repeated type inference when checking experimental and unstable properties in generic object literals.
e57688f: Clear an inherited Effect plugin when a child
tsconfigdefines an empty or replacementpluginslist.9696634: Report experimental and unstable properties supplied in contextually typed object literals, including shorthand properties. For example,
x({ test: 42 })andx({ test })now warn when the parameter type markstestwith@stability experimental, even if the function and interface are stable.0dfc0be: Fix a crash in the "Convert to Effect.fn" refactor when
genis a named import or a local alias.import { gen } from "effect/Effect" export const foo = () => gen(function*() { return 1 })Requesting code actions on
genused to fail the wholetextDocument/codeActionrequest with a nil pointer panic. The refactor now rewrites toEffect.fn, using the file's existing Effect import name when there is one:import { gen } from "effect/Effect" export const foo = Effect.fn("foo")(function* () { return 1; });The refactor does not add a missing
Effectimport. The user adds it.6107975: Update the shim generator's Go tools dependency to support Go 1.27.2 export data and restore compiler setup.
Preserve pointers to unexported structs in generated shim mirrors so fields that follow them retain their offsets and accessors return the correct values.
8e0b5bf: Resolve the types carried by typeparser results only when a rule reads them, and reuse the resolved type on later reads. For example, a piping flow no longer queries the type of every transformation up front, so a rule that filters flows by callee skips those queries. Diagnostics are unchanged.
6512cfb: Cache module export checks per symbol. Rules check whether most identifiers and callees refer to a module export, such as
gen,fn, ormapfrom theeffectpackage'sEffectmodule. Each symbol now gets a slot in a paged array indexed by symbol id, the layout the TypeScript 7.1 checker uses for its own symbol caches. The slot holds a small map of answers keyed by module and member name. Before, every answer shared one large hash map. For example,tsc -bon the Effect monorepo with every rule enabled runs about 1% faster with identical diagnostics. On TypeScript 7.0.2, which lacks block-allocated symbol ids, the per-symbol slots stay in a hash map.b780f66: Fix the Effect.fn and async-to-Effect refactors for functions nested inside another declaration's value. A function in a catch binding default no longer makes the code action request fail, and a function in an object, array, call argument, class field, or later declarator is now replaced in place instead of overwriting the whole value. For example, converting
taskinexport const inObject = { task: () => Effect.gen(function*() { return 1 }) }now producesexport const inObject = { task: Effect.fn(function* () { return 1; }) }.959570b: Store the Effect caches that cover most nodes of a file in paged arrays indexed by node id, the layout the TypeScript 7.1 checker uses for its own hottest node caches. A lookup now indexes an array instead of hashing a node pointer. For example,
tsc -bon the Effect monorepo runs about 2% faster with identical diagnostics. On TypeScript 7.0.2, which lacks block-allocated node ids, these caches stay hash maps.60eac10: Run Effect diagnostics after TypeScript checks unused identifiers so plugin symbol queries cannot suppress TS6133. For example, with
noUnusedParametersenabled,export function unusedPredicate(value: unknown): value is number { return true; }now reports the unusedvalueparameter with the plugin enabled, just as it does with the plugin disabled.- removed
7450a52: Remove the
debugplugin option and the debug-onlyFlowsgroup from the document outline. 3e4a55d: Cache object-literal contextual types per checker across experimental and unstable API diagnostics. Keep normal and inference-blocked queries separate, including nil results, to avoid repeating the same contextual-type queries.
4d9fba4: Ship the latest TypeScript compiler once in each platform package. It was packaged twice, as
lib/tscand asartifacts/typescript/<latest>/tsc, each with its ownlib.*.d.tsfiles. It now ships only aslib/tsc, which makes@effect/tsgo-darwin-arm6429 MB smaller unpacked.get-exe-path,diagnostics,patchandgetExePath()resolve the latest TypeScript version tolib/tscand other versions toartifacts/typescript/<version>/tsc. Tools that runlib/tscdirectly keep working.3e4a55d: Prevent false TypeScript iterator and object-spread diagnostics when experimental or unstable API checks query generic constraints inside inferred generator function expressions. Skip inference-blocked contextual queries in these expressions while retaining normal contextual lookups. This conservative fallback can omit constraint-based property warnings inside inferred generators.
da2f46d: Skip type queries for expressions that can never have an Effect library type, such as literals, functions and, on Effect v4, plain object literals. Diagnostics are unchanged, but they are cheaper to compute: on the Effect monorepo a
tsc -bbuild is about 1.3s faster with the default rules and about 2.4s faster with every rule exceptapiStabilityLeakenabled.For example, rules such as
effectInVoidSuccessno longer ask the checker for the type of the array and object literal arguments here, because neither can be an Effect:Effect.forEach([1, 2, 3], (n) => Effect.log(n), { concurrency: 2 })1c7cbf9: Update Effect v4 dependencies and test fixtures from
4.0.0-rc.118to stable4.0.2. Align@effect/platform-node,@effect/platform-node-shared, and@effect/vitestwith the same release.fea53cc: Use the configured
keyPatternsforData.TaggedErrorandSchema.TaggedErrorcompletions, so the inserted tag already matches the key expected bydeterministicKeys.For example, with
{ "target": "error", "pattern": "package-identifier" }inkeyPatterns, completingclass NotFound extends Data.insrc/errors.tsof package@app/corenow insertsData.TaggedError("@app/core/errors/NotFound")<{}>{}instead ofData.TaggedError("NotFound")<{}>{}. Without anerrorkey pattern the completion still uses the class name.cb7567e: Support both field-based and method-based compiler symbols through generated shim helpers.
7450a52: Update the TypeScript next tag to
typescript@next, which shipstypescript-gocommitd61a7d235906e78be9b111de0ba060e28e67ecfa, and update the TypeScript latest tag totypescript@latest.
- 0.51.x
0.51.1
7 Oct 2026a5bd7f1: Update the TypeScript next tag to
typescript@next, which shipstypescript-gocommita1ef42b9ea7032fa60df127d42b4c86fd2a110ee, and update the TypeScript latest tag totypescript@latest.
0.51.0
7 Oct 20269ca6ea2: Add related declaration locations to
apiStabilityLeakdiagnostics. For example, when a stable export exposes an experimental type, the diagnostic on the export now includes a child pointing to the experimental type's declaration, including declarations in other files.caee22f: Fix
apiStabilityLeakto ignore inherited bases whose public members are all optional and explicitly stability-tagged, including bases reached through augmentations and superclass factories. Direct properties and parameters typed as those bases remain checked. Exclude@internalproperties and methods from the public surface throughout the leak check.
- 0.50.x
0.50.0
6 Oct 202669c8ce5: Add the opt-in
apiStabilityLeakdiagnostic for Effect v4 package maintainers.
It reports exports whose public types, parameters, or return values expose a
less stable API: stable exports must not expose unstable or experimental types,
and unstable exports must not expose experimental types. Untagged exports are
treated as stable; experimental exports impose no restriction.For example,
export interface StableApi { value: ExperimentalType }reports
a leak whenExperimentalTypehas an@stability experimentaltag. Public
members, generic arguments, inferred types, and re-exports are checked without
recursively instantiating types.The rule is off by default and excluded from the recommended, strict, and
correctness presets. Enable the newmaintainerspreset to report it as a
warning, or configureapiStabilityLeakdirectly. Declared stability lookups are
shared with the existing unstable and experimental API usage diagnostics.
- 0.49.x
0.49.0
6 Oct 202675e6ca5: Migrate compiler integrations to the current TypeScript path and configuration APIs, and refresh the TypeScript patch stack for the new upstream snapshot. Keep TypeScript 7.0.2 supported through adapters for the legacy typescript-go provider.
For example, plugin option and diagnostic severity resolution now accept rooted source and config file paths directly, while the legacy shims adapt those calls to TypeScript 7.0.2. Preserve Effect options through upstream option cloning and comparison, and fix include patterns for files in filesystem roots.
Keep the Nix compiler source pin, lock file, and vendor hash synchronized with the updated snapshot, and apply Git binary compiler patches during Nix builds. Preserve the original TypeScript 7.0.2 provider shim APIs for tsgolint, with modern API adapters confined to the canonical shim facade.
- 0.48.x
0.48.1
5 Oct 2026c964cca: Fix
unstableApiUsageandexperimentalApiUsagenaming overloaded (dual) exports by module, which preventedallowedUnstableApis/allowedExperimentalApisfrom allowing them per export.A dual export whose call signatures carry their own
@stabilitytag — for exampleeffect/http/HttpClientRequest#bodyText— was reported under the bare module name (effect/http/HttpClientRequest) because the selected call signature is not the module export. An allow-list entry foreffect/http/HttpClientRequest#bodyTexttherefore never matched, and the only way to allow the use was a whole-module entry.The reported name now resolves to the export that owns the selected overload signature, matching the README's
package/module#exportNameform:import { HttpClientRequest } from "effect/http" export const request = HttpClientRequest.post("http://x").pipe( HttpClientRequest.setHeader("a", "b"), HttpClientRequest.bodyText("{}", "application/json") )With:
"allowedUnstableApis": [ "effect/http/HttpClientRequest#post", "effect/http/HttpClientRequest#setHeader", "effect/http/HttpClientRequest#bodyText" ]
all three uses are allowed, and any unlisted dual export still warns under
package/module#exportName.
0.48.0
2 Oct 2026a954eb5: Add
allowedUnstableApisandallowedExperimentalApisto selectively allow unstable or experimental declaration modules or exported APIs. For example,effect/http/HttpClientallows the entire module, whileeffect/http/HttpClient#getallows only its exportedgetAPI. Both options support per-file overrides, and both diagnostics display the declaration-based name.0900778: Build packaged TypeScript compilers without embedded standard libraries so editor go-to-definition opens real library files. Ship matching
lib.*.d.tsfiles beside each versioned compiler and the latestlib/tscalias, keepingdiagnosticsandget-exe-pathworking when running the packaged executable directly.
- 0.47.x
0.47.2
30 Sep 2026536f83a: Fix a panic in
unstableApiUsageandexperimentalApiUsageon thedefaultof a dynamically importedexport =or JSON module.bddb623: Update the TypeScript next tag to
typescript@next, which shipstypescript-gocommit0681ef7fa3a2378ccf49645b6d5b7463bdca74bb, and update the TypeScript latest tag totypescript@latest.
0.47.0
29 Sep 2026b67ef81: Update the Effect v4 integration to
4.0.0-rc.118and use its public module paths. Namespace auto-imports for nested modules now resolve to paths such aseffect/cli/Prompt.66668e2: Add the
experimentalApiUsageandunstableApiUsagediagnostics for APIs marked with@stability experimentalor@stability unstable. Both rules warn by default. For example, a reference to an unstable API now reports that breaking changes may happen between versions.8067475: Fix
getExePathrejecting the schema version shipped by platform packages.Discover installed Oxlint musl bindings without rejecting them before component selection, so TypeScript-only commands work when Oxlint is installed on Alpine Linux. Report unsupported Oxlint replacements during patch preparation instead, allowing
--skip-missingand restoring original binaries withunpatch.
Minor Changes
b67ef81: Update the Effect v4 integration to
4.0.0-rc.118and use its public module paths. Namespace auto-imports for nested modules now resolve to paths such aseffect/cli/Prompt.66668e2: Add the
experimentalApiUsageandunstableApiUsagediagnostics for APIs marked with@stability experimentalor@stability unstable. Both rules warn by default. For example, a reference to an unstable API now reports that breaking changes may happen between versions.
Patch Changes
8067475: Fix
getExePathrejecting the schema version shipped by platform packages.Discover installed Oxlint musl bindings without rejecting them before component selection, so TypeScript-only commands work when Oxlint is installed on Alpine Linux. Report unsupported Oxlint replacements during patch preparation instead, allowing
--skip-missingand restoring original binaries withunpatch.2e215ce: Update the TypeScript next tag to
typescript@next, which shipstypescript-gocommit4f5ddae224b9529a69b571f631fe3a2cb283162f, and update the TypeScript latest tag totypescript@latest. Refresh the Oxlint configuration schema from the selected package.
- 0.46.x
0.46.1
26 Sep 202609644ee:
effect-tsgo diagnosticsnow reports files it skipped because their tsconfig does not enable the@effect/language-serviceplugin, instead of only printingChecked 0 files out of N files.The JSON summary gains a matchingfilesWithoutPlugincount.Checked 0 files out of 8 files. Skipped 8 files because their tsconfig does not enable the @effect/language-service plugin. 0 errors, 0 warnings and 0 messages.
dfa24e8: Fix
effectFnOpportunityconversions to preserve enclosing expressions, sibling declarations, comments, literal spelling, and source formatting. Avoid suggesting conversions for function declarations referenced before their declaration.Wrap non-call pipe arguments in unary callbacks so they do not receive the converted function's arguments. For example,
.pipe(Effect.ignore)becomes anEffect.fnpipeable_ => Effect.ignore(_), while factory calls such asEffect.map(f)are retained.8d89b43: Deduplicate strictBooleanExpressions diagnostics when multiple union members display the same type name.
Patch Changes
09644ee:
effect-tsgo diagnosticsnow reports files it skipped because their tsconfig does not enable the@effect/language-serviceplugin, instead of only printingChecked 0 files out of N files.The JSON summary gains a matchingfilesWithoutPlugincount.Checked 0 files out of 8 files. Skipped 8 files because their tsconfig does not enable the @effect/language-service plugin. 0 errors, 0 warnings and 0 messages.
dfa24e8: Fix
effectFnOpportunityconversions to preserve enclosing expressions, sibling declarations, comments, literal spelling, and source formatting. Avoid suggesting conversions for function declarations referenced before their declaration.Wrap non-call pipe arguments in unary callbacks so they do not receive the converted function's arguments. For example,
.pipe(Effect.ignore)becomes anEffect.fnpipeable_ => Effect.ignore(_), while factory calls such asEffect.map(f)are retained.8d89b43: Deduplicate strictBooleanExpressions diagnostics when multiple union members display the same type name.
7611be0: Preserve Effect plugin options in the Oxlint integration when
tsconfig.jsonusesextends, whether the options are inherited or declared locally. For example,effectFn: ["span", "inferred-span", "suggested-span"]now enables the sameeffect-fn-opportunityreports as an inline configuration withoutextends.
0.46.0
25 Sep 20266db6fa6: Add the
catchIfTagToCatchTagdiagnostic and quick fix for replacing direct_tagequality predicates inEffect.catchIfwithEffect.catchTag.ae1ed02: Add the v4-only
catchRefailToTapErrordiagnostic. It suggestsEffect.tapErrorwhen anEffect.catchhandler sequences an effect withEffect.andThenor a zero-argumentEffect.flatMapcallback and then fails with the original, unmodified error. Generator handlers and selective catches are excluded.437b17e: Retain the latest three stable Oxlint releases and the Oxlint runtimes required by the latest three stable Vite+ releases, including their compiler dependencies. Add versioned compatibility profiles so CI tests every distinct retained runtime pair.
The refreshed upstream metadata supports Oxlint 1.77.0, 1.79.0, 1.80.0, 1.81.0, and 1.82.0, covering Vite+ 0.2.9, 0.3.0, and 0.3.1, and advances TypeScript next to 7.1.0-dev.20260911.1.
Minor Changes
6db6fa6: Add the
catchIfTagToCatchTagdiagnostic and quick fix for replacing direct_tagequality predicates inEffect.catchIfwithEffect.catchTag.ae1ed02: Add the v4-only
catchRefailToTapErrordiagnostic. It suggestsEffect.tapErrorwhen anEffect.catchhandler sequences an effect withEffect.andThenor a zero-argumentEffect.flatMapcallback and then fails with the original, unmodified error. Generator handlers and selective catches are excluded.437b17e: Retain the latest three stable Oxlint releases and the Oxlint runtimes required by the latest three stable Vite+ releases, including their compiler dependencies. Add versioned compatibility profiles so CI tests every distinct retained runtime pair.
The refreshed upstream metadata supports Oxlint 1.77.0, 1.79.0, 1.80.0, 1.81.0, and 1.82.0, covering Vite+ 0.2.9, 0.3.0, and 0.3.1, and advances TypeScript next to 7.1.0-dev.20260911.1.
223f9fa: Add the
flatMapIgnoredParamToAndThendiagnostic and quick fix for replacing zero-parameterEffect.flatMapcallbacks that return an existing constant Effect value withEffect.andThen. Existing diagnostics now also recognize Effect APIs referenced through constant aliases, and their quick fixes rebuild the replacement API from the source file's imported module name without modifying the shared alias.7173762: Add a
strictdiagnostic preset that promotes every default-enabled diagnostic to an error. Expose the complete preset catalog consistently through TypeScript setup and the generated Oxlint presets.9652243: Warn when
diagnosticSeveritycontains an unknown Effect rule name, including in overrides and inherited configurations. For example,"floatingEfect": "error"now reportseffect(unknownRuleName)instead of being silently ignored.The check uses the fully merged configuration. Set
"unknownRuleName": "off"to disable it or"unknownRuleName": "error"to raise its severity. Local keys are underlined in tsconfig; inherited keys without local syntax produce a diagnostic without a source location.
Patch Changes
f110e11: Restore compatibility with TypeScript 7.1.0-dev.20260924.1 by updating diagnostic generation and plugin parsing patches, adapting single-file diagnostic requests to the upstream snapshot API, and regenerating compiler shims and Nix inputs.
7c0ddbc: Update the TypeScript next tag to
typescript@next, which shipsTypeScriptcommitf29aeb9f825d96feea27841f3f7342dbf0df68a8, and update the repository toolchain to Go 1.27.
- 0.45.x
0.45.0
10 Sep 2026066c4b0: Add the opt-in
schemaSyncdiagnostic to prefer Effect-based Schema decoding and encoding overdecodeSync,decodeUnknownSync,encodeSync, andencodeUnknownSyncin any context. It recommends the corresponding Effect v3 or v4 method and is enabled by theeffect-nativepreset.bc87c9f: Update the TypeScript next tag to
typescript@next, which shipstypescript-gocommitf3b04fe05642d53b4ff126a4af05fe2587b43748, and update the TypeScript latest tag totypescript@latest.
- 0.44.x
0.44.0
9 Sep 2026a64e17d: Add
obsoleteMatchImportdiagnostic (TS377127) to warn when importing@effect/matchin projects targeting Effect v4. In Effect v4, pattern matching is built directly intoeffect(import { Match } from "effect"orimport * as Match from "effect/Match").63331b6: Add
obsoleteSchemaImportdiagnostic (TS377128) to warn when importing@effect/schemaor@effect/schema/*in projects targeting Effect v4. In Effect v4, Schema is built directly intoeffect(import { Schema } from "effect"orimport * as Schema from "effect/Schema").29733f1: Add the
timeoutCatchTagToTimeoutOrElsediagnostic and quick fixes for Effect v4. SuggestEffect.timeoutOrElseforEffect.timeoutfollowed byEffect.catchTag("TimeoutError", ...), andEffect.timeoutOptionfor the corresponding Some/None pattern. Only suggest a rewrite when the input error channel excludesTimeoutErrorand the handler does not use the caught error.
Minor Changes
a64e17d: Add
obsoleteMatchImportdiagnostic (TS377127) to warn when importing@effect/matchin projects targeting Effect v4. In Effect v4, pattern matching is built directly intoeffect(import { Match } from "effect"orimport * as Match from "effect/Match").63331b6: Add
obsoleteSchemaImportdiagnostic (TS377128) to warn when importing@effect/schemaor@effect/schema/*in projects targeting Effect v4. In Effect v4, Schema is built directly intoeffect(import { Schema } from "effect"orimport * as Schema from "effect/Schema").29733f1: Add the
timeoutCatchTagToTimeoutOrElsediagnostic and quick fixes for Effect v4. SuggestEffect.timeoutOrElseforEffect.timeoutfollowed byEffect.catchTag("TimeoutError", ...), andEffect.timeoutOptionfor the corresponding Some/None pattern. Only suggest a rewrite when the input error channel excludesTimeoutErrorand the handler does not use the caught error.
Patch Changes
a05d76b: Reuse the normalized piping-flow shape and sequence matchers across existing diagnostics.
d990b0a: Fix
cryptoRandomUUIDandcryptoRandomUUIDInEffectdiagnostic messages and rule descriptions in Effect v4 to recommend the EffectCryptomodule instead ofRandom. In Effect v4,Randomdoes not providerandomUUIDand uses non-cryptographicMath.random, whereas cryptographic UUID generation is provided byCrypto.Crypto(such asyield* crypto.randomUUIDv4).7993db9: Update the TypeScript next tag to
typescript@next, which shipstypescript-gocommit1f70213d4922b434345f639b441681e470c7cfc1, and update the TypeScript latest tag totypescript@latest.
- 0.43.x
0.43.0
8 Sep 2026956b8d6: Extend
nodeBuiltinImportto recommend Effect-native alternatives forconsole,timers,timers/promises,stream,stream/promises, andstream/web, including theirnode:forms.For Effect v4, also flag
cryptoandnode:cryptoimports and recommendCryptofromeffect. For example,import { randomUUID } from "node:crypto"is now diagnosed; use theCryptoservice'srandomUUIDv4effect instead. Effect v3 crypto imports remain allowed because that version has no corresponding Crypto service.Correct the Effect v4
child_processrecommendation to point toeffect/unstable/process. The rule remains disabled by default; configurenodeBuiltinImportwith error severity to prohibit covered imports.
- 0.42.x
0.42.0
8 Sep 20267565750: Add the
matchEffectToMapBothstyle diagnostic and quick fix for replacingEffect.matchEffecthandlers that returnEffect.failandEffect.succeedwithEffect.mapBoth.a09feae: Add the
catchAllTagDispatchToCatchTagstyle diagnostic and quick fix for replacing manual tagged-error dispatch withEffect.catchTagorEffect.catchTags.2d501a2: Add the
provideLayerSucceedToProvideServicediagnostic and quick fix for replacing inlineLayer.succeedandLayer.effectprovision with direct service provision.
Minor Changes
7565750: Add the
matchEffectToMapBothstyle diagnostic and quick fix for replacingEffect.matchEffecthandlers that returnEffect.failandEffect.succeedwithEffect.mapBoth.a09feae: Add the
catchAllTagDispatchToCatchTagstyle diagnostic and quick fix for replacing manual tagged-error dispatch withEffect.catchTagorEffect.catchTags.2d501a2: Add the
provideLayerSucceedToProvideServicediagnostic and quick fix for replacing inlineLayer.succeedandLayer.effectprovision with direct service provision.46c6e68: Add the
matchEffectToMatchstyle diagnostic and quick fix for replacingEffect.matchEffectorEffect.matchCauseEffectwhose handlers only returnEffect.succeedwith their non-effectful counterparts.Make lazy-expression parsing synchronous and non-generator by default, with flags for callers that explicitly accept thunks, async functions, or generators.
59c5fff: Adopt the piping flow parser in more diagnostics.
promiseInEffectSuccess: an explicit promise-success annotation (type arguments onEffect.succeed/as/map/zipWith) now suppresses the diagnostic from any position in the surrounding pipe, not only the last argument.base.pipe(Effect.as<Promise<number>>(promiseValue), Effect.as(promiseValue))no longer reports, matching the reversed order that was already accepted.allOfMapToForEach: now also detects the data-last form expressed through piping flows, e.g.pipe(values.map(effectful), Effect.all)andpipe(values.map(effectful), Effect.all, Effect.asVoid), which were previously invisible to the call-expression walk. These matches are diagnostic-only: the existing quick fix remains limited to the standaloneEffect.all(xs.map(f), options?)call it can safely rewrite.The piping flow parser now keeps the type arguments of parenthesized pipe arguments, e.g.
pipe(x, (Effect.as<...>(v))).The piping flow parser now normalizes curried pipeable applications, so
Effect.catch(handler)(effect)haseffectas its subject,Effect.catchas its callee, andhandleras its transformation argument. The normalization is limited to calls whose signatures verify that they are the pipeable counterpart of a data-first overload of the same combinator, leaving unrelated curried APIs such asEffect.fn("name")(body)unchanged.
db28a74: Add the
runOfExitToRunExitdiagnostic, which replacesEffect.runPromiseapplied toEffect.exitwith the dedicatedEffect.runPromiseExitrunner.
Patch Changes
348021d: Update TypeScript next to 7.1.0-dev.20260906.1 and adapt diagnostics snapshot cleanup to its new API while preserving compatibility with stable TypeScript.
928506b: Update the TypeScript next tag to
typescript@next, which shipstypescript-gocommit1f70213d4922b434345f639b441681e470c7cfc1, and update the TypeScript latest tag totypescript@latest. Refresh the Oxlint configuration schema from the selected package.
- 0.41.x
0.41.0
4 Sep 2026- removed
d3efa70: Remove the AST location parameter from type-only
TypeParseroperations. Effect, Layer, Stream, Schema, service, Context.Tag, Scope, and related type predicates now derive instantiated property types directly from the supplied checker type. d095234: Normalize piping-flow transformations around their callee, arguments, and explicit type arguments without exposing a representation-dependent transformation node. Add shared rewriter operations for replacing transformations and flow prefixes while preserving data-first, data-last,
pipe(...), and.pipe(...)source forms.1d0dfb8: Update the TypeScript next tag to
typescript@next, which shipstypescript-gocommitcf7b9361a33fa0c8e1afa3cf45fde29c9ab23ec0, and update the TypeScript latest tag totypescript@latest.
- 0.40.x
0.40.0
3 Sep 2026815273c: Add the Effect v4
raceFirstWithSleepToTimeoutstyle diagnostic, which suggestsEffect.timeoutOrElsewhen a first-completion race has exactly oneEffect.sleep- orEffect.delay-based timer arm.Reclassify
acquireReleaseDisposableas style andunsafeEffectTypeAssertionas correctness.c1ac8e5: Avoid reporting the
schemaNumberdiagnostic whenSchema.Numberis refined with the built-inisFiniteorisIntchecks, including pipe-style refinements.0fba9d1: Update the TypeScript next tag to
typescript@next, which shipstypescript-gocommit43a90f4c105bc9db7cb7aa299beddafbabe1d23e, and update the TypeScript latest tag totypescript@latest.
- 0.39.x
0.39.1
2 Sep 2026c2e4353: Update the TypeScript next tag to
7.1.0-dev.20260901.1, update Oxlint to1.81.0, and refresh the generated configuration schemas. Support SchemaStore's draft-07 nullable schema representation when injecting the Effect language-service plugin schema.
0.39.0
1 Sep 20267e30dc9: Add the
acquireReleaseDisposablerule to replace manual disposal finalizers passed toEffect.acquireReleasewithEffect.acquireDisposable.f134c31: Add the
optionMatchToFromOptiondiagnostic and quick fix for Option-to-Effect conversions that can useEffect.fromOption.The rule recognizes supported
Option.matchcall styles andOption.isSome/Option.isNoneconditional expressions whose branches only wrap the value withEffect.succeedor produceEffect.fail. It suggests the one-argumentEffect.fromOptionform for the defaultCause.NoSuchElementError, and preserves custom failures in a lazy callback.90c884e: Expose piping-flow extraction through the
etsgoapiGo API.The type parser already understands "piping flows" — a subject expression followed by an ordered list of transformations, unifying the
pipe(...), pipeable.pipe(...), data-first, data-last andEffect.fnforms — but that analysis was only reachable from internal packages.etsgoapi.TypeParsernow surfaces it so external Go integrations can consume it without importinginternal/....tp := etsgoapi.NewTypeParser(program, checker) for _, flow := range tp.PipingFlows(sourceFile, true /* includeEffectFn */) { // flow.Subject.Node / flow.Subject.OutType — the starting expression and its type for _, step := range flow.Transformations { // step.Kind (pipe | pipeable | dataFirst | dataLast | call | effectFn | effectFnUntraced) // step.Callee / step.Args / step.OutType } }Adds the public
PipingFlow,PipingFlowSubject,PipingFlowTransformationandTransformationKindtypes alongside the new(*TypeParser).PipingFlowsmethod.
Minor Changes
7e30dc9: Add the
acquireReleaseDisposablerule to replace manual disposal finalizers passed toEffect.acquireReleasewithEffect.acquireDisposable.f134c31: Add the
optionMatchToFromOptiondiagnostic and quick fix for Option-to-Effect conversions that can useEffect.fromOption.The rule recognizes supported
Option.matchcall styles andOption.isSome/Option.isNoneconditional expressions whose branches only wrap the value withEffect.succeedor produceEffect.fail. It suggests the one-argumentEffect.fromOptionform for the defaultCause.NoSuchElementError, and preserves custom failures in a lazy callback.90c884e: Expose piping-flow extraction through the
etsgoapiGo API.The type parser already understands "piping flows" — a subject expression followed by an ordered list of transformations, unifying the
pipe(...), pipeable.pipe(...), data-first, data-last andEffect.fnforms — but that analysis was only reachable from internal packages.etsgoapi.TypeParsernow surfaces it so external Go integrations can consume it without importinginternal/....tp := etsgoapi.NewTypeParser(program, checker) for _, flow := range tp.PipingFlows(sourceFile, true /* includeEffectFn */) { // flow.Subject.Node / flow.Subject.OutType — the starting expression and its type for _, step := range flow.Transformations { // step.Kind (pipe | pipeable | dataFirst | dataLast | call | effectFn | effectFnUntraced) // step.Callee / step.Args / step.OutType } }Adds the public
PipingFlow,PipingFlowSubject,PipingFlowTransformationandTransformationKindtypes alongside the new(*TypeParser).PipingFlowsmethod.804c2a9: Add the
flatMapConditionalToFilterOrFaildiagnostic and quick fix, which replaces identity-succeedEffect.flatMapconditionals withEffect.filterOrFailorEffect.filterOrElse.4e14641: Add the
preferSucceedSomeOrNonediagnostic and autofix for replacingEffect.succeed(Option.none())andEffect.succeed(Option.some(value)), including equivalent pipe forms, withEffect.succeedNoneandEffect.succeedSome(value).
Patch Changes
fcc641e: Keep the Nix TypeScript source pin synchronized with the TypeScript next metadata so Nix builds compile generated shims against the matching compiler revision.
36f2524: Update the TypeScript next tag to
typescript@next, which shipstypescript-gocommit9a8581c393a38961489cc8409ae4dfbe97fc25ec, and update the TypeScript latest tag totypescript@latest.
- 0.38.x
0.38.0
27 Aug 2026773b245: Add the
allOfMapToForEachstyle diagnostic, which suggests replacingEffect.all(values.map(callback), options)with the equivalentEffect.forEach(values, callback, options)form.fe7a29e: Add the
catchAllDieToOrDiestyle diagnostic, which suggests replacingEffect.catchorEffect.catchAllwithEffect.orDiewhen the catch-all
handler forwards its typed failure unchanged toEffect.die.32c575a: Add the
catchConditionalRefailToCatchIfdiagnostic for conditionalEffect.catchandEffect.catchCausehandlers that re-fail their untouched input, suggestingEffect.catchIf,Effect.catchCauseIf, orEffect.catchTagas appropriate.
Minor Changes
773b245: Add the
allOfMapToForEachstyle diagnostic, which suggests replacingEffect.all(values.map(callback), options)with the equivalentEffect.forEach(values, callback, options)form.fe7a29e: Add the
catchAllDieToOrDiestyle diagnostic, which suggests replacingEffect.catchorEffect.catchAllwithEffect.orDiewhen the catch-all
handler forwards its typed failure unchanged toEffect.die.32c575a: Add the
catchConditionalRefailToCatchIfdiagnostic for conditionalEffect.catchandEffect.catchCausehandlers that re-fail their untouched input, suggestingEffect.catchIf,Effect.catchCauseIf, orEffect.catchTagas appropriate.41ec458: Detect the data-first form of
effectMapVoidby driving detection off piping flows.effectMapVoidpreviously matched only the data-last / pipeable form of the pattern, so a data-firstEffect.map(self, () => {})was missed. Detection now runs over the piping-flow transformations, which normalize the subject away, so both forms are reported uniformly and the quick fix rewrites each one correctly.For example, the data-first call:
Effect.map(Effect.succeed(1), () => {})is now flagged and fixed to:
Effect.asVoid(Effect.succeed(1))
while the existing data-last form (
pipe(self, Effect.map(() => {}))) continues to be fixed to a bareEffect.asVoid.1ab4380: Improve dual function detection by matching alpha-equivalent data-first and pipeable overload declarations without instantiating their generic signatures.
For example, data-first calls such as
Option.match(value, handlers)now normalize to the same piping-flow representation asvalue.pipe(Option.match(handlers)), even when the overloads reorder generic parameters or return a generic union.2ae20c4: Refactor the
mapSomeToAsSomemapper detection onto the sharedUnwrapIdentityForwarderhelper. The diagnostic and quick fix now also recognize identity-forwarding function expressions:// now triggers, alongside Effect.map(Option.some) and Effect.map((v) => Option.some(v)) numberEffect.pipe( Effect.map(function (value) { return Option.some(value) }) )Annotated or optional mapper parameters and explicit type arguments on the inner
Option.somecall still do not trigger, since they can intentionally widen the resultingOptiontype.2a02aae: Add the
mapSomeToAsSomediagnostic and quick fix, which replacesEffect.map(Option.some)and its exact eta-expanded form withEffect.asSomein pipeable and data-first flows.
Patch Changes
68a603e: Bound CI Go caches with a resolved cache identity
repoctl upstream resolvenow emits a Go cache identity derived fromupstream.json: thetypescriptcomponent owns and saves its Go caches,oxlint-tsgolintrestores the compiler objects already cached by the typescript jobs under its TypeScript dependency version (Go's build cache is content-addressed, so the shared compiler packages hit directly), and the Rust-basedoxlintcomponent skips Go caching entirely instead of saving a duplicate GOCACHE snapshot.The go-build cache key no longer includes the commit SHA, so a multi-GB cache entry is written once per dependency state instead of on every push to main, and non-materialized setups are restore-only. Previously each push saved ~15GB of duplicate GOCACHE snapshots, evicting every other cache in the repository (GitHub caps repository caches at 10GB) and forcing all validation jobs to run cold.
The generated shim cache key now also hashes
_patches/typescript/**, so patch changes for the migrated TypeScript compiler repository invalidate cached shims correctly.e30bbdb: Fix
supportedEffectmetadata for two rules whose declaration disagreed with their actual behavior:genericEffectServicesdeclared["v3", "v4"]but is gated to run only on Effect v3 projects. It now declares["v3"], so v4 users no longer enable a rule that can never fire.schemaSyncInEffectdeclared["v3"]but fully supports Effect v4 (suggestingdecodeEffect/encodeEffectvariants). It now declares["v3", "v4"].
metadata.jsonand the generated rule docs were regenerated accordingly. No diagnostic behavior changed.24cbb0d: Fix
repoctl upstream updatefailing when a TypeScript commit is reachable from both supported provider repositories.Previously,
resolveTypeScriptProviderandreadRemoteTypeScriptGitlinkin_tools/repoctl/src/upstream.tserrored out withTypeScript commit <sha> matched 2 supported repositorieswhenever a single revision existed in bothmicrosoft/TypeScript(the canonical upstream) and the legacymicrosoft/typescript-gofork. This blocked the daily "Update Upstreams" workflow for revisions shared between the two.Both functions now prefer
microsoft/TypeScriptwhen it matches and fall back tomicrosoft/typescript-gootherwise. A "no supported repository matched" error is still raised when neither matches.7a07115: Update the TypeScript next tag to
typescript@next, which shipstypescript-gocommit5739027c9a7df24e27123f453a50c011b37717b6, and update the TypeScript latest tag totypescript@latest.
- 0.37.x
0.37.0
25 Aug 2026afb17ac: Support both the legacy
microsoft/typescript-gocompiler and the migratedmicrosoft/TypeScript/tsccompiler behind the canonical TypeScript shim
namespace.a3af171: Build the Nix package from the migrated TypeScript monorepo source and update the pinned compiler revision correctly.
eba879b: Suppress the
unnecessaryPipeChaindiagnostic when merging chained pipe calls would exceed the available overload arity.
Minor Changes
afb17ac: Support both the legacy
microsoft/typescript-gocompiler and the migratedmicrosoft/TypeScript/tsccompiler behind the canonical TypeScript shim
namespace.
Patch Changes
a3af171: Build the Nix package from the migrated TypeScript monorepo source and update the pinned compiler revision correctly.
eba879b: Suppress the
unnecessaryPipeChaindiagnostic when merging chained pipe calls would exceed the available overload arity.83b8e2a: Update the TypeScript next tag to
typescript@next, which shipstypescript-gocommite9e477458d7b975ed5e43117fb85f6bc87363a6a, and update the TypeScript latest tag totypescript@latest. Refresh the Oxlint configuration schema from the selected package.
- 0.36.x
0.36.5
15 Aug 20269ddab5d: Report unsupported target package versions with the current
@effect/tsgoversion and the supported alternatives.922903b: Document the target package versions supported by each published release.
ca311a5: Exclude type-only heritage nodes from execution flow graphs across supported TypeScript versions.
Patch Changes
9ddab5d: Report unsupported target package versions with the current
@effect/tsgoversion and the supported alternatives.922903b: Document the target package versions supported by each published release.
ca311a5: Exclude type-only heritage nodes from execution flow graphs across supported TypeScript versions.
7c54018: Update the TypeScript next tag to
typescript@next, which shipstypescript-gocommit34ffe2a2531a226da0046d213899ae0b721229b0, and update the TypeScript latest tag totypescript@latest.
0.36.3
10 Aug 202673f7f28: Refresh patched binaries when an updated
@effect/tsgopackage provides a different replacement artifact.9190801: Update Effect v4 dependencies and embedded test fixtures to
4.0.0-beta.107.
0.36.2
10 Aug 20268362acc: Extend the walker-rule prefilter to call expressions.
A call expression's type is its resolved signature's return type, and both the signature and that return type are already cached from the main check phase.
NodeCouldBeStrictEffectnow consults them for call nodes and skips the expensive flow-analysis re-check when the declared return type conclusively cannot be a strict Effect. Signature-less calls, optional chains, and every inconclusive return type stay conservative, andpromiseInEffectSuccessno longer computes a location type for calls only to discard it. Emitted diagnostics are unchanged; on a large Effect monorepo build this removes a further ~4.6% of wall time on top of the reference-node prefilter, bringing the total Effect diagnostics overhead versus a pristine tsgo build of the same commit down to ~17%.9020153: Skip diagnostic rules below the minimum visible severity before executing them.
In
tscCLI mode withoutincludeSuggestionsInTsc, suggestion- and message-severity diagnostics are dropped from the output after rules run. The rule runner now receives the minimum severity the caller can surface and skips such rules up front, avoiding their type-checker queries entirely. A rule below the threshold still runs when any directive in the file references it (for example// @effect-diagnostics ruleName:erroror a wildcard), since directives can raise its severity and must be tracked forunusedDirectivereporting. Emitted diagnostics are unchanged; on a large Effect monorepo build this removes roughly 1–2s of check time.257af25: Skip flow-analysis type queries for references that conclusively cannot be an Effect.
The
effectInFailureandpromiseInEffectSuccessrules walk every node of a file and query its flow type just to test whether it is a strict Effect type. The newTypeParser.NodeCouldBeStrictEffectprefilter inspects the referenced symbol's declared type first — flow narrowing can only refine the declared type, so a declared type that conclusively contains no possibly-Effect constituent (primitives, plain objects with a different type name, unions thereof) can never produce a strict Effect flow type, and the expensive query is skipped. The predicate is conservative:any/unknown, type parameters, conditionals, symbol-less types, and deep unions always fall through to the full query. Emitted diagnostics are unchanged; on a large Effect monorepo build this removes ~10% of build wall time (~2.7s of ~26.8s).
0.36.1
9 Aug 20264db1d4b: Preserve existing indentation and newline styles when setup updates JSON configuration files.
c154a04: Update the TypeScript next tag to
typescript@next, which shipstypescript-gocommit24fabe95acba758c05fcb349bf427a3a0c8ad676, and update the TypeScript latest tag totypescript@latest.
- 0.35.x
0.35.0
7 Aug 2026f25821b: Generate detailed upstream update pull request descriptions with explicit version changes and the TypeScript-Go commits introduced by the update.
3fe06c8: Avoid false positive TS2731 diagnostics for symbol-valued interpolations in tagged template literals when Effect diagnostic rules traverse the template expression.
989964b: Prevent
preferTypedSchemaDecoderfrom panicking when a decoder input is produced by a preceding call or pipe transformation.
Minor Changes
f25821b: Generate detailed upstream update pull request descriptions with explicit version changes and the TypeScript-Go commits introduced by the update.
Patch Changes
3fe06c8: Avoid false positive TS2731 diagnostics for symbol-valued interpolations in tagged template literals when Effect diagnostic rules traverse the template expression.
989964b: Prevent
preferTypedSchemaDecoderfrom panicking when a decoder input is produced by a preceding call or pipe transformation.86c30b1: Persist Effect plugin options in TypeScript build information so incremental builds recheck semantic diagnostics when extended tsconfig plugin settings change.
b8e7314: Update the TypeScript next tag to
typescript@next, which shipstypescript-gocommit86cc4767d4ebadb9b7845d0ab8eb2b05785c3fee, and update the TypeScript latest tag totypescript@latest.
- 0.34.x
0.34.0
7 Aug 2026974513e: Add a non-interactive
setupworkflow with explicit project, integration, diagnostic, editor, preview, and apply options. Setup now also recommends running the package manager install command whenever it changespackage.json.ba4ec9a: Cache generated TypeScript-Go shims by their effective inputs during local repository setup and CI runs.
6d0ffda: Remove unused internal helpers and add dead-code analysis to the repository lint workflow.
Minor Changes
974513e: Add a non-interactive
setupworkflow with explicit project, integration, diagnostic, editor, preview, and apply options. Setup now also recommends running the package manager install command whenever it changespackage.json.
Patch Changes
ba4ec9a: Cache generated TypeScript-Go shims by their effective inputs during local repository setup and CI runs.
6d0ffda: Remove unused internal helpers and add dead-code analysis to the repository lint workflow.
892021a: Use absolute GitHub URLs for links in the published README so documentation links remain clickable on npm.
- 0.33.x
0.33.0
6 Aug 2026ae0d537: Add the
preferTypedSchemaDecoderstyle suggestion, which recommends typed Schema decoder APIs when an input is assignable to the schema's encoded type.42534d2: Reuse Go build cache entries across shim generation by preparing package-loading inputs at stable, content-addressed paths.
cfea036: Update Effect v4 dependencies and embedded test fixtures to
4.0.0-beta.104, update Schema class completions for theErrorandTaggedErrorrenames, and suppress auto-imports from blocked Effect internal modules.
Minor Changes
ae0d537: Add the
preferTypedSchemaDecoderstyle suggestion, which recommends typed Schema decoder APIs when an input is assignable to the schema's encoded type.
Patch Changes
42534d2: Reuse Go build cache entries across shim generation by preparing package-loading inputs at stable, content-addressed paths.
cfea036: Update Effect v4 dependencies and embedded test fixtures to
4.0.0-beta.104, update Schema class completions for theErrorandTaggedErrorrenames, and suppress auto-imports from blocked Effect internal modules.ec0b11f: Update the TypeScript next tag to
typescript@next, which shipstypescript-gocommit12318e599d21f516defea3b20e5d44b9369da723, and update the TypeScript latest tag totypescript@latest.
- 0.32.x
0.32.0
5 Aug 202652ec481: Normalize upstream metadata into versioned TypeScript, Oxlint, and oxlint-tsgolint components, including the versions required by Vite+. Repository setup and validation now operate on unique component versions instead of named upstream profiles.
7447a69: Patch Oxlint's TypeScript declarations with the
effecttsgoplugin and rule names.
- 0.31.x
- 0.30.x
- 0.29.x
0.29.0
4 Aug 202602035a1: Add TypeScript and Oxlint integration selection to
effect-tsgo setup, including supported Oxlint dependency pinning and integration-aware prepare scripts.9e21c6c: Split release builds for TSC, tsgolint, and the Oxlint native binding so Go artifacts can be cross-compiled on Linux independently of the platform-specific Rust builds.
- 0.28.x
- 0.27.x
- 0.26.x
- 0.24.x
0.24.3
23 Jul 2026Reading the note…