Keep your types in sync with Typewriter
I just found this Rust create Typerwriter
It allows you to define a type once in Rust and automatically generated the approrpiate Pydantic BaseModel,
Typescript Interface, Zod validation for a frontend, etc. Supports 10 target languages.
This problem pops up in a lot of larger systems where one team or piece of the stack needs to be in 2 or 3 languages for, hopefully good, reasons.
Here is a quick little excerpt from their README to give you an idea of how it works:
Rust - Source of truth
use typebridge::TypeWriter;
use serde::{Serialize, Deserialize};
/// A user in the system.
#[derive(Serialize, Deserialize, TypeWriter)]
#[sync_to(typescript, python, go)]
pub struct User {
pub id: String,
pub email: String,
pub name: String,
pub age: Option<u32>,
pub is_active: bool,
pub tags: Vec<String>,
}Python → user.py
# Auto-generated by typewriter v1.0.0. DO NOT EDIT.
from pydantic import BaseModel
from typing import Optional
class User(BaseModel):
"""A user in the system."""
id: str
email: str
name: str
age: Optional[int] = None
is_active: bool
tags: list[str]TypeScript → user.ts
/**
* A user in the system.
*/
export interface User {
id: string;
email: string;
name: string;
age?: number | undefined;
is_active: boolean;
tags: string[];
}TypeScript Zod Schema → user.schema.ts
import { z } from 'zod';
export const UserSchema = z.object({
"id": z.string(),
"email": z.string(),
"name": z.string(),
"age": z.number().optional(),
"is_active": z.boolean(),
"tags": z.array(z.string()),
});Go → user.go
// Source: User
package types
// A user in the system.
type User struct {
Id string `json:"id"`
Email string `json:"email"`
Name string `json:"name"`
Age *uint32 `json:"age,omitempty"`
Is_active bool `json:"is_active"`
Tags []string `json:"tags"`
}The author Darshan Vichhi wrote up a post on his motivation and how to use it also if you want to dive deeper.