FAQ

为什么我在 node_modules 中的 ArkType 包中看到类型错误?

这可能是由于您的 tsconfig.json 与我们的配置不兼容所致。只要您的源代码中的类型正确,这完全无害。

我们强烈推荐在每个 TypeScript 项目中启用 skipLibCheck,以避免此类假阴性并显著提升编辑器性能。

是否有办法创建异步 morph?

除了在输出对象上将其作为 promise 处理之外,没有其他方法。

就目前而言,这似乎不值得为类型系统中的 morph 添加显著的复杂性。

如果您有引人注目的用例,请在 这个 GitHub issue 上告知我们。

您的 type/Type 命名规范是怎么回事?

您可能已经注意到,在我们的文档中,我们对某些 Type 使用 PascalCase,对其他一些使用 camelCase:

const  = ({
	name: "string",
	platform: "'android' | 'ios'",
	"version?": "number | string"
})

const  = ("string.json.parse").to({
	name: "string",
	version: "string.semver"
})

这种区别实际上源于我们为内部 TypeScript 类型命名所使用的规则:

  • 对以下内容使用 PascalCase

    • 实体/非泛型类型(例如 UserSomeData
    • 具有名词名称的泛型类型,例如 Array<t>。作为经验法则,如果其所有参数都有默认值,则您的泛型应以此方式命名(不幸的是,TS 内置的 Array 类型没有默认参数,但它本该是 unknown!)
  • 对以下内容使用 camelCase

    • 具有动词名称的泛型类型,例如 inferDomain<t>。以此方式命名的类型通常应至少有一个必需参数。
    • 参数名称,例如 Array<t> 中的 t

如果您不喜欢这样,请随意使用最适合您仓库的命名规则——这不会以任何方式影响您的 Type 或作用域别名。

为什么我的包装器泛型不起作用?

TypeScript 泛型推断 notoriously 难以处理。包装 Type 和定义的通用模式已在 Generics 文档 中概述。

如果您想编写类型级逻辑,则需要进行类型断言。

在实现具有泛型返回类型的函数时,您几乎总是需要在实现中进行类型断言,要么显式使用 as,要么使用重载。

将其视为以内部安全性换取外部精确性。只要您编写的函数将在外部被多次调用,这种开销就是合理的。如果不是,它可能根本不需要是泛型的——像 string 这样的宽泛返回类型而非 ${prefix}.${key} 可能就足够了。

查看示例
// 通过显式断言
const  = <const def>(
	of: type.<def>
): type.<{ of: def }> =>
	type.raw({
		box: of
		// 在实现泛型时,never 是您的首选
		// 用于允许任意赋值,同时比 `any` 的风险更小
	}) as never

// 通过重载
// 仅外部签名在调用时被考虑
function createBox2<const def>(
	of: type.<def>
): type.<{ of: def }>
// 与实现关联的签名要宽松得多,在类型安全性方面应视为等同于断言
function createBox2(of: unknown) {
	return type.raw({
		box: of
	})
}

请注意,在两种情况下,我们都显式注解了所需的返回类型,并在内部使用某种断言方法来允许我们的实现。这是实现泛型函数的常见方式,更一般地说,是将实现与 TS 无法自行推断的类型关联起来的常见方式。

对于任何更复杂的情况,您将不得不依赖对类型操作的理解来实现预期结果。通过追踪 ArkType 的内部类型,您可能会发现有用的模式,甚至在 我们的 Discord 中找到友好的人,他们可能愿意伸出援手。

然而,一般来说,我们无法保证您的泛型会按您预期的行为工作

编写一个好的泛型函数可能需要理解许多复杂细节和边缘情况——这是我们的核心 API 所抽象掉的那类内容。

不幸的是,就 ArkType 如何与外部泛型集成而言,这是不可行的。

获得您想要的结果需要耐心,但这种 API 的 DX 上限极高。

如果我们到现在还没有吓跑您,我们很期待看到您用它构建什么 🧗

On this page