bcherny/json-schema-to-typescript

Generate validators

SamMousa opened this issue · 2 comments

This is a more generic version of #8

I think it makes sense to generator user defined type guards and user defined type assertions.
They should check both the static stuff that is expressed in the interface as well as the dynamic stuff.

Currently when interfacing with backends that implement an API you have to trust that it implements the models correctly. At the edge of our code, we see stuff like this:

const response = await fetch("uri");
const someModel = await response.json();

Now we must trust / assume that the model is correct. The bad way (imo) to do this is with typecasts:

const someModel: ModelX = (await response.json()) as ModelX;

This is essentially opting out of any checks. Instead we can write a user defined type assertion:

function assertObject(thing: unkown): asserts thing is object {
    if (typeof thing !== 'object') {
        throw "Expected thing to be an object";
    }
}

function assertString(arg: unknown): asserts arg is string {
	if (typeof arg !== 'string') {
		console.error('Not of type string:', arg);
		throw 'Argument is not of type string';
	}
}

function assertStringRecord(obj: unknown): asserts obj is Record<string, unknown> {
	if (typeof obj !== 'object' || obj === null) {
		throw 'Argument must be an object';
	}
	for (const key in obj) {
		assertString(key);
	}
}

function assertModelX(thing: unknown): asserts thing is ModelX {
    assertObject(thing);
    if (!thing.hasOwnProperty('id') || typeof thing.id != 'number') {
        throw "Id must be numeric"
    }
}

These helper functions can be easily generated for most, if not all, cases.

They aren't sufficient to validate complex schemas though and is out of scope of the package (generating typescript types).
You have to use ajv to generate validators.

They aren't sufficient to validate complex schemas though

I don't think that is true, since they are just code and you could validate anything.

and is out of scope of the package (generating typescript types).

Fair enough!

Might be interesting to pair this with ajv for validation. In that situation the implementation will be trivial. I'll see if I can maybe make an adapter or something.