Security News
GitHub Removes Malicious Pull Requests Targeting Open Source Repositories
GitHub removed 27 malicious pull requests attempting to inject harmful code across multiple open source repositories, in another round of low-effort attacks.
Runtypes is a TypeScript library that provides runtime validation and type checking for JavaScript objects. It allows developers to define types and validate data against those types at runtime, ensuring that the data conforms to the expected structure and types.
Basic Type Validation
Runtypes allows you to define basic types like String and Number and validate data against these types. If the data does not match the expected type, an error is thrown.
const { String, Number } = require('runtypes');
const Name = String;
const Age = Number;
Name.check('John Doe'); // Passes
Age.check(30); // Passes
// Name.check(123); // Throws an error
// Age.check('30'); // Throws an error
Object Validation
Runtypes allows you to define complex types like objects and validate data against these types. You can specify the structure of the object and the types of its properties.
const { Record, String, Number } = require('runtypes');
const Person = Record({
name: String,
age: Number
});
Person.check({ name: 'John Doe', age: 30 }); // Passes
// Person.check({ name: 'John Doe', age: '30' }); // Throws an error
Union Types
Runtypes supports union types, allowing you to define a type that can be one of several types. This is useful for validating data that can have multiple valid types.
const { Union, String, Number } = require('runtypes');
const StringOrNumber = Union(String, Number);
StringOrNumber.check('Hello'); // Passes
StringOrNumber.check(123); // Passes
// StringOrNumber.check(true); // Throws an error
Array Validation
Runtypes allows you to define array types and validate data against these types. You can specify the type of the elements in the array.
const { Array, String } = require('runtypes');
const StringArray = Array(String);
StringArray.check(['Hello', 'World']); // Passes
// StringArray.check(['Hello', 123]); // Throws an error
Optional Properties
Runtypes allows you to define optional properties in objects. This is useful for validating data where some properties may or may not be present.
const { Record, String, Number, Optional } = require('runtypes');
const Person = Record({
name: String,
age: Optional(Number)
});
Person.check({ name: 'John Doe' }); // Passes
Person.check({ name: 'John Doe', age: 30 }); // Passes
// Person.check({ name: 'John Doe', age: '30' }); // Throws an error
io-ts is a runtime type system for IO decoding/encoding in TypeScript. It provides similar functionality to runtypes, allowing you to define types and validate data at runtime. However, io-ts has a more functional programming approach and integrates well with fp-ts.
Zod is a TypeScript-first schema declaration and validation library. It provides a similar feature set to runtypes, allowing you to define schemas and validate data at runtime. Zod is known for its simplicity and ease of use.
Yup is a JavaScript schema builder for value parsing and validation. It is similar to runtypes in that it allows you to define schemas and validate data. Yup is widely used in the React ecosystem, especially with form libraries like Formik.
Runtypes is a JavaScript and TypeScript library which allows you to take values about which you have no assurances and ensure
that they conform to some type A
. This is done by means of composable type validators of primitives, literals, arrays,
tuples, records, unions. Better yet, it has TypeScript bindings which allow exactly expressing the validated results in a type-safe
manner.
npm install --save runtypes
For example, suppose you have objects which represent asteroids, planets, ships and personnel. In TypeScript, you might model them like so:
type Coordinates = [number, number, number]
interface Asteroid {
type: 'asteroid'
coordinates: Coordinates
mass: number
}
interface Planet {
type: 'planet'
coordinates: Coordinates
mass: number
population: number
habitable: boolean
}
type Rank
= 'captain'
| 'first mate'
| 'officer'
| 'ensign'
interface CrewMember {
name: string
age: number
rank: Rank
home: Planet
}
interface Ship {
type: 'ship'
coordinates: Coordinates
mass: number
name: string
crew: CrewMember[]
}
type SpaceObject = Asteroid | Planet | Ship
If the objects which are supposed to have these shapes are loaded from some external source, perhaps a JSON file, we need to
validate that the objects conform to their specifications. We do so by building corresponding Runtype
s in a very straightforward
manner:
const Coordinates: Runtype<Coordinates> = tuple(number, number, number)
const Asteroid: Runtype<Asteroid> = record({
type: literal('asteroid'),
coordinates: Coordinates,
mass: number,
})
const Planet: Runtype<Planet> = record({
type: literal('planet'),
coordinates: Coordinates,
mass: number,
population: number,
habitable: boolean,
})
const Rank: Runtype<Rank> = union(
literal('captain'),
literal('first mate'),
literal('officer'),
literal('ensign'),
)
const CrewMember: Runtype<CrewMember> = record({
name: string,
age: number,
rank: Rank,
home: Planet,
})
const Ship: Runtype<Ship> = record({
type: literal('ship'),
coordinates: Coordinates,
mass: number,
name: string,
crew: array(CrewMember),
})
const SpaceObject: Runtype<SpaceObject> = union(Asteroid, Planet, Ship)
Now if we are given a putative SpaceObject
we can validate it like so:
const spaceObject: SpaceObject = SpaceObject.coerce(obj)
If the object doesn't conform to the type specification, coerce
will throw an exception.
It's worth pointing out that all of the type annotations above are optional in TypeScript; the correct type parameter
for the composed Runtype
will be inferred if you leave them off. In fact, you can skip writing out the TypeScript
types altogether and instead derive them from the Runtype
s like so:
const Coordinates = tuple(number, number, number)
type Coordinates = typeof Coordinates.falseWitness
const Asteroid = record({
type: literal('asteroid'),
coordinates: Coordinates,
mass: number,
})
type Asteroid = typeof Asteroid.falseWitness
const Planet = record({
type: literal('planet'),
coordinates: Coordinates,
mass: number,
population: number,
habitable: boolean,
})
type Planet = typeof Planet.falseWitness
const Rank = union(
literal('captain'),
literal('first mate'),
literal('officer'),
literal('ensign'),
)
type Rank = typeof Rank.falseWitness
const CrewMember = record({
name: string,
age: number,
rank: Rank,
home: Planet,
})
type CrewMember = typeof CrewMember.falseWitness
const Ship = record({
type: literal('ship'),
coordinates: Coordinates,
mass: number,
name: string,
crew: array(CrewMember),
})
type Ship = typeof Ship.falseWitness
const SpaceObject = union(Asteroid, Planet, Ship)
type SpaceObject = typeof SpaceObject.falseWitness
For a given r: Runtype<A>
, r.falseWitness: A
is always undefined
in reality, so never try to treat it as an actual A
. Even though
it's a lie, it's useful because we can apply the typeof
operator to it in order to obtain the derived type A
. This trick obviates the
need to repeat our type definitions at both the value and the type level. Nifty!
In addition to coercion, runtypes can be used as type guards:
function disembark(obj: {}) {
if (SpaceObject.guard(obj)) {
// obj: SpaceObject
if (obj.type === 'ship) {
// obj: Ship
obj.crew = []
}
}
}
FAQs
Runtime validation for static types
The npm package runtypes receives a total of 195,998 weekly downloads. As such, runtypes popularity was classified as popular.
We found that runtypes demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
GitHub removed 27 malicious pull requests attempting to inject harmful code across multiple open source repositories, in another round of low-effort attacks.
Security News
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.
Security News
Node.js will be enforcing stricter semver-major PR policies a month before major releases to enhance stability and ensure reliable release candidates.