Feature request: Runtime validation
For a schema "MyType", I would like this tool to generate the following TypeScript code.
import Ajv from "ajv";
const ajv = new Ajv();
const MyTypeSchema = {...}; // the schema object
const validateMyType = ajv.compile(MyTypeSchema);
export interface MyType {
...
}
export function MyType(value: any): MyType {
if (validateMyType(value)) {
return value as MyType;
} else {
throw new TypeError("Cannot convert value to type 'MyType'");
}
}
This would be invaluable addition, because currently TypeScript's greatest weakness is no dynamic type checking for I/O scenarios.
I would be willing to PR this if it is very likely to be accepted.
This is a neat idea, but my hunch is it'll be pretty hard to do in practice. Do you want to flush out (in this issue, or with code) what the runtime validation code might look like, and what the edge cases we should watch out for are? I'd encourage you to think exhaustively about the set of types we need to handle: arrays, tuples, objects, referenced types, custom types, and so on.
I don't think this would be that difficult.
We would add a type conversion error class to the main module
export class TypeConversionError extends TypeError {
constructor(public readonly typeName: string, public readonly issues: any) {
super(`Failed to convert value to '${typeName}'`);
}
}
At the top of each file, we would generate
import Ajv from "ajv";
const ajv = new Ajv();
The for each type (ex: MyType)
- Generate the schema as an value (ie the
JSON.parse(rawSchemaString))const MyTypeSchema = {...}; // the schema object - Generate the type validation function leveraging the schema
const validateMyType = ajv.compile(MyTypeSchema); - Generate the type (the existing behavior of this tool)
export type MyType = ...; - Generate the type safe casting function
export function MyType(value: any): MyType { const valid = validateMyType(value); if (valid) { return value as MyType; } else { throw new TypeConversionError("MyType", ajv.errors); } }
Do you have concerns about any specific step of this?
Looks like the biggest issue is generating the schema object. Currently, the pipeline only passes through the AST, whereas we would have to pass the schemas alongside the AST through the pipeline.
apologies for the dupe. i swore i searched. don't know how i missed that, thanks.
Edit: oops. i meant to post this in my issue...
but my hunch is it'll be pretty hard to do in practice
you've already done the hard part (generating ts types from a json schema). as for validation, ajv does all the heavy lifting there. as long as the ts type is accurate to the json schema it should be good to go, no?
speaking for myself, what i'm after is something pretty simple: just generating the ajv boilerplate alongside the ts type as a single unit. that way it's impossible for the two to diverge or break in subtle ways.