npm package: @schemashift/io-ts-zod
Description: io-ts to Zod transformer for SchemaShift — converts io-ts codecs and types to Zod schemas
Author: Joseph May
Latest version: 0.14.0

# @schemashift/io-ts-zod

io-ts → Zod transformer for SchemaShift. Converts io-ts type definitions and codecs to Zod schemas with AST-based transformations.

[![npm version](https://img.shields.io/npm/v/@schemashift/io-ts-zod.svg)](https://www.npmjs.com/package/@schemashift/io-ts-zod)
[![npm downloads](https://img.shields.io/npm/dm/@schemashift/io-ts-zod.svg)](https://www.npmjs.com/package/@schemashift/io-ts-zod)
[![CI](https://github.com/jdmay2/schemashift/actions/workflows/ci.yml/badge.svg)](https://github.com/jdmay2/schemashift/actions/workflows/ci.yml)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)

**Tier:** Pro

## Installation

```bash
npm install @schemashift/io-ts-zod
```

## Usage

```typescript
import { createIoTsToZodHandler } from '@schemashift/io-ts-zod';
import { TransformEngine } from '@schemashift/core';

const engine = new TransformEngine();
engine.registerHandler('io-ts', 'zod', createIoTsToZodHandler());
```

## Transformation Mappings

### Imports

| io-ts | Zod |
|-------|-----|
| `import * as t from 'io-ts'` | `import { z } from 'zod'` |
| `import t from 'io-ts'` | `import { z } from 'zod'` |

### Primitive Types (Property Access)

io-ts primitives are accessed as properties without parentheses. They are converted to Zod function calls:

| io-ts | Zod |
|-------|-----|
| `t.string` | `z.string()` |
| `t.number` | `z.number()` |
| `t.boolean` | `z.boolean()` |
| `t.null` | `z.null()` |
| `t.undefined` | `z.undefined()` |
| `t.void` | `z.void()` |
| `t.unknown` | `z.unknown()` |
| `t.any` | `z.any()` |
| `t.never` | `z.never()` |
| `t.Int` | `z.number().int()` |
| `t.Integer` | `z.number().int()` |

### Composite Types (Call Expressions)

| io-ts | Zod |
|-------|-----|
| `t.type({...})` | `z.object({...})` |
| `t.partial({...})` | `z.object({...}).partial()` |
| `t.strict({...})` | `z.object({...})` |
| `t.exact({...})` | `z.object({...})` |
| `t.array(schema)` | `z.array(schema)` |
| `t.readonlyArray(schema)` | `z.array(schema)` |
| `t.record(key, value)` | `z.record(key, value)` |
| `t.tuple([a, b])` | `z.tuple([a, b])` |
| `t.union([a, b])` | `z.union([a, b])` |
| `t.intersection(a, b)` | `z.intersection(a, b)` |
| `t.literal(value)` | `z.literal(value)` |
| `t.keyof({...})` | `z.enum(Object.keys({...}))` |
| `t.refinement(schema, pred)` | `z.refine(schema, pred)` |
| `t.readonly(schema)` | `z.readonly(schema)` |

### Type Helpers

| io-ts | Zod |
|-------|-----|
| `t.TypeOf<typeof schema>` | `z.infer<typeof schema>` |
| `t.OutputOf<typeof schema>` | `z.output<typeof schema>` |

## Patterns Requiring Manual Review

io-ts uses fundamentally different patterns (Either monads, bidirectional codecs, fp-ts integration) that cannot be automatically converted 1:1. The transformer generates actionable warnings for these patterns.

### Either Monad Handling

```typescript
// io-ts
import { isRight } from 'fp-ts/Either';
const result = UserCodec.decode(data);
if (isRight(result)) {
  const user = result.right;
}

// Zod (manual conversion)
const result = UserSchema.safeParse(data);
if (result.success) {
  const user = result.data;
}
```

### Codec Encode/Decode

```typescript
// io-ts — bidirectional codec
const DateCodec = new t.Type<Date, string>(
  'Date',
  (u): u is Date => u instanceof Date,
  (u, c) => /* decode */,
  (date) => date.toISOString() // encode
);

// Zod — parse only, encoding is separate
// TODO(schemashift): Replace .decode()/.encode() with z.parse()/z.safeParse().
// Encoding must be handled separately.
```

### Branded Types

```typescript
// io-ts
interface PositiveBrand { readonly Positive: unique symbol }
type Positive = t.Branded<number, PositiveBrand>;

// Zod (manual conversion)
const Positive = z.number().positive().brand<'Positive'>();
```

### fp-ts Imports

The transformer warns about fp-ts imports (Either, pipe, fold) that need conversion to standard try/catch or `.safeParse()` patterns.

## Related Packages

- [schemashift-cli](https://www.npmjs.com/package/schemashift-cli) — CLI tool for running migrations
- [@schemashift/core](https://www.npmjs.com/package/@schemashift/core) — Core analysis engine
- [@schemashift/io-ts-effect](https://www.npmjs.com/package/@schemashift/io-ts-effect) — Alternative: io-ts → Effect Schema

## License

MIT