{"id":51895712,"url":"https://github.com/junzhli/typescript-type-validator","last_synced_at":"2026-07-26T09:03:58.968Z","repository":{"id":299194215,"uuid":"1002239467","full_name":"junzhli/typescript-type-validator","owner":"junzhli","description":"Typescript-first type validator","archived":false,"fork":false,"pushed_at":"2025-06-20T02:12:47.000Z","size":101,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-07-21T12:56:05.826Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/junzhli.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-06-15T02:57:19.000Z","updated_at":"2025-06-20T02:12:05.000Z","dependencies_parsed_at":"2025-06-15T08:59:13.497Z","dependency_job_id":"3180152b-35a5-4efa-bbfc-5b42dfb2309f","html_url":"https://github.com/junzhli/typescript-type-validator","commit_stats":null,"previous_names":["junzhli/typescript-type-validator"],"tags_count":25,"template":false,"template_full_name":null,"purl":"pkg:github/junzhli/typescript-type-validator","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/junzhli%2Ftypescript-type-validator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/junzhli%2Ftypescript-type-validator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/junzhli%2Ftypescript-type-validator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/junzhli%2Ftypescript-type-validator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/junzhli","download_url":"https://codeload.github.com/junzhli/typescript-type-validator/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/junzhli%2Ftypescript-type-validator/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35908330,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-07-20T02:08:10.276Z","status":"online","status_checked_at":"2026-07-26T02:00:06.503Z","response_time":89,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-07-26T09:03:58.234Z","updated_at":"2026-07-26T09:03:58.963Z","avatar_url":"https://github.com/junzhli.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Typescript type validator\n[![NPM Version](https://img.shields.io/npm/v/typescript-type-validator)](https://www.npmjs.com/package/typescript-type-validator)\n[![Build the project](https://github.com/junzhli/typescript-type-validator/actions/workflows/build.yaml/badge.svg?branch=main)](https://github.com/junzhli/typescript-type-validator/actions/workflows/build.yaml)\n\nA fully TypeScript-supported type validator that enables type checks at both transpile time and runtime using a flexible schema and input validation.\n\n## Features\n* Type-Safe Schema Definition\n* Automatic Type Inference\n* Runtime Validation\n* Nested Objects and Arrays\n* Reusable Validators\n* Flexible Validation Options (`ValidateOptions`)\n* Custom Type Field Validation\n\n## Installation\n```shell\n# yarn\nyarn add typescript-type-validator\n# npm\nnpm install typescript-type-validator\n```\n\n## Usage\n\n### 1. Define a Schema\n\n```typescript\nimport { field, objectField, arrayField, customField, Type, Validator, TypeFromSchema, FieldOptions } from \"typescript-type-validator\";\n\n// Define a schema for your data\nconst userSchema = {\n  id: field(Type.Number),                             // required field (default)\n  name: field(Type.String),                           // required field (default)\n  email: field(Type.String, { optional: true }),      // optional field\n  profile: objectField({\n    age: field(Type.Number),                          // required field\n    verified: field(Type.Bool, { optional: true }),   // optional field\n  }),\n  tags: arrayField(field(Type.String)),               // required array of strings\n  posts: arrayField(objectField({\n    title: field(Type.String),\n    content: field(Type.String),\n    published: field(Type.Bool, { optional: true }),\n  }), { optional: true }),                            // optional array of objects\n  // Custom field: must be a string that starts with \"user_\"\n  customId: customField((val) =\u003e {\n    if (typeof val !== \"string\" || !val.startsWith(\"user_\")) throw new Error(\"customId must start with 'user_'\");\n    return val as `user_${string}`;\n  }, { optional: true }),\n} as const;\n```\n\n### 2. Get Inferred Type\n\n```typescript\n// TypeFromSchema gives you the TypeScript type for your schema\ntype User = TypeFromSchema\u003ctypeof userSchema\u003e;\n// User is:\n// {\n//   id: number;\n//   name: string;\n//   email?: string;\n//   profile: { age: number; verified?: boolean };\n//   tags: string[];\n//   posts?: { title: string; content: string; published?: boolean }[];\n//   customId?: `user_${string}`; // inferred from the custom field\n// }\n```\n\n### 3. Validate Data at Runtime\n\n```typescript\nconst userData = {\n  id: 1,\n  name: \"Alice\",\n  profile: { age: 30 },\n  tags: [\"admin\", \"editor\"],\n};\n\nconst validated = Validator.validate(userSchema, userData);\n// validated is now strongly typed as User\n\n// Throws ValidationError if invalid:\ntry {\n  Validator.validate(userSchema, { id: \"not-a-number\", name: \"Bob\", profile: { age: 20 }, tags: [] });\n} catch (e) {\n  console.error(e); // ValidationError with details\n}\n```\n\n### 4. Use with Validation Options\n\n```typescript\nimport { ValidateOptions } from \"typescript-type-validator\";\n\n// Basic validation options\nconst options: ValidateOptions = {\n  strict: true,           // throws on unexpected fields\n  rootKey: \"request.body\" // prefixes all error keys\n};\n\nconst userData = {\n  id: 2,\n  name: \"Charlie\",\n  profile: { age: 25 },\n  tags: [\"user\"],\n  extra: \"not allowed\",\n};\n\ntry {\n  Validator.validate(userSchema, userData, options);\n} catch (e) {\n  console.error(e); // ValidationError: UnexpectedFieldError for key \"request.body.extra\"\n}\n\n// You can also use individual options\nValidator.validate(userSchema, userData, { strict: true });\nValidator.validate(userSchema, userData, { rootKey: \"api.input\" });\nValidator.validate(userSchema, userData, {}); // default options\nValidator.validate(userSchema, userData);     // default options\n```\n\n### 5. Enhanced Error Context with Root Key\n\nThe `rootKey` option is particularly useful for API validation where you want to provide clear error paths:\n\n```typescript\nconst apiSchema = {\n  user: objectField({\n    profile: objectField({\n      name: field(Type.String),\n      age: field(Type.Number),\n    })\n  })\n};\n\ntry {\n  Validator.validate(apiSchema, {\n    user: { profile: { name: \"John\", age: \"invalid\" } }\n  }, { rootKey: \"request.body\" });\n} catch (e) {\n  console.error(e.error.key); // \"request.body.user.profile.age\"\n  // Instead of just: \"user.profile.age\"\n}\n```\n\n### 6. Use as a Class\n\n```typescript\nconst userValidator = new Validator(userSchema);\n\n// Same API as static method\nconst validUser = userValidator.validate({\n  id: 3,\n  name: \"Dana\",\n  profile: { age: 40, verified: true },\n  tags: [],\n});\n\n// With options\nconst validUserStrict = userValidator.validate(userData, { strict: true });\n```\n\n### 7. Custom Type Field Validation\n\nYou can define custom fields using your own resolver functions. The resolver receives the input value and must return the validated value. The return type will be inferred automatically.\n\n```typescript\nimport { customField, Validator, TypeFromSchema } from \"typescript-type-validator\";\n\nconst schema = {\n  evenNumber: customField((val, key) =\u003e {\n    if (typeof val !== \"number\" || val % 2 !== 0) throw new Error(`Not an even number under key: ${key}`);\n    return val; // must return the original value\n  }),\n  optionalEvenNumber: customField((val, key) =\u003e {\n    if (typeof val !== \"number\" || val % 2 !== 0) throw new Error(`Not an even number under key: ${key}`);\n    return val;\n  }, { optional: true }),\n};\n\ntype CustomType = TypeFromSchema\u003ctypeof schema\u003e;\n// CustomType is: { evenNumber: number; optionalEvenNumber?: number }\n\nValidator.validate(schema, { evenNumber: 4 }); // OK\nValidator.validate(schema, { evenNumber: 3 }); // Throws error\n```\n\n## Field Options\n\nAll field functions (`field`, `objectField`, `arrayField`, `customField`) support the `FieldOptions` parameter:\n\n```typescript\ntype FieldOptions = { optional?: boolean };\n\n// Examples:\nfield(Type.String)                     // required (default)\nfield(Type.String, {})                 // required (explicit)\nfield(Type.String, { optional: false }) // required (explicit)\nfield(Type.String, { optional: true })  // optional\n\nobjectField(schema)                    // required (default)\nobjectField(schema, { optional: true }) // optional\n\narrayField(innerField)                 // required (default)\narrayField(innerField, { optional: true }) // optional\n\ncustomField(resolver)                  // required (default)\ncustomField(resolver, { optional: true }) // optional\n```\n\n## Validation Options\n\nThe `ValidateOptions` type provides flexible validation configuration:\n\n```typescript\ntype ValidateOptions = {\n  strict?: boolean;   // Default: false - throws on unexpected fields when true\n  rootKey?: string;   // Default: undefined - prefixes all error keys\n};\n\n// Usage examples:\nValidator.validate(schema, data)                                    // defaults\nValidator.validate(schema, data, {})                               // explicit defaults\nValidator.validate(schema, data, { strict: true })                 // strict mode only\nValidator.validate(schema, data, { rootKey: \"api.request\" })       // error context only\nValidator.validate(schema, data, { strict: true, rootKey: \"body\" }) // both options\n```\n\n---\n\n**Exports available:**\n- `field`, `objectField`, `arrayField`, `customField` — for schema definition\n- `Type` — enum for field types\n- `FieldOptions` — type for field configuration options\n- `ValidateOptions` — type for validation configuration options\n- `TypeFromSchema` — type inference from schema\n- `Validator` — class and static method for validation\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjunzhli%2Ftypescript-type-validator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjunzhli%2Ftypescript-type-validator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjunzhli%2Ftypescript-type-validator/lists"}