Sonamu automatically generates TypeScript types that provide complete type safety based on Entity definitions. This document explains how each Entity field type is converted to TypeScript types.
Type Conversion Overview
Field Types Entity Prop → TypeScript Type auto-conversion and type safety
Nullable Support nullable: true → T | null optional null handling
Array Types type[] → T[] array type auto-generation
Relation Types BelongsToOne → number (FK) relation field type conversion
Basic Type Conversion
Shows how each Entity field type is converted to TypeScript types.
Numeric Types
Entity Definition
Generated Type
{
"props" : [
{ "name" : "id" , "type" : "integer" },
{ "name" : "view_count" , "type" : "integer" , "nullable" : true },
{ "name" : "user_id" , "type" : "bigInteger" }
]
}
Entity Type TypeScript Type Description integernumber32bit integer integer[]number[]Integer array bigIntegerbigint64bit integer (large numbers) bigInteger[]bigint[]Large integer array
bigInteger vs integer : integer is sufficient for IDs or counts, but use bigInteger for
timestamps (milliseconds) or very large numbers.
String Types
Entity Definition
Generated Type
{
"props" : [
{ "name" : "email" , "type" : "string" , "length" : 100 },
{ "name" : "bio" , "type" : "string" },
{ "name" : "tags" , "type" : "string[]" }
]
}
Entity Type TypeScript Type Description stringstringString string[]string[]String array
The length attribute doesn’t affect TypeScript types, but is converted to .max(length)
validation in Zod.
Boolean Types
Entity Definition
Generated Type
{
"props" : [
{ "name" : "is_active" , "type" : "boolean" },
{ "name" : "permissions" , "type" : "boolean[]" }
]
}
Date Types
Entity Definition
Generated Type
{
"props" : [
{ "name" : "created_at" , "type" : "date" },
{ "name" : "login_history" , "type" : "date[]" , "nullable" : true }
]
}
JSON Serialization : In API responses, Date is transmitted as an ISO string (string). Zod’s z.date() automatically converts the string to a Date object.// API Response (JSON)
{ "created_at" : "2024-01-01T00:00:00.000Z" }
// After Zod parsing
{ created_at : Date } // Automatically converted to Date object
UUID Types
Entity Definition
Generated Type
{
"props" : [
{ "name" : "uuid" , "type" : "uuid" },
{ "name" : "related_ids" , "type" : "uuid[]" }
]
}
TypeScript doesn’t have a dedicated UUID type, so it’s represented as string. Format is
validated with .uuid() in Zod validation.
Numeric Precision Types
Two types for handling PostgreSQL high-precision numbers.
number vs numeric
Entity Definition
Generated Type
{
"props" : [
{
"name" : "price" ,
"type" : "number" ,
"precision" : 10 ,
"scale" : 2
},
{
"name" : "balance" ,
"type" : "numeric" ,
"precision" : 20 ,
"scale" : 8
}
]
}
Entity Type TypeScript Type PostgreSQL Type Use Case numbernumberreal, double precision, numericGeneral calculations (floating point) numericstringnumericFinancial calculations (fixed point)
Choosing number vs numeric :✅ Use number when :
General numeric calculations
Decimal precision is not critical
Scientific calculations, statistics
❌ Use numeric when :
Financial calculations (money, prices, balances)
Exact decimals are required
Cryptocurrency amounts
// number - floating point errors possible
0.1 + 0.2 === 0.3 ; // false (0.30000000000000004)
// numeric - exact value preserved as string
import Decimal from "decimal.js" ;
new Decimal ( "0.1" ). plus ( "0.2" ). equals ( "0.3" ); // true
Enum Types
Entity Enums are converted to TypeScript Union types.
Entity Definition
Generated Type (sonamu.generated.ts)
{
"enums" : {
"UserRole" : {
"admin" : "Administrator" ,
"moderator" : "Moderator" ,
"normal" : "Normal User"
}
},
"props" : [
{ "name" : "role" , "type" : "enum" , "id" : "UserRole" },
{ "name" : "badges" , "type" : "enum[]" , "id" : "UserBadge" }
]
}
Benefits :
Autocomplete support
Type safety guaranteed
Compile errors for invalid values
// ✅ Correct usage
const user : User = {
role: "admin" , // Autocompleted
};
// ❌ Compile error
const user : User = {
role: "guest" , // Error: Type '"guest"' is not assignable
};
JSON Type
Used when storing complex object structures as JSON.
Entity Definition
Define in types file
{
"props" : [
{ "name" : "metadata" , "type" : "json" , "id" : "PostMetadata" }
]
}
The json type references the Zod schema specified by id. This schema must be defined directly
in {entity}.types.ts.
Virtual Type
Computed fields not stored in the database.
Entity Definition
Define in types file
{
"props" : [
{ "name" : "full_name" , "type" : "virtual" , "id" : "UserFullName" }
]
}
Virtual fields are computed in Model’s Enhancer:
const enhancers = this . createEnhancers ({
A : ( row ) => ({
... row ,
full_name: ` ${ row . first_name } ${ row . last_name } ` ,
}),
});
Vector Type
Type for vector search (pgvector).
Entity Definition
Generated Type
{
"props" : [
{ "name" : "embedding" , "type" : "vector" , "dimensions" : 1536 },
{ "name" : "embeddings_history" , "type" : "vector[]" , "dimensions" : 1536 }
]
}
dimensions doesn’t affect TypeScript types, but is used in PostgreSQL schema and Zod validation.// Zod validation
z . array ( z . number ()). length ( 1536 ); // dimensions validation
Relation Types
Fields representing relationships between Entities.
BelongsToOne (Many-to-One)
Entity Definition
Generated Type
{
"props" : [
{
"name" : "user" ,
"type" : "relation" ,
"relationType" : "BelongsToOne" ,
"with" : "User"
}
]
}
Field name transformation : user → user_idIn Entity, you define as user, but the actual TypeScript type becomes user_id.
OneToOne (One-to-One)
Entity Definition
Generated Type
{
"props" : [
{
"name" : "profile" ,
"type" : "relation" ,
"relationType" : "OneToOne" ,
"with" : "Profile" ,
"hasJoinColumn" : true
}
]
}
HasMany / ManyToMany
Entity Definition
Generated Type
{
"props" : [
{
"name" : "posts" ,
"type" : "relation" ,
"relationType" : "HasMany" ,
"with" : "Post" ,
"joinColumn" : "user_id"
}
]
}
HasMany and ManyToMany are not included in base types. When you define a Subset, those types
are included in the Subset type.
Nullable Handling
nullable: true is converted to TypeScript Union type.
Entity Definition
Generated Type
{
"props" : [
{ "name" : "nickname" , "type" : "string" , "nullable" : true },
{ "name" : "tags" , "type" : "string[]" , "nullable" : true },
{
"name" : "manager" ,
"type" : "relation" ,
"relationType" : "BelongsToOne" ,
"with" : "User" ,
"nullable" : true
}
]
}
Array nullable : nullable: true for string[] means the array itself can be null.// nullable: true
tags : string [] | null
// ✅ Possible
const user = { tags: null };
const user = { tags: [] };
const user = { tags: [ "a" , "b" ] };
// ❌ Not possible
const user = { tags: undefined };
// If array elements should be nullable, you need a custom type
tags : ( string | null )[] // Define as custom type
Complete Type Mapping Table
Mapping table of all Entity Prop types to TypeScript types.
Entity Type TypeScript Type Notes integernumber32bit integer integer[]number[]Integer array bigIntegerbigint64bit integer bigInteger[]bigint[]Large integer array stringstringString string[]string[]String array numbernumberFloating point number[]number[]Floating point array numericstringFixed point (precision as string) numeric[]string[]Fixed point array booleanbooleanBoolean boolean[]boolean[]Boolean array dateDateDate (string in JSON) date[]Date[]Date array uuidstringUUID string uuid[]string[]UUID array enumEnumTypeUnion type enum[]EnumType[]Union type array jsonCustomTypeCustom object type virtualCustomTypeComputed field vectornumber[]Vector (pgvector) vector[]number[][]Vector array tsvectorstringFull-text search (PostgreSQL) BelongsToOnenumberForeign Key (FK) OneToOne (hasJoinColumn)numberForeign Key (FK) HasMany- Not in Base type ManyToMany- Not in Base type
Practical Example
Type conversion example for an actual User Entity.
user.entity.json
Generated Type (user.types.ts)
{
"id" : "User" ,
"table" : "users" ,
"props" : [
{ "name" : "id" , "type" : "integer" },
{ "name" : "email" , "type" : "string" , "length" : 100 },
{ "name" : "username" , "type" : "string" , "length" : 50 },
{ "name" : "role" , "type" : "enum" , "id" : "UserRole" },
{ "name" : "is_active" , "type" : "boolean" },
{ "name" : "bio" , "type" : "string" , "nullable" : true },
{ "name" : "follower_count" , "type" : "integer" },
{ "name" : "created_at" , "type" : "date" },
{ "name" : "updated_at" , "type" : "date" },
{
"name" : "profile" ,
"type" : "relation" ,
"relationType" : "OneToOne" ,
"with" : "Profile" ,
"hasJoinColumn" : true ,
"nullable" : true
}
],
"enums" : {
"UserRole" : {
"admin" : "Administrator" ,
"moderator" : "Moderator" ,
"normal" : "Normal User"
}
}
}
Next Steps
Generated Types Types of generated types and their uses
Zod Validation Runtime validation with Zod
E2E Type Safety End-to-end type safety
Field Types Complete Entity field type reference