# @candid-core/schema 中文文档

规范地址：https://npmcn.com/package/%40candid-core/schema/

版本：0\.5\.0
npm 元数据更新时间：2026-11-02T09:56:12.354Z
中文译文更新时间：2026-11-09T17:24:56.658Z
软件包许可：Apache-2\.0

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40candid-core/schema
原文对照：https://npmcn.com/package/%40candid-core/schema/?lang=original
项目主页：https://github.com/b3hr4d/candid-core/tree/main/crates/candid-core-ts/ts#readme
源码仓库：https://github.com/b3hr4d/candid-core

弃用说明：Renamed to @meantjs/schema

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：470 kB，20 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- 运行依赖：0 个
- 首次发布：2026-07-31T11:17:09.067Z
- 最新版本发布：2026-10-27T13:56:25.352Z
- 近 30 天下载量：2131（2026-10-09 至 2026-11-07，npm 官方下载统计）
- 已发布版本数：8（近 12 个月 8 个）

## 中文简介

Candid的Zod-style schema runtime:具有静态推论,结构验证功能的建设者,一个TypeScript-native 二进制编码器,以及一个从坦率的Canonical Contract文档中构建出相同计划的加载器.

## 安装

```sh
npm install @candid-core/schema
```

也可以使用：`pnpm add @candid-core/schema`、`yarn add @candid-core/schema`、`bun add @candid-core/schema`

## README

# @ candid- core/ schema

