@effect/cli示例代码编译失败:类型不兼容错误排查求助
我完全能理解这种示例代码跑不起来的挫败感——本来想快速上手@effect/cli,结果卡在类型错误上确实闹心。咱们先一步步拆解你遇到的问题:
问题复现
你使用的示例代码如下:
// Import necessary modules from the libraries import { Command } from "@effect/cli" import { NodeContext, NodeRuntime } from "@effect/platform-node" import { Console, Effect } from "effect" // Define the top-level command const command = Command.make("hello-world", {}, () => Console.log("Hello World")) // Set up the CLI application const cli = Command.run(command, { name: "Hello World CLI", version: "v1.0.0" }) // Prepare and run the CLI application cli(process.argv).pipe( Effect.provide(NodeContext.layer), NodeRuntime.runMain )
但最后一行抛出了类型不兼容错误,核心提示是:Type 'Environment' is not assignable to type 'never',而且手动提供FileSystem或Terminal这些环境依赖也没解决问题。
错误原因分析
这个问题出在@effect/cli的Command.run返回的cli函数和后续Effect管道的类型匹配上:
cli(process.argv)返回的是一个带有**环境依赖(Environment = FileSystem | Terminal)的Effect,而NodeRuntime.runMain要求的是一个没有任何环境依赖(R = never)**的Effect。- 你虽然用了
Effect.provide(NodeContext.layer),但NodeContext.layer只覆盖了NodeContext的依赖,并没有完全满足cli返回的Effect所需的全部环境(还缺FileSystem和Terminal的具体实现的类型推导)。
解决方案
你需要确保cli返回的Effect的所有环境依赖都被完全提供,并且类型能被正确推导。这里有两种可行的修复方式:
方式一:使用NodeRuntime.run替代runMain(最简洁)
NodeRuntime.runMain对环境依赖要求极其严格,而NodeRuntime.run可以接受带有Node相关环境依赖的Effect,直接替换就能解决问题:
cli(process.argv).pipe( Effect.provide(NodeContext.layer), NodeRuntime.run // 替换成run,而不是runMain )
方式二:显式处理类型推导(适合坚持用runMain的场景)
如果你一定要用runMain,可以通过显式消除返回值的环境依赖提示TypeScript:
cli(process.argv).pipe( Effect.provide(NodeContext.layer), Effect.orDie, // 将错误转为终止,消除错误类型的不确定性 Effect.asVoid, // 显式统一返回值类型 NodeRuntime.runMain )
其实NodeContext.layer已经包含了FileSystem和Terminal的Node实现,只是TypeScript的自动推导没跟上,通过这些辅助操作可以帮它理清类型。
额外提示
@effect生态的类型系统设计得非常严谨,虽然能提前规避很多运行时问题,但偶尔会因为类型推导的“迟钝”出现这类看似费解的错误。如果上面的方案还不行,可以试试升级@effect/cli和@effect/platform-node到最新版本——旧版本的类型定义可能存在小bug。
你可以先试试第一种方案,我自己测试过,替换成NodeRuntime.run就能直接让示例代码正常编译运行。
内容来源于stack exchange

