# @anglinb/ts-to-zod

> Generate zod schemas from typescript types/interfaces

Latest version **1.3.2** (published 2021-07-29) · MIT license · 0 weekly downloads

## Install

```sh
npm install @anglinb/ts-to-zod
pnpm add @anglinb/ts-to-zod
yarn add @anglinb/ts-to-zod
bun add @anglinb/ts-to-zod
```

Provides the command `ts-to-zod`.

## Health

**Score 25/100 (F)** — status: abandoned.

Positive: has types; no vulnerabilities; high quality score.

Warnings: low downloads; no esm support.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 1.3.2 |
| Published | 2021-07-29 |
| First published | 2021-07-28 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | CommonJS |
| Dependencies | 20 |
| Unpacked size | 233.8 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Author | Fabien Bernard @fabien0102 |
| Maintainers | anglinb |
| Keywords | zod, typescript, generator, oclif |

## Links

- npm: https://www.npmjs.com/package/@anglinb/ts-to-zod
- Repository: https://github.com/fabien0102/ts-to-zod
- Issues: https://github.com/fabien0102/ts-to-zod/issues
- npm.io page: https://npm.io/package/@anglinb/ts-to-zod

## Dependencies (20)

- [ora](https://npm.io/package/ora.md) ^5.4.0
- [zod](https://npm.io/package/zod.md) ^3.1.0
- [case](https://npm.io/package/case.md) ^1.6.3
- [rxjs](https://npm.io/package/rxjs.md) ^6.6.7
- [async](https://npm.io/package/async.md) ^3.2.0
- [slash](https://npm.io/package/slash.md) ^3.0.0
- [tslib](https://npm.io/package/tslib.md) ^2.1.0
- [lodash](https://npm.io/package/lodash.md) ^4.17.21
- [threads](https://npm.io/package/threads.md) ^1.6.3
- [tsutils](https://npm.io/package/tsutils.md) ^3.21.0
- [chokidar](https://npm.io/package/chokidar.md) ^3.5.1
- [fs-extra](https://npm.io/package/fs-extra.md) ^9.1.0
- [inquirer](https://npm.io/package/inquirer.md) ^8.0.0
- [prettier](https://npm.io/package/prettier.md) ^2.2.1
- [lz-string](https://npm.io/package/lz-string.md) ^1.4.4
- [typescript](https://npm.io/package/typescript.md) 4.2.3
- [@oclif/config](https://npm.io/package/@oclif/config.md) ^1.17.0
- [@oclif/command](https://npm.io/package/@oclif/command.md) ^1.8.0
- [@typescript/vfs](https://npm.io/package/@typescript/vfs.md) ^1.3.4
- [@oclif/plugin-help](https://npm.io/package/@oclif/plugin-help.md) ^3.2.2

## Alternatives

- [@salesforce/cli](https://npm.io/package/@salesforce/cli.md) — 389.7K weekly downloads
- [@mintlify/cli](https://npm.io/package/@mintlify/cli.md) — 208.9K weekly downloads
- [@grafana/e2e-selectors](https://npm.io/package/@grafana/e2e-selectors.md) — 128.7K weekly downloads
- [mintlify](https://npm.io/package/mintlify.md) — 112.0K weekly downloads
- [@intlayer/cli](https://npm.io/package/@intlayer/cli.md) — 22.8K weekly downloads

## Recent versions

- 1.3.2 (latest) — 2021-07-29
- 1.3.1 — 2021-07-28

## README

<div align="center">
  <img src="ts-to-zod-logo.svg" width="200px" align="center" />
  <h1 align="center">ts-to-zod</h1>
</div>

Generate [Zod](https://github.com/colinhacks/zod) schemas (v3) from Typescript types/interfaces.

[![Version](https://img.shields.io/npm/v/ts-to-zod.svg)](https://npmjs.org/package/ts-to-zod)
[![Github CI](https://github.com/fabien0102/ts-to-zod/actions/workflows/tests.yaml/badge.svg)](https://github.com/fabien0102/ts-to-zod/actions/workflows/tests.yaml)
[![codecov](https://codecov.io/gh/fabien0102/ts-to-zod/branch/main/graph/badge.svg?token=W5M8UIJ59C)](https://codecov.io/gh/fabien0102/ts-to-zod)
[![License](https://img.shields.io/npm/l/ts-to-zod.svg)](https://github.com/fabien0102/ts-to-zod/blob/main/LICENSE)
[![oclif](https://img.shields.io/badge/cli-oclif-brightgreen.svg)](https://oclif.io)

## Usage

```sh
$ yarn add --dev ts-to-zod
$ yarn ts-to-zod src/iDontTrustThisApi.ts src/nowIcanValidateEverything.ts
```

That's it, go to `src/nowIcanValidateEverything.ts` file, you should have all the exported `interface` and `type` as Zod schemas with the following name pattern: `${originalType}Schema`.

Note: The generated zod schemas have `zod@next` as dependency.

## Embedded validation

To make sure the generated zod schemas are 100% compatible with your original types, this tool is internally comparing `z.infer<generatedSchema>` and your original type. If you are running on those validation, please open an issue 😀

Notes:

- Only exported types/interface are tested (so you can have some private types/interface and just exports the composed type)
- Even if this is not recommanded, you can skip this validation step with `--skipValidation`. (At your own risk!)

## Validators

This tool supports some JSDoc tags inspired from openapi to generate zod validator.

List of supported keywords:

| JSDoc keyword                      | JSDoc Example     | Generated Zod validator      |
| ---------------------------------- | ----------------- | ---------------------------- |
| `@minimum {number}`                | `@minimum 42`     | `z.number().min(42)`         |
| `@maximum {number}`                | `@maximum 42`     | `z.number().max(42)`         |
| `@minLength {number}`              | `@minLength 42`   | `z.string().min(42)`         |
| `@maxLength {number}`              | `@maxLength 42`   | `z.string().min(42)`         |
| `@format {"email"\|"uuid"\|"url"}` | `@format email`   | `z.string().email()`         |
| `@pattern {regex}`                 | `@pattern ^hello` | `z.string().regex(/^hello/)` |

Those JSDoc tags can also be combined:

```ts
// source.ts
export interface HeroContact {
  /**
   * The email of the hero.
   *
   * @format email
   */
  email: string;

  /**
   * The name of the hero.
   *
   * @minLength 2
   * @maxLength 50
   */
  name: string;

  /**
   * The phone number of the hero.
   *
   * @pattern ^([+]?d{1,2}[-s]?|)d{3}[-s]?d{3}[-s]?d{4}$
   */
  phoneNumber: string;

  /**
   * Does the hero has super power?
   *
   * @default true
   */
  hasSuperPower?: boolean;

  /**
   * The age of the hero
   *
   * @minimum 0
   * @maximum 500
   */
  age: number;
}

// output.ts
export const heroContactSchema = z.object({
  /**
   * The email of the hero.
   *
   * @format email
   */
  email: z.string().email(),

  /**
   * The name of the hero.
   *
   * @minLength 2
   * @maxLength 50
   */
  name: z.string().min(2).max(50),

  /**
   * The phone number of the hero.
   *
   * @pattern ^([+]?d{1,2}[-s]?|)d{3}[-s]?d{3}[-s]?d{4}$
   */
  phoneNumber: z.string().regex(/^([+]?d{1,2}[-s]?|)d{3}[-s]?d{3}[-s]?d{4}$/),

  /**
   * Does the hero has super power?
   *
   * @default true
   */
  hasSuperPower: z.boolean().default(true),

  /**
   * The age of the hero
   *
   * @minimum 0
   * @maximum 500
   */
  age: z.number().min(0).max(500),
});
```

## Advanced configuration

If you want to customized the schema name or restrict the exported schemas, you can do this by adding a `ts-to-zod.config.js` at the root of your project.

Just run `yarn ts-to-zod --init` and you will have a ready to use configuration file (with a bit of typesafety).

## Limitation

Since we are generating Zod schemas, we are limited by what Zod actually supports:

- No type generics
- No complex circular dependencies (you will be warn if you have some in your types)
- No `Record<number, …>`
- …

To resume, you can use all the primitive types and some the following typescript helpers:

- `Record<string, …>`
- `Pick<>`
- `Omit<>`
- `Partial<>`
- `Required<>`
- `Array<>`
- `Promise<>`

This utils is design to work with one file only, and will reference types from the same file:

```ts
// source.ts
export type Id = string;
export interface Hero {
  id: Id;
  name: string;
}

// output.ts
export const idSchema = z.string();
export const heroSchema = z.object({
  id: idSchema,
  name: z.string(),
});
```

## Programmatic API

You need more than one file? Want even more power? No problem, just use the tool as a library.

High-level function:

- `generate` take a `sourceText` and generate two file getters

Please have a look to `src/core/generate.test.ts` for more examples.

Low-level functions:

- `generateZodSchema` help you to generate `export const ${varName} = ${zodImportValue}.object(…)`
- `generateZodInferredType` help you to generate `export type ${aliasName} = ${zodImportValue}.infer<typeof ${zodConstName}>`
- `generateIntegrationTests` help you to generate a file comparing the original types & zod types

To learn more about thoses functions or their usages, `src/core/generate.ts` is a good starting point.

## Local development

```sh
$ git clone
$ cd ts-to-zod
$ yarn
$ ./bin/run
USAGE
  $ ts-to-zod [input] [output]
  ...
```

You also have plenty of unit tests to play safely:

```sh
$ yarn test --watch
```

And a playground inside `example`, buildable with the following command:

```sh
$ yarn gen:example
```

Last note, if you are updating `src/config.ts`, you need to run `yarn gen:config` to have generate the schemas of the config (`src/config.zod.ts`) (Yes, we are using the tool to build itself #inception)

Have fun!

---
_Source: https://npm.io/package/@anglinb/ts-to-zod · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
