simple-runtypes icon indicating copy to clipboard operation
simple-runtypes copied to clipboard

Add lazy or some way to create recursive types

Open arv opened this issue 2 years ago • 5 comments

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

arv avatar Jan 05 '23 14:01 arv

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)?

hoeck avatar Jan 05 '23 14:01 hoeck

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 avatar Jan 05 '23 14:01 arv

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

arv avatar Jan 05 '23 14:01 arv

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!

hoeck avatar Jan 05 '23 19:01 hoeck

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

arv avatar Jan 05 '23 20:01 arv