Mr X
Mr X

Reputation: 1739

How to add additionalProperties in nested schema in typebox ajv which has common schema import?

I tried to add the { additionalProperties : false} to one of my typebox schema

schema.ts


export const numericString = (options: { default: string }) =>
  Type.String({
    ...options,
    pattern: '^[0-9]+$'
  });

export const commonQueryParamsWithPagination = Type.Object({
  sort: Type.Optional(Type.String()),
  page: numericString({ default: '1' }),
  size: numericString({ default: '100' })
});

export const getUserRequestQuerySchema = Type.Intersect(
  [
    Type.Object({
      status: Type.String()
    }),
    commonQueryParamsWithPagination
  ]
);

export const getUserRequestSchema = Type.Object({
  query: getUserRequestQuerySchema,
  body: Type.Any(),
  headers : Type.Any(),
  params: Type.Any()
} ,   { additionalProperties: false });


This works if any other property is passed to the the top level,

In case we need to add this property to the query schema along with request schema

Option 1:

  [
    Type.Object({
      status: Type.String()
    }),
    commonQueryParamsWithPagination
  ],
  { additionalProperties: false }
);

This approach make the all the property as additional property and is not allowed at all

In order make it work we need to make the query schema without Type.Intersect and commonQueryParamsWithPagination


export const getUserRequestQuerySchema = Type.Object({
      status: Type.String(),
      sort: Type.Optional(Type.String()),
      page: numericString({ default: '1' }),
       size: numericString({ default: '100' })
    }),

As there can be multiple conditions where I have reuse the existing schema so how would I make it work for { additionalProperties : false } for neseted schema whihc need to reuse the existing schema ?

Upvotes: 0

Views: 56

Answers (1)

Jeremy Fiel
Jeremy Fiel

Reputation: 3219

It looks like you may be running into a common misconception with earlier JSON Schema versions, in this case, draft-07.

additionalProperties: false and allOf is probably not doing what you think it should be doing.

Quite a few schema authors get this part of the specification incorrect

{
  "additionalProperties": false,
  "allOf": [
    {
      "properties": {"name": {"type": "string"}},
    },
    {
      "properties": {"age": {"type": "number"}}
    }
  ]
}

this schema will not allow any object instance to pass validation because the root schema is constrained to no additional properties. additionalProperties cannot see into subschemas defined in the allOf.

The only way to make this work in that manner is to define all properties in each subschema at the root of the schema where the allOf is defined. An empty schema is sufficient for the additionalProperties to recognize those keywords, then the allOf subschema constraints can be applied correctly

{
  "additionalProperties": false,
  "properties": {
    "name": {},
    "age": {}
  },
  "allOf": [
    {
      "properties": {"name": {"type": "string"}},
    },
    {
      "properties": {"age": {"type": "number"}}
    }
  ]
}

I have no idea how to write this in TypeBox, I have no experience with this tool. Sorry, can't help there but I wanted to explain the behavior I think you are running into.

Upvotes: 0

Related Questions