@yamaimo-illus/typespec-to-zod v0.8.0
typespec-to-zod
This library is effortlessly converts YAML from TypeSpec into Zod schemas.
Usage
Provide the CLI with the input/output file path and additional options as shown below.
typespec-to-zod -i path/to/openapi.yaml -o path/to/generated.ts -c -p -q -n nullishCommand-line options
The tool supports a variety of command-line options to customize the output:
| Options | Description | Default |
|---|---|---|
-i, --input | Path to the OpenAPI YAML file. | N/A |
-o, --output | Output file path for the generated schema. | N/A |
-c, --components | Flag to generate components. | false |
-p, --paths | Flag to generate paths. | false |
-q, --queries | Flag to generate queries. | false |
-n, --nullable-mode | Set null handling mode: nullish/optional | nullish |
Examples
Supported TypeSpec built-in types
See Built-in types | TypeSpec.
Numeric types
These are the mappings from TypeSpec numeric types to Zod:
| TypeSpec Type | Zod Type Conversion |
|---|---|
| numeric | z.number() |
| integer | z.number() |
| float | z.number() |
| int64 | z.number().int() |
| int32 | z.number().int() |
| int16 | z.number().int() |
| int8 | z.number().int() |
| safeint | z.number().int() |
| uint64 | z.number().int() |
| uint32 | z.number().int() |
| uint16 | z.number().int() |
| uint8 | z.number().int() |
| float32 | z.number() |
| float64 | z.number() |
| decimal | z.number() |
| decimal128 | z.number() |
Example TypeSpec:
model NumericTypes {
numericProperty: numeric;
integerProperty: integer;
floatProperty: float;
int64Property: int64;
int32Property: int32;
int16Property: int16;
int8Property: int8;
safeintProperty: safeint;
uint64Property: uint64;
uint32Property: uint32;
uint16Property: uint16;
uint8Property: uint8;
float32Property: float32;
float64Property: float64;
decimalProperty: decimal;
decimal128Property: decimal128;
}Generated Zod schema:
export const schemaNumericTypes = z.object({
numericProperty: z.number(),
integerProperty: z.number(),
floatProperty: z.number(),
int64Property: z.number().int(),
int32Property: z.number().int(),
int16Property: z.number().int(),
int8Property: z.number().int(),
safeintProperty: z.number().int(),
uint64Property: z.number().int(),
uint32Property: z.number().int(),
uint16Property: z.number().int(),
uint8Property: z.number().int(),
float32Property: z.number(),
float64Property: z.number(),
decimalProperty: z.number(),
decimal128Property: z.number()
})Date and Time types
These types involve conversions that consider date and time formatting:
| TypeSpec Type | Zod Type Conversion |
|---|---|
| plainDate | z.string().date() |
| plainTime | z.string().time() |
| utcDateTime | z.string().datetime() |
| offsetDateTime | z.string().datetime() |
| duration | z.string().duration |
Example TypeSpec:
model DateAndTimeTypes {
plainDateProperty: plainDate;
plainTimeProperty: plainTime;
utcDateTimeProperty: utcDateTime;
offsetDateTimeProperty: offsetDateTime;
durationProperty: duration;
}Generated Zod schema:
export const schemaDateAndTimeTypes = z.object({
plainDateProperty: z.string().date(),
plainTimeProperty: z.string().time(),
utcDateTimeProperty: z.string().datetime(),
offsetDateTimeProperty: z.string().datetime(),
durationProperty: z.string().duration()
})Other core types
These are additional core types and their mappings:
| TypeSpec Type | Zod Type Conversion |
|---|---|
| bytes | Not supported but it generated as z.string() |
| string | z.string() |
| boolean | z.boolean() |
| null | z.unknown() |
| Array\<Element> | z.array(z.Element()) |
| Record\<Element> | Not supported but it generated as z.object({}) |
| unknown | z.unknown() |
| void | NOT SUPPORTED |
| never | NOT SUPPORTED |
Example TypeSpec:
model OtherCoreTypes {
bytesProperty: bytes;
stringProperty: string;
booleanProperty: boolean;
nullProperty: null;
ArrayProperty: numeric[];
recordProperty: Record<numeric>;
unknownProperty: unknown;
// voidProperty: void; Not Supported
// neverProperty: never; Not Supported
}Generated Zod schema:
export const schemaOtherCoreTypes = z.object({
bytesProperty: z.string(),
stringProperty: z.string(),
booleanProperty: z.boolean(),
nullProperty: z.unknown(),
ArrayProperty: z.array(z.number()),
recordProperty: z.record(z.string(), z.number()),
unknownProperty: z.unknown()
})String types
The tool also supports string-specific types and their conversions:
| TypeSpec Type | Zod Type Conversion |
|---|---|
| url | z.string().url() |
Example TypeSpec:
model StringTypes {
urlProperty: url;
}Generated Zod schema:
export const schemaStringTypes = z.object({
urlProperty: z.string().url()
})Supported TypeSpec Decorators
These decorators in TypeSpec can be converted to specific constraints in Zod schemas:
| TypeSpec Decorator | Zod Type Conversion |
|---|---|
| @minItems() | .min() |
| @maxItems() | .max() |
| @minLength() | .min() |
| @maxLength() | .max() |
| @minValue() | .gte() |
| @maxValue() | .lte() |
| @exclusiveMinimum() | .gt() |
| @exclusiveMaximum() | .lt() |
Example TypeSpec:
model TypeSpecDecorators {
@minItems(1)
@maxItems(5)
items: string[];
@minLength(1)
@maxLength(5)
name: string;
@minValue(1)
@maxValue(5)
age: int16;
@minValueExclusive(1)
@maxValueExclusive(5)
count: int16;
}Generated Zod schema:
export const schemaTypeSpecDecorators = z.object({
items: z.array(z.string()).min(1).max(5),
name: z.string().min(1).max(5),
age: z.number().int().gte(1).lte(5),
count: z.number().int().gt(1).lt(5)
})Supported TypeSpec Format Decorators
These format decorators in TypeSpec can be converted to specific constraints in Zod schemas:
| TypeSpec Format | Zod Type Conversion |
|---|---|
| @format("date-time") | .datetime() |
| @format("date") | .date() |
| @format("time") | .time() |
| @format("duration") | .duration() |
| @format("ip") | .ip() |
| @format("email") | .email() |
| @format("uuid") | .uuid() |
| @format("cuid") | .cuid() |
| @format("cuid2") | .cuid2() |
| @format("uri") | .url() |
| @format("url") | .url() |
Extended Syntax for Doc Decorator
By using the zod: identifier within a doc comment, you can instruct the typespec-to-zod to generate Zod schemas with specific requirements.
This feature provides greater flexibility and control over the validation rules directly from the TypeSpec model.
Example TypeSpec:
model ExtendedSyntaxForDocDecorator {
@doc("Username zod: z.string().min(2, { message: 'Must be 2 or more characters long' })")
name: string;
}Generated Zod schema:
export const schemaExtendedSyntaxForDocDecorator = z.object({
// Username
name: z.string().min(2, { message: 'Must be 2 or more characters long' })
})Contributing
Contributions are welcome!
If you find a bug or have a feature request, feel free to open an issue or submit a pull request.
License
This project is licensed under the MIT License.