Creating a Schema Validator for JSONML Format in TypeScript

Hi! I'm trying to create a schema validatort for the JSonML format, which is something like this:

["<node_type>", ...<node_arguments>]


For example:
[
  "markdown",
  [
    "header",
    {
      "level": 2
    },
    "This is a ##Header level 2"
  ],
  [
    "para",
    "This is a paragraph"
  ]
]


My initial attempt is lookign something like this:

function JSonMLNode<K extends string, T>(nodeName: K, schema: S.Schema<T>): S.Schema<readonly [K, T]> {
  return S.Array(S.Union(S.Literal(nodeName), schema))
    .pipe(S.filter((xs) => xs.length > 0 && xs[0] === nodeName))
    .annotations({ identifier: `Node ${nodeName}` }) as any;
}

const JHeader = S.Tuple(S.Literal("header"), S.Struct({ level: S.Number }), S.String).annotations({ identifier: "Node Header" });
const JBulletList = JSonMLNode("bulletlist", S.Tuple(S.String, S.String));
const JParagraph = JSonMLNode("para", S.String);

const JElement = S.Union(JHeader, JParagraph, JBulletList).annotations({ identifier: "JSon Element" });

export const JSonMLSchema = JSonMLNode("markdown", JElement);


I'm having two main issues that I need help with:

1. Is there a way to make variadic tuples? For the moment I've created JSonMLNode to avoid this, but I would have to extend it a little bit, for example I coulnd't express JHeader with is as it stands.
2. Is there a way to specify a discrimination function (rather than a field) for the union type? I would like to use JHeader if the first argument is "header" and so on. This makes the errors very hard to read as they show me why a particular node doesn't match all the unions.
Was this page helpful?