jsonata-js/jsonata

Stronger `registerFunction` TS types by inferring types from signature, and a road to a language service (PR coming!)

adamscybot opened this issue · 0 comments

First a little context, I have a PR I've been chipping away at that's 95% done. I have completed this work as part of another package I am working on that creates a "plugin" wrapper around JSONata, but it struck me there's no reason this particular part can't be in the core. The change is exclusively only to the TS types. I will raise it hopefully over the next week, I just need to move it from my WIP package. You can see the impl thus far here. I've put in a fair amount of effort in clearing all the edge cases. I'm first creating this issue to set the goals and invite discussion, and hopefully get some indication from the maintainers that they think this would be good and approval-permitting, could be merged 😊.

When using TS with JSonata It's a little tiresome and error-prone to have to manually define the types of a function provided to registerFunction when they are already expressed within the signature string. For example:

expression.registerFunction(
  "<s-ns?:s>",
  (
    arg1: string | undefined,
    arg2: number | undefined,
    arg3: string | undefined,
  ) => {
    // stuff
  },
);

Wouldn't it be nice if TS just knew from the signature those were the types? Well, now we can! Via TS Template Literal Types.

I propose that via modification to the TS declarations of the package, we could implement a TS based signature string parser that can automatically infer the types of the args. Including complex cases like unions, subtypes, nested subtypes. and even taking into account modifiers.

Below screenshots show proposed ParseSignature type alias being used directly, but it would be used automatically under the hood for registerFunction in the final PR and automatically read the passed signature string.

image

It could also detect bad signature at compile time.

image

This would:

  1. Give stronger guarantees for typescript users, and nice IDE support for registerFunction.
  2. Find erroneous or problematic signatures.
  3. Open the door to a possible language service in something like VSCode for JSonata. It seems like a lot of code just to make registerFunction nice (but that's valuable too; and its only type declarations without runtime change). But being able to do this makes a basic language service support much more achievable. Since the function registry (and associated signatures) could be used to check usage and provide errors in the IDE in actual queries! This PR wont cover it, but its a step there.
  4. No idea if this is something that the maintainers care about, but if changing the actual core impl of JSONata to TS was on the cards this is the most annoying hurdle gone, if wanting to avoid breaking changes and have good type safety.