You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Ajv与TypeScript编写验证器时遇类型不兼容错误求助

Ajv + TypeScript 类型不兼容问题排查与解决

问题代码

import Ajv, { JSONSchemaType } from "ajv";
const ajv = new Ajv();

interface Attribute {
  name: string;
  type: string;
  ref?: boolean;
  cardinality?: string;
  optional?: boolean;
}

interface Concept {
  type: string;
  root?: boolean;
  attributes?: Array<Attribute>;
  hidden?: boolean;
  terminal?: boolean;
  expression?: string;
}

const properties = {
  name: { type: "string" },
  type: { type: "string" },
  ref: { type: "boolean" },
  cardinality: { type: "string"}, 
  optional: { type: "boolean" },
};

const conceptSchema: JSONSchemaType<Concept> = {
  type: "object",
  properties: {
    type: { type: "string" },
    root: { type: "boolean"},
    attributes: {
      type: "array",
      uniqueItems: true,
      items: {
        type: "object",
        properties: properties,
        required: ["name", "type"],
      },
    },
    hidden: { type: "boolean" },
    terminal: { type: "boolean" },
    expression: { type: "string" },
  },
  required: ["type"],
  additionalProperties: false,
};

错误信息

"message": "类型 '{ type: "object"; properties: { type: { type: "string"; }; root: { type: "boolean"; }; attributes: { type: "array"; uniqueItems: true; items: { type: "object"; properties: { name: { type: string; }; type: { type: string; }; ref: { ...; }; cardinality: { ...; }; optional: { ...; }; }; required: ("type" | "name")[]; }...' 无法分配给类型 'UncheckedJSONSchemaType<Concept, false>'。
'properties.attributes' 的类型在两种类型中不兼容。
类型 '{ type: "array"; uniqueItems: true; items: { type: "object"; properties: { name: { type: string; }; type: { type: string; }; ref: { type: string; }; cardinality: { type: string; pattern: string; }; optional: { type: string; }; }; required: ("type" | "name")[]; }; }' 无法分配给类型 '{ $ref: string; } | (UncheckedJSONSchemaType<Attribute[] | undefined, false> & { nullable: true; const?: null | undefined; enum?: readonly (Attribute[] | null | undefined)[] | undefined; default?: Attribute[] | ... 1 more ... | undefined; })'。
'items' 属性的类型不兼容。
类型 '{ type: "object"; properties: { name: { type: string; }; type: { type: string; }; ref: { type: string; }; cardinality: { type: string; pattern: string; }; optional: { type: string; }; }; required: ("type" | "name")[]; }' 无法分配给类型 'UncheckedJSONSchemaType<Attribute, false>'。
'properties.name' 的类型在两种类型中不兼容。
类型 '{ type: string; }' 无法分配给类型 '{ $ref: string; } | (UncheckedJSONSchemaType<string, false> & { const?: string | undefined; enum?: readonly string[] | undefined; default?: string | undefined; })'。
类型 '{ type: string; }' 无法分配给类型 '{ type: "string"; } & StringKeywords & { allOf?: readonly UncheckedPartialSchema[] | undefined; anyOf?: readonly UncheckedPartialSchema[] | undefined; ... 4 more ...; not?: UncheckedPartialSchema<...> | undefined; } & { ...; } & { ...; }'。
类型 '{ type: string; }' 无法分配给类型 '{ type: "string"; }'。
'type' 属性的类型不兼容。
类型 'string' 无法分配给类型 '"string"'。"

问题原因

错误的核心是TypeScript的类型推断机制:

  • 单独定义的properties对象中,{ type: "string" }里的"string"会被TypeScript默认推断为通用的string类型,而非精确的字面量类型"string"。
  • Ajv的JSONSchemaType要求JSON Schema中的type字段必须是字面量类型(比如"string"、"boolean"),以此和TypeScript接口的类型严格对应,所以出现类型不匹配。

解决方法

方法1:用as const锁定字面量类型

给properties中每个type的值添加as const断言,强制TypeScript将其识别为字面量类型:

const properties = {
  name: { type: "string" as const },
  type: { type: "string" as const },
  ref: { type: "boolean" as const },
  cardinality: { type: "string" as const }, 
  optional: { type: "boolean" as const },
};

方法2:给properties指定精确类型

直接为properties定义符合Ajv要求的类型,明确每个属性的type是字面量类型:

import { JSONSchemaType } from "ajv";

type AttributePropertySchema = {
  name: JSONSchemaType<string>;
  type: JSONSchemaType<string>;
  ref: JSONSchemaType<boolean>;
  cardinality: JSONSchemaType<string>;
  optional: JSONSchemaType<boolean>;
};

const properties: AttributePropertySchema = {
  name: { type: "string" },
  type: { type: "string" },
  ref: { type: "boolean" },
  cardinality: { type: "string"}, 
  optional: { type: "boolean" },
};

方法3:内联properties定义

如果不需要复用properties,直接把属性定义写在conceptSchema的items中,TypeScript会自动推断字面量类型:

const conceptSchema: JSONSchemaType<Concept> = {
  type: "object",
  properties: {
    type: { type: "string" },
    root: { type: "boolean"},
    attributes: {
      type: "array",
      uniqueItems: true,
      items: {
        type: "object",
        properties: {
          name: { type: "string" },
          type: { type: "string" },
          ref: { type: "boolean" },
          cardinality: { type: "string"}, 
          optional: { type: "boolean" },
        },
        required: ["name", "type"],
      },
    },
    hidden: { type: "boolean" },
    terminal: { type: "boolean" },
    expression: { type: "string" },
  },
  required: ["type"],
  additionalProperties: false,
};

内容的提问来源于stack exchange,提问作者Humberto

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 12:35:19