Home

Awesome

gen-typed-validators

CircleCI Coverage Status semantic-release Commitizen friendly npm version

Automatically generate runtime validators from your Flow or TypeScript type definitions! (using typed-validators)

Table of Contents

<!-- toc --> <!-- tocstop -->

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

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.