Gathering detailed insights and metrics for runcheck
Gathering detailed insights and metrics for runcheck
Gathering detailed insights and metrics for runcheck
Gathering detailed insights and metrics for runcheck
npm install runcheck
Typescript
Module System
Min. Node Version
Node Version
NPM Version
TypeScript (97.76%)
JavaScript (2.2%)
Shell (0.04%)
Total Downloads
0
Last Day
0
Last Week
0
Last Month
0
Last Year
0
2 Stars
335 Commits
1 Watchers
4 Branches
1 Contributors
Updated on Jul 08, 2025
Latest Version
1.12.0
Package Id
runcheck@1.12.0
Unpacked Size
329.01 kB
Size
79.09 kB
File Count
16
NPM Version
10.9.2
Node Version
23.4.0
Published on
Jul 08, 2025
Cumulative downloads
Total Downloads
Last Day
0%
NaN
Compared to previous day
Last Week
0%
NaN
Compared to previous week
Last Month
0%
NaN
Compared to previous month
Last Year
0%
NaN
Compared to previous year
A lib for js/typescript runtime type checks with autofix support. Runcheck has the goal of being very lightweight and fast ⚡. Because of that, it has only around 2.9kb Gzipped (at v0.30), has no dependencies and is tree-shakeable!
Obs: Runcheck is in Beta and it's api can still change
One of the goals of runcheck is to be blazing fast. Here are some benchmarks:
runcheck dist
is the same version asruncheck
in the benchmarks but bundled
1pnpm add runcheck
runcheck type | ts type equivalent |
---|---|
rc_string | string |
rc_number | number |
rc_boolean | boolean |
rc_any | any |
rc_null | null |
rc_undefined | undefined |
rc_date | Date |
rc_intanceof(instance: T) | Classes typecheck in general |
rc_literals(...literals: T[]) | Type literal in general like hello , true , 1 |
rc_union(...types: T[]) | Union types in general like string | 1 |
rc_array<T>(type: T) | T[] |
rc_tuple<T>(...types: T[]) | [T, T] |
rc_intersection(...types: T[]) | Intersection types like {a:string} & {b:string} |
You can also use rc_loose_array
to reject the wrong elements of an array and return the valid ones.
1const shape = rc_loose_array(rc_string) 2 3const input = ['hello', 1, 'world'] 4 5const result = rc_parse(input, shape) 6 7// result.data will be ['hello', 'world'] 8// result.warnings will return the warnings about the invalid elements
With the rc_array
or rc_loose_array
type you can also use the unique
option to check if the array has no duplicated values.
1const shape = rc_array(rc_string, { unique: true })
For arrays of objects, you can provide a string to unique
option to check if the array items has no duplicated values of a specific property.
1const shape = rc_array(rc_object({ id: rc_string }), { unique: 'id' })
You can also provide a function to unique
option to check if the array items has no duplicated values based on a custom function return.
1const shape = rc_array(
2 rc_object({ id: rc_string, meta_id: rc_string.optional() }),
3 {
4 unique: (item) => item.meta_id || item.id,
5 },
6)
rc_object
1const shape = rc_object({
2 name: rc_string,
3 age: rc_number,
4 isCool: rc_boolean,
5 // nested objects
6 address: {
7 street: rc_string,
8 number: rc_number,
9 },
10})
The rc_object
will allow extra properties but, any extra propertie will be striped in parsing. To allow extra in parsing properties, use rc_extends_obj
.
Optional keys can be marked with the optionalKey()
method.
1const shape = rc_object({ 2 name: rc_string.optionalKey(), 3 age: rc_number, 4 isCool: rc_boolean, 5}) 6 7/* 8infered type will be: 9{ 10 name?: string | undefined, 11 age: number, 12 isCool: boolean, 13} 14 15instead of: 16{ 17 name: string | undefined, 18 age: number, 19 isCool: boolean, 20} 21*/
rc_obj_strict
The same as rc_object
but, any extra properties will be throw an error in parsing.
rc_obj_merge
Allow to merge two rc_object
types. Example:
1const shape = rc_obj_merge(
2 rc_object({
3 name: rc_string,
4 age: rc_number,
5 isCool: rc_boolean,
6 }),
7 rc_object({
8 address: rc_string,
9 phone: rc_string,
10 }),
11)
rc_record
Validates only the values of a object, equivalent to Record<string, T>
in typescript.
1const shape = rc_record(rc_number) 2 3// shape type is `Record<string, number>` 4 5// `rc_record` also accepts the following options: 6const shape = rc_record(rc_number, { 7 checkKey: (key) => key !== 'a', // Check if the key is valid 8 looseCheck: true, // If true, the invalid keys will be striped 9})
rc_loose_record
Validates only the values of a object, equivalent to Record<string, T>
in typescript. But, it will reject invalid keys and return the valid ones.
1const shape = rc_loose_record(rc_number)
1import { rc_parse } from 'runcheck'
2
3const input = JSON.parse(jsonInput)
4
5const parseResult = rc_parse(input, rc_array(rc_string))
6
7if (parseResult.error) {
8 throw new Error(parseResult.errors.join('\n'))
9 // Errors are a array of strings
10}
11
12const result = parseResult.data
13// Do something with result
You can also use rc_parser
to create a reusable parser.
1import { rc_parser } from 'runcheck' 2 3const parser = rc_parser(rc_array(rc_string)) 4 5const parseResult = parser(jsonInput) 6const parseResult2 = parser(jsonInput2)
Use the strict
option to disable autofix and fallback
1const parseResult = rc_parse(
2 input,
3 // fallback will be ignored
4 rc_array(rc_string).withFallback([]),
5 {
6 strict: true,
7 },
8)
Use rc_is_valid
and rc_validator
to do a simple type assertion.
1import { rc_is_valid } from 'runcheck' 2 3const input = JSON.parse(jsonInput) 4 5if (rc_is_valid(input, rc_array(rc_string))) { 6 // input will be inferred by ts as `string[]` 7}
Use rc_assert_is_valid
to do a simple type assertion in a parse result.
1import { rc_assert_is_valid } from 'runcheck'
2
3const input = JSON.parse(jsonInput)
4
5const result = rc_parse(input, rc_array(rc_string))
6
7rc_assert_is_valid(result)
8// will throw an error if the result is invalid, otherwise will narrow the result type to a valid result
You can now use the result methods unwrapOr
and unwrapOrNull
for more convenient loose parsing:
1import { rc_parse } from 'runcheck'
2
3const input = JSON.parse(jsonInput)
4
5// Using unwrapOr method
6const result = rc_parse(input, rc_array(rc_string)).unwrapOr([])
7// will fallback to [] if the input is invalid
8
9// Using unwrapOrNull method
10const result2 = rc_parse(input, rc_array(rc_string)).unwrapOrNull()
11// will fallback to null if the input is invalid
You can use the unwrap()
method directly on the parse result:
1import { rc_parse, RcValidationError } from 'runcheck' 2 3const input = JSON.parse(jsonInput) 4 5try { 6 const result = rc_parse(input, rc_array(rc_string)).unwrap() 7 // result will be the parsed data or throw RcValidationError 8} catch (error) { 9 if (error instanceof RcValidationError) { 10 // handle error 11 } 12}
Values can be autofixed and fallback values can be provided for parsing. The checks will pass but the result will return warnings messages.
1type SuccessResult = { 2 error: false 3 data: T 4 warnings: string[] | false 5}
Use the method rc_[type].withFallback(fallback)
to provide a fallback value if the input is not valid.
1const input = 'hello' 2 3const result = rc_parse(input, rc_string.withFallback('world'))
You can also use rc_[type].autoFix()
to automatically fix the input if it is not valid.
1const input = 1
2
3const result = rc_parse(
4 input,
5 rc_string.autoFix((input) => input.toString()),
6)
There are also some predefined autofixed types that you can import:
1import { rc_string_autofix, rc_boolean_autofix } from 'runcheck/autofixable' 2 3// use like any other type
You can also use rc_[type].where(customCheckFunction)
to perform custom checks.
1const input = 1 2 3const positiveNumberType = rc_number.where((input) => input > 0)
You can use RcInferType<typeof schema>
to infer the types from a schema.
1const schema = rc_object({
2 name: rc_string,
3 age: rc_number,
4 isCool: rc_boolean,
5})
6
7export type Person = RcInferType<typeof schema>
You can also use the RcPrettyInferType<typeof schema>
to get a more readable type.
You can use also modiers like rc_string.optional()
to extend the rc types:
runcheck modifier | ts type equivalent |
---|---|
rc_[type].optional() | T | undefined |
rc_[type].orNull() | T | null |
rc_[type].orNullish() | T | null | undefined |
You can use rc_recursive
to create recursive types. But the types can't be inferred in this case. So you need to provide the type manually.
1type MenuTree = {
2 name: string
3 children: MenuTree[]
4}
5
6// the type should be provided manually to the variable in this case
7const menuTreeSchema: RcType<MenuTree[]> = rc_array(
8 rc_object({
9 name: rc_string,
10 // you can safely autorefence the schema here
11 children: rc_recursive(() => menuTreeSchema),
12 }),
13)
14
15const result = rc_parse(input, menuTreeSchema)
You can use rc_transform
to validate an input and transform it to another data.
1const input = 'hello' 2 3const result = rc_parse( 4 input, 5 rc_transform(rc_string, (input) => input.length), 6)
Use the outputSchema
option to create a type that validates both the input and the output of the transform. So if the input matches the outputSchema
the transform will be ignored.
1const input = 'hello' 2 3const schema = rc_transform(rc_string, (input) => input.length, { 4 outputSchema: rc_number, 5}) 6 7const result = rc_parse(input, schema) 8 9if (result.ok) { 10 // this will be valid too 11 const transformedResult = rc_parse(result.data, schema) 12} 13 14// Be carefull: `outputSchema` will be used only if the input type is invalid 15 16const schema = rc_transform( 17 rc_union(rc_string, rc_number), 18 (input) => String(input).toUperCase(), 19 { 20 // this will be ignored because has an equivalent type to the input 21 outputSchema: rc_string, 22 }, 23) 24 25// use a more strict input type to avoid this 26 27const schema = rc_transform( 28 rc_union(rc_string, rc_number).where((input) => isNotUperCase(input)), 29 (input) => String(input).toUperCase(), 30 { 31 outputSchema: rc_string.where((input) => isUperCase(input)), 32 }, 33)
You may want to create a transformed type which result can be validated with the same schema. For this you can use the rc_narrow
type. Example:
1const stringOrArrayOfStrings = rc_union(rc_string, rc_array(rc_string))
2
3const schema = rc_narrow(stringOrArrayOfStrings, (input) =>
4 Array.isArray(input) ? input : [input],
5)
6
7const result = rc_parse('hello', schema)
8
9if (result.ok) {
10 // the schema can safely be used to validate the result too
11 const transformedResult = rc_parse(result.data, schema)
12}
You can use rc_default
to provide a default value if the input is undefined
.
1const input = {
2 name: 'John',
3}
4
5const result = rc_parse(
6 input,
7 rc_object({
8 name: rc_string,
9 age: rc_default(rc_number, 20),
10 }),
11)
12
13if (result.ok) {
14 result.data.age // = 20
15}
If you need to use default in nullish values you can use rc_nullish_default
.
rc_get_from_key_as_fallback
Allows to rename a key in a object. Example:
1const shape = rc_object({
2 // name will use the value of oldName if name is not present in input
3 // which will rename `oldName` to `name` in the result
4 name: rc_get_from_key_as_fallback('oldName', rc_string),
5 age: rc_number,
6 isCool: rc_boolean,
7})
you can use rc_object
with the normalizeKeysFrom
option to normalize the keys of a object to snake case.
1const shape = rc_object(
2 {
3 name: rc_string,
4 age: rc_number,
5 isCool: rc_boolean,
6 },
7 { normalizeKeysFrom: 'snake_case' },
8)
9
10rc_parse({ name: 'John', age: 20, is_cool: true }, shape) // will not return an error and will normalize the response to { name: 'John', age: 20, isCool: true }
rc_get_obj_schema
Allows to get a subset of a object schema. Example:
1const shape = rc_object({
2 name: rc_string,
3 age: rc_number,
4 isCool: rc_boolean,
5})
6
7const nameSchema = rc_get_obj_schema(shape).name
rc_obj_extends
Don't strip unchecked keys from the result. Example:
1const shape = rc_object({
2 name: rc_string,
3})
4
5const result = rc_parse(
6 { name: 'John', age: 20, is_cool: true },
7 rc_obj_extends(shape),
8)
9
10// keys `age` and `is_cool` will be present in the result
11result.data // { name: 'John', age: 20, is_cool: true }
rc_obj_pick
Allows to pick a subset of a object schema. Example:
1const shape = rc_object({
2 name: rc_string,
3 age: rc_number,
4 isCool: rc_boolean,
5})
6
7const nameSchema = rc_obj_pick(shape, ['name'])
rc_obj_omit
Allows to omit a subset of a object schema. Example:
1const shape = rc_object({
2 name: rc_string,
3 age: rc_number,
4 isCool: rc_boolean,
5})
6
7const baseSchema = rc_obj_omit(shape, ['isCool'])
rc_obj_builder
Creates a rc_object
from a type. This gives better error messages and autocompletion.
1type SchemaType = { 2 level1: { 3 level2: { 4 level3: { 5 level4: { 6 level5: number 7 } 8 } 9 } 10 } 11 optionalObj?: { 12 a: string 13 } 14 objOrNull: null | { 15 a: string 16 } 17 objOrNullish: 18 | null 19 | undefined 20 | { 21 a: string 22 } 23} 24 25const schema = rc_obj_builder<SchemaType>()({ 26 level1: { 27 level2: { 28 level3: { 29 level4: { 30 level5: rc_string, 31 // better error here 32 }, 33 }, 34 }, 35 }, 36 optionalObj: [ 37 'optional', 38 { 39 a: rc_string, 40 // better error here and autocompletion :) 41 }, 42 ], 43 objOrNull: [ 44 'null_or', 45 { 46 a: rc_string, 47 }, 48 ], 49 objOrNullish: [ 50 'nullish_or', 51 { 52 a: rc_string, 53 }, 54 ], 55})
rc_discriminated_union
Creates a discriminated union type with faster check performance compared to rc_union
.
1const networkState = rc_discriminated_union('state', { 2 loading: {}, 3 success: { 4 response: rc_string, 5 }, 6 error: { 7 code: rc_number, 8 }, 9}) 10 11const result = rc_unwrap( 12 rc_parse({ state: 'success', response: 'hello' }, networkState), 13) 14// result will be inferred as: 15// | { state: 'loading' } 16// | { state: 'success', response: string } 17// | { state: 'error', code: number }
rc_array_filter_from_schema
Creates a two passes array validation. The first will validate the items against the filter schema and filter the item. The second will perform the type check against the filtered items.
1const schema = rc_array_filter_from_schema(
2 // 1 validate the items against a filter schema
3 rc_object({
4 deleted: rc_boolean,
5 }),
6 // Then filter the items based on the filter schema result
7 (item) => !item.deleted,
8
9 // 2 validate the filtered items
10 rc_object({
11 value: rc_string,
12 }),
13)
14
15const result = rc_parse(
16 [
17 { deleted: false, value: 'hello' },
18 { deleted: true, value: 'world' },
19 ],
20 schema,
21)
22
23// result.value === [{ value: 'hello' }]
No vulnerabilities found.
No security vulnerabilities found.