HardPro challengePythonJavaScriptTypeScript
Schema Validator with Mapped Types
TypeScriptTypesPatterns
This is the core concept behind Zod, Valibot, and io-ts: a schema object that both validates at runtime AND infers TypeScript types.
The pattern
type TypeMap = {
string: string;
number: number;
boolean: boolean;
array: unknown[];
object: Record<string, unknown>;
};
// Schema maps field names to TypeMap keys:
const userSchema = { name: 'string', age: 'number', active: 'boolean' } as const;
// InferSchema<S> derives the validated type:
type InferSchema<S extends Record<string, keyof TypeMap>> = {
[K in keyof S]: TypeMap[S[K]];
};
type User = InferSchema<typeof userSchema>;
// → { name: string; age: number; active: boolean }Implement createValidator(schema)
Returns a validate(value) function that:
- Returns
{ ok: true, data: T }if the value matches every key/type in the schema - Returns
{ ok: false, errors: string[] }listing all violations
Validation rules:
- Missing key →
"Missing key: \"fieldName\"" - Wrong type →
"\"fieldName\" must be number, got string" nullor non-object input →["Expected an object"]
Supported type strings: 'string', 'number', 'boolean', 'array', 'object'
Sample tests
Test #1valid object passes validation
Input: [{"age":"number","name":"string"},{"age":30,"name":"Alice"}]
Output: {"ok":true,"data":{"age":30,"name":"Alice"}}
Test #2wrong type fails with error message
Input: [{"age":"number","name":"string"},{"age":30,"name":42}]
Output: {"ok":false,"errors":["\"name\" must be string, got number"]}
Test #3missing required key fails
Input: [{"id":"number","active":"boolean"},{"id":1}]
Output: {"ok":false,"errors":["Missing key: \"active\""]}
Test #4array type passes
Input: [{"tags":"array"},{"tags":[1,2,3]}]
Output: {"ok":true,"data":{"tags":[1,2,3]}}
Test #5string instead of array fails
Input: [{"tags":"array"},{"tags":"not-an-array"}]
Output: {"ok":false,"errors":["\"tags\" must be array, got string"]}