reflect-types
v2.0.0
Published
Type combinators for JavaScript/TypeScript at runtime
Downloads
5
Maintainers
Readme
Reflect Types
Reflect types allows you to work with types both at compile time and at runtime.
Think Zod, but with the useful feature of being able to analyse and traverse the types, not just use them for validation.
⚠️ This library is still under development. Things might not work or might not work as advertised. You have been warned!
Make generic functions truly generic with type information
import { types } from "reflect-types"
function buildEquality<T>(t: Type): boolean {
switch (t.kind) {
case 'string':
return (a,b) => a === b;
case 'vec2':
return (a,b) => a[0] === b[0] && a[1] === b[1];
// and so on ...
}
}
function assoc<K, V>(data: Array<[K,V]>, key: K, k: Type) {
const eq = buildEquality(k);
// ...
}
const data = [
[1, 'one'],
[5, 'five'],
[3, 'three'],
[6, 'six'],
];
const elementType = types.vec2();
assoc(data, 1, elementType); // returns 'one'
Define an object type and validate some data with it
import { types } from "reflect-types"
import { validate } from "reflect-type/lib/validators.js"
const personType = types.object({
id: types.uuid4(),
fullName: types.string(),
email: types.email(),
dateOfBirth: types.date(),
});
const person1 = {
id: '22ba434a-c662-4cc9-8a05-5cf1c7c90fd7',
fullName: 'James Smith',
email: '[email protected]',
dateOfBirth: new Date('8/23/1997'),
}
const [errors, result] = validate(person1, personType);
if (errors.length > 0) {
for (const error of errors) {
console.log(error);
}
return;
}
// Yay! Now, `result` may e.g. be stored in the database.
Inspect a type in order to infer whether it is nullable
import { Type, types } from "reflect-types"
function isNullable(type: Type): boolean {
switch (type.kind) {
case 'literal':
return type.value === null;
case 'nullable':
return true;
case 'optional':
return isNullable(type.type);
case 'object':
case 'array':
case 'string':
case 'boolean':
case 'number':
return false;
default:
assertNever(type);
}
}
const type = fetchSomeTypeSomehow();
console.log(
isNullable(type)
? `The type is nullable.`
: `The type is not nullable.`);
Installation
Just install reflect-types
using your favorite package manager, e.g.:
npm install reflect-types
Reference
Extending the type system
The type system is flexible enough to be extended with user-defined types.
Here is a code snippet that create a new type for RGB-colors.
import { TypeBase } from "reflect-types"
type RGB = [r: number, g: number, b: number];
export class RGBType implements TypeBase {
// Give your type an unique name. Names should be lowercase and use dashes
// when consisting of multiple words.
readonly kind = 'rgb';
// This resolves to the actual TypeScript type of value that is held by this type.
__type!: RGB;
}
declare module "reflect-types" {
interface Types {
rgb: RGBType,
}
}
export function rgb(): RGBType {
return new RGBType();
}
In the code above, we first define a TypeScript type for the values we wish to support, in this case RGB
.
Next, we create the actual class that will represent these values in reflect-types
. Usually these have the suffix Type
.
They implement TypeBase
, a minimal interface that every type should adhere to.
The fields kind
and __type
indicate the tag and the TypeScript type, respectively.
Next, the declare module
-directive ensures that when a user specifies our new type somewhere, it is actually accepted by e.g. types.object()
.
Finally, we create a simple constructor for our type, making the class transparent and avoiding the use of new
.
License
This project is licensed under the MIT license. See LICENSE.txt
for more information.