I am tasked with defining a schema for "operations" that will be used in my application. This schema must be easily extendable for other groups of "operations" and should include a dictionary of settings for each keyword.
Eventually, a "generic caller" will need to receive the type of the "operation" along with the keyword, and then cache it for future calls.
It is crucial for this "generic caller" to verify that the requested keyword is defined within the operation at compile time to catch errors early on in the development process.
Below is a solution that closely aligns with what I am looking for:
// Operation interface
interface Operation {
url: string
parameters: Record<string,string>
}
// Operations schema
class Operations {}
class BaseOperations extends Operations {
one: {
url: '/one',
parameters: {p: '1'}
}
two: {
url: '/two',
parameters: {}
}
}
// Generic caller (with caching functionality)
function runOperation<T extends Operations>(type: {new(): T;}, keyword: keyof T) {
let operation = new type();
//cache_and_run(operation[keyword]);
}
// Main
function main() {
runOperation(BaseOperations, 'one');
runOperation(BaseOperations, 'two');
runOperation(BaseOperations, 'three'); // Expected VS Code error
}
The only issue here is that the parameters defined in Operations
are not bound to the Operation
interface. While this is a minor problem, I aim to ensure that both ends (operation definitions and their usage) are validated at compile time.
Further research led me to the use of "index signature" parameter, which enforces the returned type:
class BaseOperations extends Operations {
[x:string]: Operation
one: {
url: '/one',
parameters: {p: '1'}
}
two: { // 'uarl' is not assignable
uarl: '/two'
}
}
However, this method disabled the 'one'|'two' check in runOperation
, as any string is now considered a valid keyof BaseOperations
.
Do you have any suggestions or solutions?