HardPro challengeJavaScriptTypeScript

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"
  • null or 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"]}