TypeDrop
2026-08-12 Challenge
2026-08-12
Easy
Typed Safe JSON Parser with Result & Schema Validation
You're building the data-ingestion layer for a configuration management tool. Raw JSON strings arrive from multiple untrusted sources (files, environment variables, API responses) and must be safely parsed, validated against a known shape, and returned as a typed `Result<T, ParseError>` — never throwing, never widening to `unknown` without a guard.
Goals
- Implement the `InferSchema<S>` conditional mapped type that converts a schema descriptor object into its corresponding TypeScript type.
- Implement `safeParseJSON` so it wraps `JSON.parse` in a try/catch and always returns a typed `Result` — never throwing.
- Implement `validateShape` to check each field's runtime type against its `FieldKind` descriptor and return a `ValidationError` naming the first failing field.
- Compose both utilities in `parseAndValidate` to form a single safe pipeline that propagates either error kind without losing type information.
challenge.ts
// Core Result type & error union
type Result<T, E> = { ok: true; value: T } | { ok: false; error: E };
type ParseError =
| { kind: "SyntaxError"; message: string; raw: string }
| { kind: "ValidationError"; message: string; field: string };
// Schema descriptor → inferred TS type (your job to implement!)
type FieldKind = "string" | "number" | "boolean" | "string[]";
type InferSchema<S extends Record<string, FieldKind>> = {
[K in keyof S]: never; // TODO: map each FieldKind to its TS type
};
// Functions you must implement:
declare function safeParseJSON(raw: string): Result<unknown, ParseError>;
declare function validateShape<S extends Record<string, FieldKind>>(
value: unknown,
schema: S
): Result<InferSchema<S>, ParseError>;
declare function parseAndValidate<S extends Record<string, FieldKind>>(
raw: string,
schema: S
): Result<InferSchema<S>, ParseError>;
Hints (click to reveal)
Hints
- For `InferSchema`, use a mapped type `[K in keyof S]: ...` combined with a conditional type `S[K] extends "string" ? string : S[K] extends "number" ? number : ...`.
- In `safeParseJSON`, catch the error as `unknown`, then check `instanceof Error` to safely read `.message` before constructing your `SyntaxParseError`.
- In `validateShape`, iterate over `Object.keys(schema)` and use `typeof (obj as Record<string, unknown>)[key]` to check each field — one localised assertion is acceptable inside this function only.
Useful resources
Or clone locally
git clone -b challenge/2026-08-12 https://github.com/niltonheck/typedrop.git