Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add lazy or some way to create recursive types #85

Open
arv opened this issue Jan 5, 2023 · 5 comments
Open

Add lazy or some way to create recursive types #85

arv opened this issue Jan 5, 2023 · 5 comments

Comments

@arv
Copy link

arv commented Jan 5, 2023

zod etc have a lazy combinator that allows creating recursive validators.

For example, given this TS type:

type Node = {
  label: string;
  children: Node[];
};

There is no way to define this with simple-runtypes

@hoeck
Copy link
Owner

hoeck commented Jan 5, 2023

You're right, this is missing. Wasn't a priority for me as I've never encountered a recursive type in any API that I needed to validate.

Do you happen to have any real world examples (just curious)?

@arv
Copy link
Author

arv commented Jan 5, 2023

I realized that I can do this with runtype but maybe there is room for simplifacation?

import * as t from 'simple-runtypes';

type Node = {
  children: Node[];
  label: string;
};

const node: t.Runtype<Node> = t.record({
  children: t.array(
    t.runtype((c) => {
      const r = t.use(node, c);
      if (!r.ok) {
        return r.error;
      }
      return r.result;
    }),
  ),
  label: t.string(),
});

Maybe lazy can be defined as:

import * as t from 'simple-runtypes';

function lazy<T>(fn: () => t.Runtype<T>): t.Runtype<T> {
  return t.runtype(v => {
    const r = t.use(fn(), v);
    return r.ok ? r.result : r.error;
  });
}

then the Node example becomes:

import * as t from 'simple-runtypes';

type Node = {
  children: Node[];
  label: string;
};

const node: t.Runtype<Node> = t.record({
  children: t.array(
    lazy(() => node),
  ),
  label: t.string(),
});

@arv
Copy link
Author

arv commented Jan 5, 2023

The real world scenarios include tree like data structures... Filesystems, btrees etc.

@hoeck
Copy link
Owner

hoeck commented Jan 5, 2023

Thx, that looks good. Is it just something that is missing in theory or do you have a case at hand where you need this feature?

I know that filesystems are in theory a tree, but the APIs I've been using in the past will just return a flat list of files/dirs for single directories, never full fledged trees.

If you like you can submit a PR but I will also add it by myself when I have some time.

And thanks for the suggestion!

@arv
Copy link
Author

arv commented Jan 5, 2023

We currently use zod (and superstruct) and have a JSON type that is recursive.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants