TSts-grm

属性与类型

模型里的每个字段都是一个属性声明。快速上手章已见标量,这一节补全所有类型与它们的边界。

标量属性

声明TS 类型语义PostgreSQL
prop.i8() / i16() / i32() / i64()numberi64 可用 asString()有符号整数SMALLINT ~ BIGINT
prop.num(p, s)number定点数(金额等)NUMERIC(p, s)
prop.f32() / f64()number浮点FLOAT / DOUBLE PRECISION
prop.str(n)string定长字符串VARCHAR(n)
prop.text()string长文本TEXT
prop.bool()boolean布尔BOOLEAN
prop.dt()Date日期时间TIMESTAMP

i64 的精度问题

BIGINT 可超过 Number.MAX_SAFE_INTEGER(2⁵³)。读回为 number 会丢精度,框架提供两个选择:

id = prop.i64().asString()   // 以 string 读写 BIGINT;超过 2⁵³ 的 id 用它
id = prop.i64()              // 否则直接用 number 即可

asString() 自动在数据库 BIGINTstring 之间转换,查询、保存、主键全部一致。

可空性

默认不可空NULL 需要显式声明:

store = prop.m2o(BookStore)        // 非空:每条 Book 必须有 store
store = prop.m2o(BookStore).nullable()   // 可空:允许 NULL(表里允许外键为空)
orchidName = prop.str(50).nullable()     // 标量同理

可空性会传导到 DTO 类型:视图里的该字段类型是 T | null,这也让 TS 的 null 检查贯穿查询与保存。

枚举与枚举集合

prop.enum 两种写法:枚举常量表({ 逻辑名: 值 })或值列表(至少两个):

gender = prop.enum({             // 逻辑名与存储值分离
    MALE: 'M',
    FEMALE: 'F',
})

tag = prop.enum("URGENT", "NORMAL", "LOW")   // 直接值列表

features = prop.enumSet("READING_ROOM", "AIR_CONDITION")  // 多选:数组
  • 枚举值只允许字符串/数字,且值必须唯一;
  • enumSet 在库里落为字符串集合(分隔存储),DTO 类型是数组。

JSON 与 JSONB(带结构校验)

prop.json / prop.jsonb 接受一个 StandardSchemaV1 结构(zod 等库天然兼容),字段的 TS 类型自动取 schema 的输出类型:

import { z } from 'zod'

details = prop.json(z.object({
    isbn: z.string(),
    rating: z.number().min(1).max(5),
}))
  • 结构只描述字段形状与转换,运行时不含反射(「DTO 哲学」讲为什么);
  • jsonJSONjsonbJSONB(二进制,可索引)。

自定义数据类型(进阶)

内置类型不够时用 prop.scalar + ScalarProvider 定义自定义数据类型(比如把数据库二进制映射成图片对象),完整机制与示例见 「查询 API → 自定义数据类型」。日常开发很少用到。

下一步

表与字段都齐了,接下来是重头戏:关联——四种关联如何声明、中间表、级联与非对称。