一个 Zod 风格的运行时间 [不错](https://github.com/dfinity/candid),驱动器 [实心](https://github.com/b3hr4d/candid-core)条子 合同模型:具有静态推论、结构验证、, a TypeScript-native Candid 二进制解码器, 以及一个装入器, 构造相同的 运行时从合同文件中发出的计划。 只有坎迪地层—— 呼叫弹匣( 运输、 身份、 演员) 属于您的层 在上面继续发展([下级](https://npmcn.com/package/%40candid-core/schema/#readme-services-and-func-references)) (中文(简体) ).

```sh
npm install --save-exact @candid-core/schema
```

这就是整个安装:没有运行时间依赖关系,也没有同行,主 处理包括([主要价值](https://npmcn.com/package/%40candid-core/schema/#readme-principal-values) 页:1.

> **0.5.0,无 `latest` 释放.** 这个README描述为0.5.0. 升级 从0.4.0起,在运行时间没有任何变化,只有一条省略规则: [`schemaFromContract`](https://npmcn.com/package/%40candid-core/schema/#readme-from-a-did-file),并仅解码于 类型级别 : `decode` 财务报告和审定财务报表 `decodeArgs` 从 `./codec` 现在输入其 因此,从解码值变为 键入其计划不描述停止编译。 移动两个软件包 组合: `@candid-core/cli` 0.4.0对 与准确的这个释放. 从0.3.0升级到仅添加类型 [`WithMode` 财务报告和审定财务报表 `ModeOf`](https://npmcn.com/package/%40candid-core/schema/#readme-services-and-func-references),该模块 cLI自0.3.0使用后生成. 从0.2.0升级是一次突破 变化:0.2.0也出口 `./actor`, (中文(简体) ), `./transport-icp`, (中文(简体) ), `./forms` 财务报告和审定财务报表 `./labels`,宣布可选 `@icp-sdk/core` 端点,键入主机为 `{ toText(): string }`,以及 拒绝 `opt opt T`, (中文(简体) ), `opt null` 财务报告和审定财务报表 `opt reserved`保留 `--save-exact`数字 : 包是1.0前的,所以任何微小放出都可能打破下一个,以及 `@candid-core/cli` 和它完全一个释放.
> 
> `@candid-core/schema` 0.3 打破 0.2 API(主值为条形文字,倒塌的选项为框式,每 `vec nat8` 是一个 `Uint8Array`,生成的模块使用新的绑定布局,并可能省略声明,以及 `./actor`, (中文(简体) ), `./transport-icp`, (中文(简体) ), `./forms` 财务报告和审定财务报表 `./labels` 子路径已去; 没有兼容层 .
> 
> 每一变化都记录在 [更改日志](https://npmcn.com/package/%40candid-core/schema/CHANGELOG.md),哪些船舶 在焦油丸中:自0.4.0下起 `0.5.0`,自0.3.0下 `0.5.0` 财务报告和审定财务报表 `0.4.0`,并且从0.2.0 这些, `0.3.0` 财务报告和审定财务报表 `0.3.0-beta.1`编辑 移徙说明 [从0.4.0起](https://ic-reactor.b3pay.net/candid-core/migrating-from-0-4.html), (中文(简体) ), [从0.3.0](https://ic-reactor.b3pay.net/candid-core/migrating-from-0-3.html) 财务报告和审定财务报表 [从0.2.0](https://ic-reactor.b3pay.net/candid-core/migrating-from-0-2.html) 显示每个断开对您的代码意味着什么 编译器显示它.

```ts
import { c, principal, type Infer } from "@candid-core/schema";
import { validate } from "@candid-core/schema/validate";
import { encode, decode } from "@candid-core/schema/codec";

const Account = c.record({ owner: c.principal, balance: c.nat });
type Account = Infer<typeof Account>; // { owner: Principal; balance: bigint }

const value: Account = { owner: principal("aaaaa-aa"), balance: 5n };

validate(Account, value); // { ok: true } | { ok: false, issues }
const encoded = encode(Account, value); // { ok: true, bytes } | { ok: false, issues }
if (encoded.ok) {
  decode(Account, encoded.bytes); // { ok: true, value: Account } | { ok: false, issues }
}
```

模块, 每个子路径导出 :

-   **`.`** - 计划核心: `c` 建筑师, `Schema<in out T>` (故意 以无常者发誓, `Infer`,而且节点接口将行走者缩小到-+ `resolveSchema` 财务报告和审定财务报表 `serviceMethods` 读回一个,因为一个计划 名称为 `rec` 间接与服务的方法是一个表, 编辑 `Principal` 类型及其 `principal` 财务报告和审定财务报表 `isPrincipal` 函数.
-   **`./validate`** ——有界限,已失效的结构验证;从未投出 任何值上(密钥未知的选项对象或不是 非负式安全整数抛出 `TypeError`,在每个子路径中:选项是 使用稳定代码和 `$`\- 根深蒂固的道路——加 `isResultSchema` 财务报告和审定财务报表 `unwrapResult`,计划指导读取 `variant { ok; err }` 公约 [下级](https://npmcn.com/package/%40candid-core/schema/#readme-unwrapping-okerr-results)。 。 。 .
-   **`./contract`** - 运行时从峡谷建造同样的计划 JSON合同文件——或单一文件 `ContractEnvelope` 携带 其散列强制字段名表.
-   **`./codec`** —— Candid 二进制线条格式, 有图案导向, 有 斯克的强制关系 在解码和明确的资源预算。 已验证 双向对照参考执行的向量。 编码 字节仅依赖于数值和 Candid 类型,绝不取决于是否 计划是生成、装入或手工建造的.

`validate`, (中文(简体) ), `encode` 财务报告和审定财务报表 `decode` 把他们的工作放在明显的堆栈上,而不是 JavaScript 调用堆栈, 因此配置的限制是他们唯一的界限 : 默认 `maxDepth` \* 256人在工作中拒绝敌对的深度价值或信息 和这个极限成正比, 一个值得信赖的宿主 升起它可以走一个 10万级链接列表或ICRC-3无论引擎的堆栈大小值—— 一个工人的小堆积包括——每通电话都有同样的答案.

这四个是整个导出地图: 没有别的了,一条深入 `dist/` 包含,可导入.

## 校长和 `@icp-sdk/core`

此软件包不依赖于 `@icp-sdk/core` ——非运行时间,不在其 声明,而不是作为对等者——因此,所有编译和运行时没有安装SDK,严格地说 类型脚本 `skipLibCheck` 不包含。 校长就是他的神话 文本,所以 SDK 值在您自己的边界上转换一次,与 `principal()`。 。 。 .

### 主要价值

`c.principal` 类型为 `Principal`从根导出 : 主文本作为品牌字符串——CRC-32校验和的小写基础32和 id 字节,破折叠组合为5个,例如 `"ryjl3-tyaaa-aaaaa-aaaba-cai"`。 。 。 . 这个 `principal` 服务参考文献 `Principal` 我也一样。 这是双向合同:

-   **你得到的东西.** 解码返回条形文字本身——平面 运行时的字符串 。 因此,解码答复仍然有效 `JSON.stringify` 联合国 主要序列化作为其文本), `structuredClone` 财务报告和审定财务报表 `postMessage`, (中文(简体) ), 比较与 `===`,并起到 `Map` 键或缓存键内。 没错 不是一个SDK `Principal` 实例; 需要类转换的代码 sDK的车 `Principal.fromText(value)`。 。 。 .
-   **尽能所施.** 没错 `Principal`验证和编码 接受一个其文字是空洞而拒绝其他一切的字符串—— 非词性拼写,对象为 `toText()`一个SDK `Principal` 实例——与 `invalid_type`,两个同意的案件。 做一个 与 `principal()`,该文本或任何东西 `toText()`数字 :

```ts
import { c, isPrincipal, principal, type Principal } from "@candid-core/schema";
import { encode } from "@candid-core/schema/codec";

declare const sdkPrincipal: { toText(): string }; // an @icp-sdk/core Principal, say

const owner: Principal = principal(sdkPrincipal); // once, at your boundary
const ledger = principal("ryjl3-tyaaa-aaaaa-aaaba-cai");

isPrincipal("aaaaa-aa"); // true: the management canister
isPrincipal("AAAAA-AA"); // false: not canonical
encode(c.record({ owner: c.principal }), { owner }); // { ok: true, bytes }
void ledger;
```

`principal()` 拒绝而不是修复。 文字必须已经是空洞的 – 小写,每五个字符后一个破折号,别的地方,匹配 校验和, 最后一个字符中的零补丁比特, 最多29字节的代号 - 或者它会扔出 `TypeError`;既不是一个字符串也不是一个 对象为 `toText()`。 。 。 . `"aaaaa-aa"` (管理罐)和 `"2vxsx-fae"` (匿名校长)是犬科; `"AAAAA-AA"` 财务报告和审定财务报表 `"aaaaaaa"` 没有. `isPrincipal` 是匹配的守护者, 相同的检查 `validate` 财务报告和审定财务报表 `encode` 应用。 该品牌只存在于类型系统中,所以 字符串不能代表主机, 没有该检查, 没有运行时间 费用.

这个名字和SDK的班级一致 输入两个别名的代码: `import type { Principal as CandidPrincipal } from "@candid-core/schema"`。 。 。 .

## 从a `.did` 文件

两条路由编译 Candid 源码到文档 `schemaFromContract` 消耗,两者都产生生成的模块所携带的精确的计数.

没有Rust工具链, [`@candid-core/cli`](https://www.npmjs.com/package/@candid-core/cli) 运行与 Web Assembly 相同的编译器和生成器。 它写出生成的 模块和a `ContractEnvelope` 文档, `./generated/service.envelope.json`, (中文(简体) ), 的字节与 `compile --envelope` 输出如下:

```sh
# The CLI release that pairs with this one: it peers exactly 0.5.0.
npx @candid-core/cli@0.4.0 gen ./service.did -o ./generated
```

有"一箱一箱"是两个命令 安装编译器, `meant`,哪个 发表于 `candid-core` 在它重新命名之前。 这是1.0前,所以针 版本此发行对 :

```sh
cargo install meant --version 0.1.0 --locked
meant compile ./service.did --envelope > ./service.json
```

`compile --envelope` 打印一个自定义文档: a `ContractEnvelope` 守住峡谷 `contract` 加一个 `extensions` 地图 `org.candid-core.field-names/v1` 条目带有字段名称表。 A 类 合同仓库权威字段标签 _编号_,而不是文本,所以名称 旅行副带 -- -- 和信封扩展部分在运河外直播 设计身份,所以携带他们 永远不会移动一个 `contract_id`。 。 。 . `schemaFromContract` 消耗整个文档 :

```ts
import { readFileSync } from "node:fs";
import { schemaFromContract } from "@candid-core/schema/contract";

const built = schemaFromContract(JSON.parse(readFileSync("./service.json", "utf8")));
if (!built.ok) {
  throw new Error(JSON.stringify(built.issues));
}

built.schemas.Account; // one Schema per declaration, in declaration order
built.actor; // the service schema, when the document has one
built.omitted; // what was left out, and why — the list the generator reports
```

二文件流也起作用:平原 `compile` (无) `--envelope`)指纹 `{ ok, contract, source_info }`名称 `[container, id, name]` 三进 `source_info.field_labels` - 其 `label.kind` 实值 `"named"` - 通过为 页:1 `names` 选项与赤色 `contract`数字 :

```ts
import { schemaFromContract, type FieldNameEntry } from "@candid-core/schema/contract";

declare const compiled: { contract: unknown };
declare const names: FieldNameEntry[];

schemaFromContract(compiled.contract, { names });
```

这两条路线都产生同样的计划 和明确的 `names` 选项总是胜过带信封的名字——信封的表格 然后就完全不咨询.

`schemas` 准确持有申报 生成的模块输出 同一文件。 无法代表生成模块的声明被忽略, 利用每一个宣言和行动者方法——通过巢穴 `func` 财务报告和审定财务报表 `service` 类型,直到包含的宣布,并列出 内 `omitted` 作为 `{ kind, name, reason, via? }`,按生成器顺序和 及其理由代码: `reserved_field_name` (一个真正命名为 `_N_` id渲染,作为键会读回错误的线id, `ambiguous_variant_arm`, (中文(简体) ), `reserved_export_name` (以名称命名的声明) `actor` 或者说 `Actor`, (中文(简体) ), `invalid_declaration_name` (名称不是) 标识符形状),以及 `references_omitted`,其 `via` 名称省略 引用声明。 演员从不省略;只输方法 列出。 无效的文档仍然失败, 与 `issues`。 。 。 .

位置和数字标签无名称并被跳过;这些字段 由生态系统的 `_id_` 公约,恰好是生成者制造的 他们。 每个名字——信封携带或呼叫者提供相同——都是 hash-enforce:它必须是其id的 Candid 假象,所以一个表是 关闭失败, 而不是悄悄重命名一个字段 。 完全没有通过桌子 使每个领域成为 `_id_`,这也是什么 `compile --no-source-info` 离开你.

生成的模块导入此软件包为命名空间 `$`,各声明 名称下的宣布类型,并绑定其计划 `$`\- 前缀的本地出口名称,所以没有Candid 名称 - `c`, (中文(简体) ), `Array`, (中文(简体) ), `delete` - 与模块本身的绑定相撞,您导入 你写的名字( e)`import { Tokens, actor, type Actor } from "./ledger"`),以及 一个编译器也给它们取了名。 无法成为模块类型的名称 (单位:千美元)`Array`, (中文(简体) ), `delete`保留 `$` 本地类型。 这个 `.did`医生 注释和参数名称在导出类型上成为 JSDoc, 有记录 属性和可变武器,以及 `Actor`和每个 `vec nat8` 是一个 `Uint8Array`,但是其元素类型被命名.

## 服务及菌类参考文献

A 类 `service` schema 描述一个罐子界面;它不叫一个. `serviceMethods` 读取其方法表——名称、模式、参数和结果 schemas——和代码将每个调用时的论据和回音转换为 Candidd 字节,这是调用层从此软件包中需要的:

```ts
import { c, principal, serviceMethods } from "@candid-core/schema";
import { encodeArgs, decodeArgs } from "@candid-core/schema/codec";

const Account = c.record({ owner: c.principal, subaccount: c.opt(c.vec(c.nat8)) });
const Ledger = c.service({
  balance_of: c.func([Account], [c.nat], "query"),
});

const method = serviceMethods(Ledger).get("balance_of");
if (method !== undefined) {
  const request = encodeArgs(method.args, [
    { owner: principal("aaaaa-aa"), subaccount: null },
  ]);
  // `request.bytes` is the argument a transport sends on the `method.mode`
  // path; the reply's bytes decode with `decodeArgs(method.results, reply)`.
  void request;
  void decodeArgs;
}
```

请求字节是一个声音缓存或分解键:类型表是 从 Candid 类型结构所建, 所以一个调用编码到相同的字节 其计划是否来自生成的模块,来自 `schemaFromContract`, (中文(简体) ), 或从 `c.*` 和上面的一样,无论按键排列值 拼写其地.

运输、身份、证书核查、重复和援引 已解码的 func 引用是调用层的工作, 而不是这个软件包的: 一个 func _价值_ 保留惰性 `{ principal, method }` 双人 仍在生成模块 导出输入的调用接口为类型 `Actor` 旁边 `actor` 服务计划,因为 `c.rec` 从 a 中删除方法结构 计划 _类型_ ——计程带值,而不是调用——所以调用层不能 把它从 `typeof`。 。 。 .

每种方法 `Actor` 也带有其模式: 它是调用签名 与 `WithMode<mode>`,以及 `ModeOf` 将模式读回,所以一个呼叫 层可以拒绝在编译时构建读取的更新.

```ts
import type { ModeOf, WithMode } from "@candid-core/schema";

type Actor = {
  fee: (() => Promise<bigint>) & WithMode<"query">;
  transfer: ((amount: bigint) => Promise<void>) & WithMode<"update">;
};
type FeeMode = ModeOf<Actor["fee"]>; // "query"
```

标记不会改变任何东西: 呼叫签名, `keyof Actor` 编辑 模块的导出是相同的,一个普通的async函数仍然执行 这个方法。 一个 `Actor` 用手书写,没有读作整体 `MethodMode` 结合,模式未知.

## 打开 OK/err 结果

`variant { ok : T; err : E }` 通用罐子结果公约,以及 寻常的解码方法就是 _价值_ 页:1 `ok`编号 :`err` 密钥——在任何记录上误射的猜测,合法携带 那些字段名称, 一个不能输入错误的有效载荷。 是否得到答复 _实值_ 结果,每一只手臂都携带着一个图谋:

```ts
import { c, type Infer } from "@candid-core/schema";
import { isResultSchema, unwrapResult } from "@candid-core/schema/validate";

const TransferError = c.variant({
  bad_fee: c.record({ expected_fee: c.nat }),
  too_old: c.null,
});
const TransferResult = c.variant({ ok: c.nat, err: TransferError });

isResultSchema(TransferResult); // true
isResultSchema(c.record({ ok: c.bool, err: c.opt(c.text) })); // false: a record is not a variant

declare const reply: unknown; // whatever the call decoded to

const outcome = unwrapResult(TransferResult, reply);
if (outcome.issues) {
  // Not a value of this schema at all: the issues `validate` would report.
  throw new Error(outcome.issues[0].message);
} else if (outcome.ok) {
  const blockIndex: bigint = outcome.value;
  void blockIndex;
} else {
  const failure: Infer<typeof TransferError> = outcome.error;
  void failure;
}
```

这两种拼法都得到承认,因为 _双对_数字 : `ok`编号 :`err`,这是莫托克的 `Result.Result` 生产,以及 `Ok`编号 :`Err`Rust的直截了当的衍生物 双臂和双臂 添加一个变体 第三个臂不是结果,因为将它映射到两个州会降低一个. 赤齿臂( C)`variant { ok; err : text }`打开 `null`单曲 candid 的值 `null` 它声明.

一个 `err` 臂是一个值,而不是一个例外:一个没有投出,一个 格式错误的值以 `{ ok: false, issues }` 而不是作为一个 也一样 一个不是结果变体的计划 _实值_ 程序员 错误和丢弃 `TypeError`。 。 。 .

## 支持矩阵

以被包装的柏油丸来测量——文物 `npm pack` 生产, 采取和消费作为一种依赖性 `@arethetypeswrong/cli` 财务报告和审定财务报表 直接编译,不从清单中推断.

|  |  |
| --- | --- |
| 类型脚本 | **≥ 5.0** |
| `moduleResolution` | `node16`, (中文(简体) ), `nodenext`, (中文(简体) ), `bundler` |
| 模块格式 | **仅限无害环境管理** - 没有共同JS建造船只 |
| 来自无害环境管理的节点 | **≥ 16** (行使16.20、18.20、20.19、22.12、25.9) |
| 节点,来自普通JS `require()` | **≥ 20.19 ≥ 22.12**,则 `await import()` |
| TypeScript, 来自普通JS 工程 | **≥ 5.8 与 `"module": "nodenext"`** |

**类型脚本 5.0** 是一个硬地板,它是一个 _剖析_ 下方错误,不是 类型错误 : `c.tuple` 以 `const` 类型参数 - 5.0 特性使tuple的元素类型不会扩大——所以4.9停止在 `error TS1139: Type parameter declaration expected.` 内 `dist/schema.d.ts` 在它输入前检查任何东西.

**`node10` 分辨率完全无法看到此软件包.** 没有高层 `main` 或者说 `types` 字段,仅一个 `exports` 映射, 所以每次导入失败 `TS2307` — TypeScript 的自带信件指示您移动到 `node16`, (中文(简体) ), `nodenext`, (中文(简体) ), 或者说 `bundler`。 。 。 .

**支持无害环境管理本身不足以作为节点.** 建设目标ES2020 并且没有下层, 所以可选的连锁 和无效的连接到达 `dist/` 逐字记录——它们出现在八个单元中的四个单元中 `dist/` 船舶——以及 V8 8.0 语法,14前的节点可以解析. 上面楼层是 最古老的版本 这个软件包实际上运行 而不是最古老的 可能发挥作用:16.20.2 行使和通过每一个子路径,没有比这更古老的东西 被索赔.

**从普通JS**,两层独立. 跑步时, `require()` 联 合 国 一个ES模块是节点在20.19和22.12中添加的;低于所投的 `ERR_REQUIRE_ESM`时 `await import("@candid-core/schema")` 成功时间 每个版本测试。 在类型一级,a `"type": "commonjs"` 项目需求 类型脚本 5.8 _财务报告和审定财务报表_ `"module": "nodenext"` —— 说 `"module": "node16"` 被钉住 至节点16语义,仍拒绝使用 `TS1479` 每测试一个编译器, 最高包括7.0.

这是故意的 **没有 `engines` 字段**两个楼层都狭窄,即: ES2020 无害环境管理能力节点,a `require(esm)`\- 适合通用JS的 - 和 在安装元数据时执行会发出警告,或失败 `engine-strict`,对于消费者则不适用. 这里有记载 换句话说.

## 域形( 有意决定 )

类型描述现代域,而非代理-js运行时形状: `opt T` 实值 `T | null` - 除了内在类型的选择 `null` (单位:千美元)`opt opt T`, (中文(简体) ), `opt null`, (中文(简体) ), `opt reserved`)为 `{ some: T } | null`这样 `None`, (中文(简体) ), `Some(None)`, (中文(简体) ), 财务报告和审定财务报表 `Some(Some(x))` 保留三个不同的值——变体是: `{ tag, value }` 受歧视的工会 `vec nat8` (单位:千美元)`blob`)为 `Uint8Array`, (中文(简体) ), `nat`编号 :`int`64位整数为 `bigint`校长是他们的教条 文字, 标记 [`Principal`](https://npmcn.com/package/%40candid-core/schema/#readme-principal-values) 绳子. 与代理人-js值形状的相容性是一个明显的非目标,记录在 计划的问题追踪器.

## 核查

每一份发行都开着一个包装的消费门 上面写着:, 在上传任何信息之前: 焦油球 `npm pack` 在犯罪时生产 被提取到一个干净的工程,在严格的类型Script下编译 `skipLibCheck` 关闭并执行——根和每一个子路径导出,一个真实的 编码/验证回程。 发布步骤然后从中构建并上传 同样的承诺。 此文件中的类型脚本 由同一扇门编成, 与被包装的文物相对, 所以这里有一个例子 无法从文件包中漂移。 解码器是额外的 对照参考执行方案本身的线线进行双向核查 向量计.

## 证明

生成的装订、合同模式和符合要求的大门都住在 [实心](https://github.com/b3hr4d/candid-core) 寄存器; 此软件包版本独立( 前 1. 0) . [变动情况](https://npmcn.com/package/%40candid-core/schema/CHANGELOG.md) 船在焦油和记录中 释放, 编译器板条箱版本它与(`meant`,作为 `candid-core` 在它重新命名之前).

## 常见问题

### @candid-core/schema 是什么？

Candid的Zod-style schema runtime:具有静态推论,结构验证功能的建设者,一个TypeScript-native 二进制编码器,以及一个从坦率的Canonical Contract文档中构建出相同计划的加载器\.注意：该包已被作者标记为弃用——Renamed to @meantjs/schema

### 如何安装 @candid-core/schema？

在项目目录运行 npm install @candid-core/schema，或使用 pnpm add / yarn add / bun add。

### @candid-core/schema 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @candid-core/schema 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @candid-core/schema 可以商用吗？

@candid-core/schema 使用 Apache-2\.0 许可。宽松许可：允许商业使用、修改和再分发，并附带明确的专利授权；分发时需保留许可与 NOTICE 文件，修改过的文件要注明改动。以上为概括，不构成法律意见，请以许可原文为准。

### @candid-core/schema 的下载量有多少？

根据 npm 官方下载统计，@candid-core/schema 在 2026/10/09 – 2026/11/07 这 30 天内被下载 2,131 次，日均约 71 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @candid-core/schema 还在维护吗？

最新版本 0\.5\.0 发布于 2026/10/27（13 天前）；至今共发布 8 个版本，其中过去 12 个月发布了 8 个；首次发布于 2026/07/31。作者已将其标记为弃用，新项目建议寻找替代方案。

