有没有办法使用 typescript zod 库来解析类实例

Gwy*_*ion 8 typescript zod

我已经使用 Zod 验证库和 Typescript 有一段时间了,并且很喜欢它。

这可能是一个非常基本的事情,但我试图找出用类功能扩展 Zod Schema 的最佳模式。

为了示例,我们有一个如下所示的 Vector3 模式:

const Vector3Schema = z.object({
    x: z.number(),
    y: z.number(),
    z: z.number(),
})

type Vector3 = z.infer<typeof Vector3Schema>;
Run Code Online (Sandbox Code Playgroud)

将类型与 zod 验证相关联是非常好的。没有重复的定义,非常干净。我喜欢。

问题是我应该如何继续使用一些类似类的功能来扩展 Vector3 类型。

也许这是我的 OOP 背景光辉槽,但我希望以类似类的方式拥有与类型相关的一些基本功能,因此可以像这样使用它:

let vec1 = Vector3Schema.parse({x:1, y: 2, z: 3});
let vec2 = Vector3Schema.parse({x:4, y: 5, z: 6});
let distance = vec1.distance(vec2);
vec1.normalize();
Run Code Online (Sandbox Code Playgroud)

我可以为 Vector3 创建一个单独的类定义,并仅使用 Zod 来验证传递给构造函数的数据。但这很快就会导致同样的老问题:必须分别维护类定义和验证逻辑。

所以我想问题是:是否有一种方便的方法将 Zod 模式解析为类实例?或者用附加功能扩展解析类型?

或者..我应该放弃我爷爷的 OOP 方式并继续采用更实用的风格:

function normalize(v: Vector3) {...}
function distance(v1: Vector3, v2: Vector3) {...}

let vec1 = Vector3Schema.parse({x:1, y: 2, z: 3});
let vec2 = Vector3Schema.parse({x:4, y: 5, z: 6});
let distance = distance(vec1, vec2);
vec1 = normalize(vec1);

Run Code Online (Sandbox Code Playgroud)

我很想听听您对这个话题的想法。

Gwy*_*ion 7

看起来这里已经讨论过 Javascript: https: //github.com/colinhacks/zod/issues/641

建议的想法是使用工厂函数来扩展对象。也许可以修改它以与打字稿一起使用。需要调查一下。

更新:

经过一番测试后,我想出了这个打字稿解决方案:

  const Vector3Schema = z.object({
    x: z.number(),
    y: z.number(),
    z: z.number(),
  });

  interface Vector3 extends z.infer<typeof Vector3Schema> {
    normalize: () => void;
    distance: (v: Vector3) => number;
  }

  function parseVector3(data: unknown): Vector3 {
    return {
      ...Vector3Schema.parse(data),
      normalize: function () { /*...*/ },
      distance: function(v: Vector3) { /*...*/}
    };
  }
Run Code Online (Sandbox Code Playgroud)

现在,与所有打字稿优点一起使用的用例将是:

let vec1 = parseVector3({x:1, y: 2, z: 3});
let vec2 = parseVector3({x:4, y: 5, z: 6});
let distance = vec1.distance(vec2);
vec1.normalize();
Run Code Online (Sandbox Code Playgroud)

如果有更好或更优雅的解决方案,请告诉我。