Skip to content

[feature request] Validate while ignoring constraints (structure-only comparison) #1627

Description

@michaelboyles

Thank you for work on Arktype :)

It would be convenient to be able to validate an object by its structure only, while ignoring any constraints (e.g. string length, int range, etc.)

🤷 Motivation

I'd like to be able to use the same Arktype type for both GET requests and POSTs. Imagine an API like

GET /blog-posts/{post-id}
POST /blog-posts/new

And a Arktype type

const BlogPost = type({
    title: "string < 100",
    content: "string < 1000",
    authorId: "number"
});

On the client, before sending the POST request to create a new blog post, I'd like to validate that the type is valid, both according to its defined structure and constraints, so that I can show the user form validation errors.

However, for the API response, I only really care that the structure is valid. If the title or content is longer than the client is expecting, it's likely that the UI can handle that reasonably gracefully, at least better than completely blowing up. Maybe the backend has updated to allow longer titles and the frontend types haven't been updated to reflect that yet.

There doesn't currently seem to be much in the way to allow type reuse. As far as I can tell, I would pretty much need to do something like this, which involves a lot of repetition:

const BlogPost = type({
    title: "string",
    // ... others with no constraints
});
const NewBlogPost = type({
    title: "string < 100",
    // ... others with constraints
});

Alternatively, maybe it's possible to do something like this? Seems like ctx has a way to descend the tree. But even if it's possible, I think it would lose all the expressiveness of declaring them inline.

const BlogPost = type({
    title: "string"
});
const NewBlogPost = BlogPost.narrow((post, ctx) => {
    // TODO validate all the properties
    return true;
});

💡 Solution

There are couple of directions that seem possible. Syntax/names are only illustrative:

  • Add another method like allows, which checks the type but skips the constraints. e.g. BlogPost.allowsStructure(maybePost)
  • Derive one type from the other. Either:
    • Declare with constraints, but have a way to derive a type without them:
      const NewBlogPost = type({ ... }); // has constraints
      const BlogPost = NewBlogPost.withoutConstraints();
    • Declare without constraints, and have some way to append them (I don't like this and it seems like it would be the most work of the 3. Only really including it for completeness)
      const BlogPost = type({ ... }); // no constraints
      const NewBlogPost = BlogPost.withConstraints({
          title: "< 100" // note that type is omitted
      });

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status
    To do

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions