{"id":14156038,"url":"https://github.com/hoeck/simple-runtypes","last_synced_at":"2026-02-08T21:17:14.238Z","repository":{"id":37602850,"uuid":"210133241","full_name":"hoeck/simple-runtypes","owner":"hoeck","description":"Small, efficient and extendable runtype library for Typescript","archived":false,"fork":false,"pushed_at":"2023-12-19T14:54:50.000Z","size":739,"stargazers_count":116,"open_issues_count":9,"forks_count":5,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-08-26T01:12:38.944Z","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":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hoeck.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","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}},"created_at":"2019-09-22T11:07:15.000Z","updated_at":"2025-04-24T19:54:48.000Z","dependencies_parsed_at":"2023-12-19T09:47:57.402Z","dependency_job_id":"4c37ee08-41f8-4d2b-ba4c-741f0bcc9b5a","html_url":"https://github.com/hoeck/simple-runtypes","commit_stats":{"total_commits":170,"total_committers":8,"mean_commits":21.25,"dds":"0.42352941176470593","last_synced_commit":"e447a3b7b6e78f12ba37e2269f468d9452b121ef"},"previous_names":[],"tags_count":26,"template":false,"template_full_name":null,"purl":"pkg:github/hoeck/simple-runtypes","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hoeck%2Fsimple-runtypes","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hoeck%2Fsimple-runtypes/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hoeck%2Fsimple-runtypes/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hoeck%2Fsimple-runtypes/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hoeck","download_url":"https://codeload.github.com/hoeck/simple-runtypes/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hoeck%2Fsimple-runtypes/sbom","scorecard":{"id":467350,"data":{"date":"2025-08-11","repo":{"name":"github.com/hoeck/simple-runtypes","commit":"99e6bb95ff68fbfeb34e5716fa5403d8b0d18f1b"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.5,"checks":[{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":0,"reason":"Found 2/22 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/npm-publish.yml:1","Warn: no topLevel permission defined: .github/workflows/unit-tests.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/npm-publish.yml:50: update your workflow using https://app.stepsecurity.io/secureworkflow/hoeck/simple-runtypes/npm-publish.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/npm-publish.yml:52: update your workflow using https://app.stepsecurity.io/secureworkflow/hoeck/simple-runtypes/npm-publish.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/npm-publish.yml:62: update your workflow using https://app.stepsecurity.io/secureworkflow/hoeck/simple-runtypes/npm-publish.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/unit-tests.yml:28: update your workflow using https://app.stepsecurity.io/secureworkflow/hoeck/simple-runtypes/unit-tests.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/unit-tests.yml:30: update your workflow using https://app.stepsecurity.io/secureworkflow/hoeck/simple-runtypes/unit-tests.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/unit-tests.yml:39: update your workflow using https://app.stepsecurity.io/secureworkflow/hoeck/simple-runtypes/unit-tests.yml/master?enable=pin","Info:   0 out of   6 GitHub-owned GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 10 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":0,"reason":"12 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-968p-4wvh-cqc8","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg","Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275","Warn: Project is vulnerable to: GHSA-67mh-4wv8-2f99","Warn: Project is vulnerable to: GHSA-35jh-r3h4-6jhm","Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv","Warn: Project is vulnerable to: GHSA-gcx4-mw62-g8wm","Warn: Project is vulnerable to: GHSA-c2qf-rxjj-qqgw","Warn: Project is vulnerable to: GHSA-jv35-xqg7-f92r","Warn: Project is vulnerable to: GHSA-7p7h-4mm5-852v","Warn: Project is vulnerable to: GHSA-3mv9-4h5g-vhg3"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-19T12:52:36.726Z","repository_id":37602850,"created_at":"2025-08-19T12:52:36.726Z","updated_at":"2025-08-19T12:52:36.726Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29244639,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-08T21:00:43.743Z","status":"ssl_error","status_checked_at":"2026-02-08T20:59:20.374Z","response_time":57,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":"2024-08-17T08:05:10.271Z","updated_at":"2026-02-08T21:17:14.217Z","avatar_url":"https://github.com/hoeck.png","language":"TypeScript","readme":"[![npm version](https://badge.fury.io/js/simple-runtypes.svg)](https://www.npmjs.com/package/simple-runtypes)\n[![unit-tests](https://github.com/hoeck/simple-runtypes/workflows/unit-tests/badge.svg?branch=master)](https://github.com/hoeck/simple-runtypes/actions?query=workflow%3Aunit-tests+branch%3Amaster)\n[![npm-publish](https://github.com/hoeck/simple-runtypes/workflows/npm-publish/badge.svg)](https://github.com/hoeck/simple-runtypes/actions?query=workflow%3Anpm-publish)\n\n## Preface\n\nI said I want **SIMPLE** runtypes.\nJust functions that validate and return data.\nCombine them into complex types and TypeScript knows their structure.\nThat's how runtypes work.\n\n\u003c!-- toc --\u003e\n\n- [Install](#install)\n- [Example](#example)\n- [Why?](#why)\n- [Benchmarks](#benchmarks)\n- [Documentation](#documentation)\n  - [Intro](#intro)\n  - [Usage Examples](#usage-examples)\n    - [Nesting](#nesting)\n    - [Strict Property Checks](#strict-property-checks)\n    - [Ignore Individual Properties](#ignore-individual-properties)\n    - [Optional Properties](#optional-properties)\n    - [Non-strict Property Checks](#non-strict-property-checks)\n    - [Discriminating Unions](#discriminating-unions)\n    - [Custom Runtypes](#custom-runtypes)\n  - [Reference](#reference)\n  - [Roadmap / Todos](#roadmap--todos)\n\n\u003c!-- tocstop --\u003e\n\n## Install\n\n```sh\n# npm\nnpm install simple-runtypes\n\n# yarn\nyarn add simple-runtypes\n```\n\n## Example\n\n1. Define the Runtype:\n\n```typescript\nimport * as st from 'simple-runtypes'\n\nconst userRuntype = st.record({\n  id: st.integer(),\n  name: st.string(),\n  email: st.optional(st.string()),\n})\n```\n\nnow, `ReturnType\u003ctypeof userRuntype\u003e` is equivalent to\n\n```typescript\ninterface {\n  id: number\n  name: string\n  email?: string\n}\n```\n\n2. Use the runtype to validate untrusted data\n\n```typescript\nuserRuntype({ id: 1, name: 'matt' })\n// =\u003e {id: 1, name: 'matt'}\n\nuserRuntype({ id: 1, name: 'matt', isAdmin: true })\n// throws an st.RuntypeError: \"invalid field 'isAdmin' in data\"\n```\n\nInvoke a runtype with [`use`](src/custom.ts#L51) to get a plain value back instead of throwing errors:\n\n```typescript\nst.use(userRuntype, { id: 1, name: 'matt' })\n// =\u003e {ok: true, result: {id: 1, name: 'matt'}}\n\nst.use(userRuntype, { id: 1, name: 'matt', isAdmin: true })\n// =\u003e {ok: false, error: FAIL}\n\nst.getFormattedError(FAIL)\n// =\u003e 'invalid keys in record: [\"isAdmin\"] at `\u003cvalue\u003e` in `{\"id\":1,\"name\": \"matt\", ... }`'\n```\n\nNot throwing errors is way more efficient and less obscure.\n\nThrowing errors and catching them outside is more convenient:\n\n```typescript\ntry {\n  ... // code that uses runtypes\n} catch (e) {\n  if (st.isRuntypeError(e)) {\n    console.error(getFormattedError(e))\n\n    return\n  }\n\n  throw e\n}\n```\n\n## Why?\n\nWhy should I use this over the plethora of [other](https://github.com/moltar/typescript-runtime-type-benchmarks#packages-compared) runtype validation libraries available?\n\n1. **Strict**: by default safe against `__proto__` injection attacks and unwanted properties\n2. **Fast**: check the [benchmark](https://github.com/moltar/typescript-runtime-type-benchmarks)\n3. **Friendly**: no use of `eval`, and a small [footprint](https://bundlephobia.com/result?p=simple-runtypes) with no dependencies\n4. **Flexible**: optionally modify the data while it's being checked - trim strings, convert numbers, parse dates\n\n## Benchmarks\n\n[@moltar](https://github.com/moltar) has done a great job comparing existing runtime type-checking libraries in [moltar/typescript-runtime-type-benchmarks](https://github.com/moltar/typescript-runtime-type-benchmarks).\n\n[@pongo](https://github.com/pongo) has benchmarked [`simple-runtypes`](https://github.com/hoeck/simple-runtypes) against [`io-ts`](https://github.com/gcanti/io-ts) in [pongo/benchmark-simple-runtypes](https://github.com/pongo/benchmark-simple-runtypes).\n\n## Documentation\n\n### Intro\n\nA [`Runtype`](src/runtype.ts#L106) is a function that:\n\n1. receives an unknown value\n2. returns that value or a copy if all validations pass\n3. throws a [`RuntypeError`](src/runtype.ts#L7) when validation fails\n   or returns [`ValidationResult`](src/custom.ts#L37) when passed to [`use`](src/custom.ts#L51)\n\n```typescript\ninterface Runtype\u003cT\u003e {\n  (v: unknown) =\u003e T\n}\n```\n\nRuntypes are constructed by calling factory functions.\nFor instance, [`string`](src/string.ts#L28) creates and returns a string runtype.\nCheck the factory functions documentation for more details.\n\n### Usage Examples\n\n#### Nesting\n\nCollection runtypes such as [`record`](src/record.ts#L141), [`array`](src/array.ts#L28), and [`tuple`](src/tuple.ts#L42) take runtypes as their parameters:\n\n```typescript\nconst nestedRuntype = st.record({\n  name: st.string(),\n  items: st.array(st.record({ id: st.integer, label: st.string() })),\n})\n\nnestedRuntype({\n  name: 'foo',\n  items: [{ id: 3, label: 'bar' }],\n}) // =\u003e returns the same data\n```\n\n#### Strict Property Checks\n\nWhen using [`record`](src/record.ts#L141), any properties which are not defined in the runtype will cause the runtype to fail:\n\n```typescript\nconst strict = st.record({ name: st.string() })\n\nstrict({ name: 'foo', other: 123 })\n// =\u003e RuntypeError: Unknown attribute 'other'\n```\n\nUsing [`record`](src/record.ts#L141) will keep you safe from any `__proto__` injection or overriding attempts.\n\n#### Ignore Individual Properties\n\nTo ignore individual properties, use [`ignore`](src/ignore.ts#L6), [`unknown`](src/unknown.ts#L6) or [`any`](src/any.ts#L6):\n\n```typescript\nconst strict = st.record({ name: st.string(), other: st.ignore() })\n\nstrict({ name: 'foo', other: 123 })\n// =\u003e {name: foo, other: undefined}\n```\n\n#### Optional Properties\n\nUse the [`optional`](src/optional.ts#L18) runtype to create [optional properties](https://www.typescriptlang.org/docs/handbook/interfaces.html#optional-properties):\n\n```typescript\nconst strict = st.record({\n  color: st.optional(st.string()),\n  width: st.optional(st.number()),\n})\n```\n\n#### Non-strict Property Checks\n\nUse [`nonStrict`](src/nonStrict.ts#L16) to only validate known properties and remove everything else:\n\n```typescript\nconst nonStrictRecord = st.nonStrict(st.record({ name: st.string() }))\n\nnonStrictRecord({ name: 'foo', other: 123, bar: [] })\n// =\u003e {name: foo}\n```\n\n#### Discriminating Unions\n\n`simple-runtypes` supports [Discriminating Unions](https://www.typescriptlang.org/docs/handbook/unions-and-intersections.html#discriminating-unions) via the [`union`](src/union.ts#L143) runtype.\n\nThe example found in the [TypeScript Handbook](https://www.typescriptlang.org/docs/handbook/unions-and-intersections.html#discriminating-unions) translated to `simple-runtypes`:\n\n```typescript\nconst networkLoadingState = st.record({\n  state: st.literal('loading'),\n})\n\nconst networkFailedState = st.record({\n  state: st.literal('failed'),\n  code: st.number(),\n})\n\nconst networkSuccessState = st.record({\n  state: st.literal('success'),\n  response: st.record({\n    title: st.string(),\n    duration: st.number(),\n    summary: st.string(),\n  }),\n})\n\nconst networdStateRuntype = st.union(\n  networkLoadingState,\n  networkFailedState,\n  networkSuccessState,\n)\n\ntype NetworkState = ReturnType\u003ctypeof networkStateRuntype\u003e\n```\n\nFinding the runtype to validate a specific discriminating union with is done efficiently with a [`Map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map).\n\n#### Custom Runtypes\n\nWrite your own runtypes as plain functions, e.g. if you want to turn a string into a `BigInt`:\n\n```typescript\nconst bigIntStringRuntype = st.string({ match: /^-?[0-9]+n$/ })\n\nconst bigIntRuntype = st.runtype((v) =\u003e {\n  const stringCheck = st.use(bigIntStringRuntype, v)\n\n  if (!stringCheck.ok) {\n    return stringCheck.error\n  }\n\n  return BigInt(stringCheck.result.slice(0, -1))\n})\n\nbigIntRuntype('123n') // =\u003e 123n\nbigIntRuntype('2.2') // =\u003e error: \"expected string to match ...\"\n```\n\n### Reference\n\nBasic runtypes that match JavaScript/TypeScript types:\n\n- [`number`](src/number.ts#L13)\n- [`string`](src/string.ts#L28)\n- [`boolean`](src/boolean.ts#L14)\n- [`null`](src/null.ts#6)\n- [`undefined`](src/undefined.ts#7)\n- [`enum`](src/enum.ts#9)\n- [`literal`](src/literal.ts#L10)\n\nMeta runtypes:\n\n- [`integer`](src/integer.ts#L26)\n- [`stringAsInteger`](src/stringAsInteger.ts#L62)\n- [`ignore`](src/ignore.ts#L6)\n- [`unknown`](src/unknown.ts#L6)\n- [`any`](src/any.ts#L6)\n- [`json`](src/json.ts#L27)\n\nObjects and Array Runtypes:\n\n- [`tuple`](src/tuple.ts#L42)\n- [`array`](src/array.ts#L28)\n- [`record`](src/record.ts#L141)\n  - [`optional`](src/optional.ts#L18)\n- [`dictionary`](src/dictionary.ts#L87)\n\nCombinators:\n\n- [`union`](src/union.ts#L143)\n- [`intersection`](src/intersection.ts#L110)\n- [`omit`](src/omit.ts#L8)\n- [`pick`](src/pick.ts#L7)\n- [`partial`](src/partial.ts#L10)\n- [`nonStrict`](src/nonStrict.ts#L16)\n- TODO: `get` - similar to Type[key]\n\nShortcuts:\n\n- [`nullOr`](src/nullOr.ts#L11)\n- [`undefinedOr`](src/undefinedOr.ts#L11)\n\n### Roadmap / Todos\n\n- `size` - a meta-runtype that imposes a size limit on types, maybe via convert-to-json and .length on the value passed to it\n- rename [`stringLiteralUnion`](src/stringLiteralUnion.ts#L6) to `literals` or `literalUnion` and make it work\n  on all types that [`literal`](src/literal.ts#L10) accepts\n- rename record to object: [#69](https://github.com/hoeck/simple-runtypes/issues/69)\n- improve docs:\n  - _preface_: what is a runtype and why is it useful\n  - _why_: explain or link to example that shows \"strict by default\"\n  - show that `simple-runtypes` is feature complete because it can\n    1. express all TypeScript types\n    2. is extendable with custom runtypes (add documentation)\n  - add small frontend and backend example projects that show how to use `simple-runtypes` in production\n- test _all_ types with [tsd](https://github.com/SamVerschueren/tsd)\n- add more combinators: partial, required, get, ...\n- separate [`Runtype`](src/runtype.ts#L106) and [`InternalRuntype`](src/runtype.ts#L171) and type runtype internals\n  (see [this comment](https://github.com/hoeck/simple-runtypes/pull/73#discussion_r948841977))\n\n#### current tasks (metadata) notes\n\n- check that intersection \u0026 union tests do properly test the distribution stuff\n- make getMetadata public\n- maybe make metadata typed and include all options so that you can walk the tree to create testdata orjson-schemas from types\n- maybe add a `serialize` function to each runtype too? to use instead of JSON.stringify and to provide a full-service library?\n- maybe make `any` a forbidden type of a runtype\n","funding_links":[],"categories":["others"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhoeck%2Fsimple-runtypes","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhoeck%2Fsimple-runtypes","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhoeck%2Fsimple-runtypes/lists"}