typst-community / valkyrie

Type safe type safety for Typst
Other
23 stars 2 forks source link

Improve introspection of types #36

Open jneug opened 1 week ago

jneug commented 1 week ago

I'm in the process of implementing a basic visualization of valkyrie schemas for my documentation template (like suggested in #17). It won't cover every possible case, but can be used as a means to define custom datatypes.

Some of the provided types don't expose all necessary information for this, though. For example #choice(list) "hides" the list of possible choices in an assertion closure.

It would be nice if types made all important information available (like in the example above in a choices key).

Some types do that (eg #either has an extra options key), but not all.

JamesxX commented 1 week ago

It's absolutely possible to change things so that those things are stored in the schema object (like how dictionary internally stores things). Have you put any thought into what a good standardised way of doing this might be?

There's a somewhat human-friendly name field that is used for generating error messages, perhaps a similar solution for identifying the type of a schema in a more computer-friendly way?

For specific schema types like either and choices, I'll look at adding pertinent info to the schema so it can be accessed when generating documentation.

jneug commented 1 week ago

So far, I'm using the name in most cases, but check for the existing of some special keys like dictionary-schema or descendents-schema to verify that I'm dealing with a dictionary / array type. The name might turn out to be inaccurate if people define their own types.

For example, I use a url type that is defined as

#let url(assertions: (), ..args) = string(
  name: "url",
  assertions: (
    assert.matches(
      regex("..."),      // regex to match URLs
    ),
    ..assertions,
  ),
  ..args,
)

My visualization does not know, that url is actually a string. For these cases, an internal type key might be useful, that can't be overridden. But I would be fine, if any more "complex" types (like choice) exposed their configuration to be able to be parsed by other packages.

I think in 0.2.0 the only type not doing this is choice. I could do a pull-request to add this, if you like.

JamesxX commented 1 week ago

I think perhaps the solution is to provide another field called description which defaults to name on construction. In your example:

#let url(assertions: (), ..args) = string(
  description: "url",
  assertions: (
    assert.matches(
      regex("..."),      // regex to match URLs
    ),
    ..assertions,
  ),
  ..args,
)

would have name:"string" and description:"url". Derived schema can then retain the parent's names if the programmer feels they behave similarly enough. There aren't many such types in the codebase so far so would be a small change for a nice benefit

jneug commented 1 week ago

Sure, that would work.