gen-typed-validators v1.1.5
gen-typed-validators
Automatically generate runtime validators from your Flow or TypeScript type definitions! (using typed-validators)
Table of Contents
How it works
Say you want to generate validators for a User type. Just add a const UserType: t.TypeAlias<User> = null declaration
after it and run this codemod:
// User.ts
export type Address = {
line1: string
line2?: string
city: string
zipCode: string
}
export type User = {
email: string
firstName?: string
lastName?: string
address?: Address
}
export const UserType: t.TypeAlias<User> = null$ gen-typed-validators User.ts
/Users/andy/github/typed-validators-codemods/User.ts
======================================
+ modified - original
@@ -1,15 +1,44 @@
+import * as t from 'typed-validators'
export type Address = {
line1: string
line2?: string
city: string
zipCode: string
}
+export const AddressType: t.TypeAlias<Address> = t.alias(
+ 'Address',
+ t.object({
+ required: {
+ line1: t.string(),
+ city: t.string(),
+ zipCode: t.string(),
+ },
+
+ optional: {
+ line2: t.string(),
+ },
+ })
+)
+
export type User = {
email: string
firstName?: string
lastName?: string
address?: Address
}
-export const UserType: t.TypeAlias<User> = null
+export const UserType: t.TypeAlias<User> = t.alias(
+ 'User',
+ t.object({
+ required: {
+ email: t.string(),
+ },
+
+ optional: {
+ firstName: t.string(),
+ lastName: t.string(),
+ address: t.ref(() => AddressType),
+ },
+ })
+)
? write: (y/N)Type Walking
Notice that the above example also creates an AddressType validator for the Address type, since Address is used in the User type. gen-typed-validators will walk all the dependent
types, even if they're imported. For example:
// Address.ts
export type Address = {
line1: string
line2?: string
city: string
zipCode: string
}
// User.ts
import { Address } from './Address'
export type User = {
email: string
firstName?: string
lastName?: string
address?: Address
}
export const UserType: t.TypeAlias<User> = null$ gen-typed-validators User.ts
/Users/andy/github/typed-validators-codemods/Address.ts
======================================
+ modified - original
@@ -1,6 +1,22 @@
+import * as t from 'typed-validators'
export type Address = {
line1: string
line2?: string
city: string
zipCode: string
}
+
+export const AddressType: t.TypeAlias<Address> = t.alias(
+ 'Address',
+ t.object({
+ required: {
+ line1: t.string(),
+ city: t.string(),
+ zipCode: t.string(),
+ },
+
+ optional: {
+ line2: t.string(),
+ },
+ })
+)
/Users/andy/github/typed-validators-codemods/User.ts
======================================
+ modified - original
@@ -1,10 +1,25 @@
-import { Address } from './Address'
+import { Address, AddressType } from './Address'
+import * as t from 'typed-validators'
+
export type User = {
email: string
firstName?: string
lastName?: string
address?: Address
}
-export const UserType: t.TypeAlias<User> = null
+export const UserType: t.TypeAlias<User> = t.alias(
+ 'User',
+ t.object({
+ required: {
+ email: t.string(),
+ },
+
+ optional: {
+ firstName: t.string(),
+ lastName: t.string(),
+ address: t.ref(() => AddressType),
+ },
+ })
+)
? write: (y/N)Limitations
- This codemod currently doesn't preserve formatting, though if it finds
prettierinstalled in your project, it will format the generated code usingprettier. Definitely not all types are supported. The goal will always be to support a subset of types that can be reliably validated at runtime.
Supported types:
- All primitive values
anyunknown/mixed- Arrays
- Tuples
- Unions (
|) - Intersections (
&) - Objects or interfaces without indexers or methods
- Flow exception: only a single indexer, to indicate a record type (
{ [string]: number }) - TS execption: indexers to allow additional properties
{ foo: number, [string]: any }{ foo: number, [string]: unknown }{ foo: number, [string | symbol]: any }{ foo: number, [string | symbol]: unknown }{ foo: number, [any]: any }{ foo: number, [any]: unknown }
- Flow exception: only a single indexer, to indicate a record type (
- TS
Recordtypes - Interface
extends - Flow exact and inexact object types
- Flow object type spread
{| foo: number, ...Bar |},{ foo: number, ...$Exact<Bar>, ... } - Class instance types
- Type aliases
- Readonly types are converted as-is (but not enforced at runtime, since readonly is strictly a compile-time hint):
- TS
readonly - Flow
$ReadOnly - Flow
$ReadOnlyArray
- TS
Right now the generated validator name is
${typeName}Typeand this isn't customizable. In the future I could change it to infer from the starting validator declaration(s).- Imports from
node_modulesaren't currently supported. It may be possible in the future when a package already contains generated validators, and it can find them along with the types in.d.tsor.js.flowfiles.
CLI
gen-typed-validators <files>
Options:
--version Show version number [boolean]
-q, --quiet reduce output [boolean]
-w, --write write without asking for confirmation [boolean]
-c, --check check that all validators match types [boolean]
--help Show help [boolean]Without the -w or -c option, it will print a diff for any changes it would make, and ask if you want to write the changes.