You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
54 lines
1.6 KiB
TypeScript
54 lines
1.6 KiB
TypeScript
export type ObjectType = { [key: string]: Schema };
|
|
export type PrimitiveType = "null" | "boolean" | "number" | "string";
|
|
export type Schema = PrimitiveType | ObjectType | Array<Schema>;
|
|
|
|
export function validate<T>(json: any, schema: Schema): T {
|
|
if (typeof schema === "string") {
|
|
return validatePrimitive(json, schema) as T;
|
|
}
|
|
|
|
if (Array.isArray(schema)) {
|
|
if (schema.length !== 1) {
|
|
throw new SyntaxError("Invalid schema: Array types must only contain one element");
|
|
}
|
|
const type = schema[0];
|
|
|
|
if (!Array.isArray(json)) {
|
|
throw new TypeError(`Expected array, got ${typeof json} instead`);
|
|
}
|
|
|
|
const a = [];
|
|
for (let e of json) {
|
|
a.push(validate(e, type));
|
|
}
|
|
return a as T;
|
|
}
|
|
|
|
const o: any = {};
|
|
for (let prop in schema) {
|
|
if (schema.hasOwnProperty(prop)) {
|
|
if (!json.hasOwnProperty(prop)) {
|
|
throw new TypeError(`Property ${schema[prop]} is missing`);
|
|
}
|
|
o[prop] = validate(json[prop], schema[prop]) as any;
|
|
}
|
|
}
|
|
return o;
|
|
}
|
|
|
|
function validatePrimitive<T extends PrimitiveType>(json: any, type: T):
|
|
PrimitiveToJSType<T> {
|
|
if (typeof json === type) {
|
|
return json;
|
|
} else {
|
|
throw new TypeError(`Expected type ${type}, got ${typeof json} instead`);
|
|
}
|
|
}
|
|
|
|
type PrimitiveToJSType<T extends PrimitiveType> =
|
|
T extends "null" ? null :
|
|
T extends "boolean" ? boolean :
|
|
T extends "number" ? number :
|
|
T extends "string" ? string :
|
|
never;
|