I am currently utilizing a parser toolkit called Chevrotain to develop a query language that offers users the ability to enhance its functionality. Despite having all the necessary components in place, I am facing challenges when it comes to defining types for this extended behavior. My goal is to establish a configuration object with typings that enable Typescript users to benefit from convenient IDE assistance in ensuring the accuracy of their input. While it seems achievable (or at least very close), my focus has been on crafting these types rather than resorting to runtime assertions.
Here's a simplistic example showcasing some configuration:
ops: {
equal: {
lhs: {
type: 'string',
from: v => String(v),
},
rhs: {
type: 'number',
from: v => v.toString(),
},
compare: (lhs, rhs) => lhs === rhs,
}
equal: { /*...*/ }
}
The following criteria are what I aim to achieve:
- The argument type for
from
should be linked to the string literal value within thetype
property. I've successfully accomplished this through various methods, with the most straightforward being a basic type such as:
type ArgTypes = {
string: string,
number: number,
ref: any, // The strings aren't necessarily Typescript types and can involve more complex types
}
The fields
lhs
andrhs
should support distinct types both as inputs and outputs.The
compare
function must accept the output of propertieslhs
andrhs
, then return a boolean value.
While I have succeeded in typing things at the level of a single operator (equal
), expanding this to an object-bag of operators has proved challenging. In an attempt showcased in a Playground link where I gradually built it up using generics and child types, the type signature for Ops
at line 105 seemed problematic. Here's the link to that playground experiment: attempt N. Another approach, inspired by a discussion on avoiding type widening issues when passing object literals as arguments in TypeScript, involved adding type arguments extensively, but encountered difficulties once the "compare" line was uncommented in the type signature. Specifically, the previously narrow types became generalized (e.g., the literal "number"
transitioned to string
).
Would it be feasible to accomplish this task, or should I consider abandoning it? If so, what would be the best course of action?