Effect v4 的 Schema 和 Config 有哪些改名?

升级到 effect 4.0.5 之后,Schema.decodeUnknown 和 Config.string 都会直接报「不存在」;更麻烦的是 Schema.decode 这个名字还在,但已经不是你以为的那个函数了。

Schema 的大部分变化是改名和换成 .check、.annotate 这类方法式写法;Config 是函数名改成大写开头。真正的陷阱只有一个:Schema.decode 与 Schema.encode 的含义变了。

下面按「执行解码」「构造 schema」「可选字段」「Config」四块列出,都是我在 4.0.5 上核对过的。Schema 本身怎么用,见 Effect Schema:在系统边界做解码,一份定义多处使用。

执行解码的函数改成了什么?

  • Schema.decodeUnknown 改名 decodeUnknownEffect,encodeUnknown 改名 encodeUnknownEffect。decodeUnknownSync 保留。
  • 陷阱:Schema.decode 与 Schema.encode 这两个名字在 v4 里仍然存在,但含义变了,它们现在是「给 schema 加转换」的组合子,不再是执行解码的函数。执行解码要用 decodeEffect、encodeEffect。

构造 schema 的写法有哪些变化?

  • Schema.Union(A, B) 必须传数组 Schema.Union([A, B]);多个字面量用 Schema.Literals([...]);Schema.Record 接两个参数 Schema.Record(Key, Value)。
  • Schema.filter 与 minLength 这一类被统一成 .check(Schema.isMinLength(1));Schema.annotations 变成 .annotate;parseJson 变成 fromJsonString;transform 变成 decodeTo;withDefaults 不存在了,解码默认值用 withDecodingDefault,构造默认值用 withConstructorDefault。
  • 错误类:Schema.TaggedError<Self>()("Tag", fields) 的形状在 4.0.5 里没有变,仍然可以直接 yield*、用 catchTag 处理。

optionalWith 没了,可选字段怎么写?

Schema.optionalWith 没有了。optional 允许值是 undefined,optionalKey 只允许省略这个键,传 undefined 会解码失败,这点在 exactOptionalPropertyTypes 下尤其重要。

把上面几项放在一起:

// schema.ts
import { Schema } from "effect"

export const Id = Schema.String.check(Schema.isMinLength(1))
export const Status = Schema.Literals(["draft", "published"])
export const Scores = Schema.Record(Schema.String, Schema.Number)
export const IdOrNumber = Schema.Union([Id, Schema.Number])

export const Payload = Schema.fromJsonString(
  Schema.Struct({
    id: Id,
    status: Status,
    note: Schema.optional(Schema.String),
    nickname: Schema.optionalKey(Schema.String)
  })
)

export const decodePayload = Schema.decodeUnknownEffect(Payload)

export class NotFound extends Schema.TaggedError<NotFound>()("NotFound", { id: Schema.Number }) {}

Config 的名字怎么变了?

名字都变成了大写开头的函数:Config.string 是 Config.String,Config.redacted 是 Config.Redacted,number、integer、boolean 对应 Number、Int、Boolean。Duration.decode 变成 Duration.fromInputUnsafe,也算同一类。

整体迁移顺序见 Effect 从 v3 升级到 v4 要改哪些地方?;解码出错时错误类型也变了,见 Effect v4 升级后有哪些编译器不会报的行为变化?。

版本是 effect 4.0.5。文中说「不存在」的 API 用 tsc 或运行时检查确认过,上面的代码在 strict 与 exactOptionalPropertyTypes 下编译过。v3 一侧的写法用 effect 3.22.3 对照确认过。