多态与引用($instanceOf / $ref)
模型世界里的两个「非标量」成员,在 Input 里各有专业语法:继承族用 $instanceOf 按子类切分,引用用 $ref / $flatRef 决定给键还是给形。
多态输入:$instanceOf
继承模型(如「核心概念 → 继承与多态」的 BookStore 族)声明一条 Input 时,公共列写在父级,子类专属列用 $instanceOf 各写各的——一条 Input 覆盖整个继承族:
// ① 多态输入:判别列自动落,子类字段按分支给
// import { model, prop, dto } from '@ts-grm/core'
// // BookStore(abstract) ← PhysicalBookStore(city) / OnlineBookStore(url)
// const StoreInput = dto.input(BookStore, c => [
// c.id.key(),
// c.name,
// c.$instanceOf(PhysicalBookStore, c => [c.city]),
// c.$instanceOf(OnlineBookStore, c => [c.url]),
// ])
- 载荷类型
TypeOf<StoreInput>是联合:物理店那支带city、在线店那支带url,判别列由框架按输入命中的分支自动写; $instanceOf可以出现在任意层级(集合成员里也能用),上游类型测试save.test-d.ts里就是c.childNodes.with(c => [c.$instanceOf(ITEM, c => [c.tags])])——子节点按ITEM类型给专属字段;- 判别列值未声明对应的子类分支时,保存按继承页提到的规则报
Illegal discriminator value。
仅引用:$ref
$ref 表示「这里只给目标键,不展开目标本体」(内部称 RefOnly):
// ② $ref:载荷里出现关联 id,目标行不产生写操作
// const BookInput = dto.input(Book, c => [
// c.id.key(),
// c.name,
// c.store.$ref("store", c => [c.id]), // 只落外键 store_id
// c.authors.$ref("authors", c => [c.id]), // 只出现在中间表
// ])
$ref 携带的关联同样会进入 InputAssociationMembers(可被 associated 选项寻址),
但目标实体的字段不进入载荷——写作时只给 id,目标行本体不发生插入/更新。
展平引用:$flatRef
$flatRef 把引用的键展平到当前层(不嵌套对象),可加 .prefix() 避免与自身列重名:
// ③ $flatRef + prefix(设计形态,无上游测试用例)
// c.$flatRef("store", c => [c.id]).prefix("store")
// // 载荷里以 store_id 平铺出现,而非 { store: { id } }
⚠️ 与 o2o 同待遇:
$ref/$flatRef目前在上游没有测试用例,仅有设计形态; 正文给出的写法为类型签名所示,发布后优先核销。
递归集合:树形输入
o2m/o2m 自引用(目录树、评论楼)可以直接递归——Input 声明里再嵌套一次 .with(...) 即可,
关联路径随之有多层("childNodes" → "childNodes.childNodes"),这是上游测试明确覆盖的形态:
// ④ 递归集合(上游 save.test-d.ts 同款写法示意)
// const INPUT = dto.input(TREE_NODE, c => [
// c.name.key(),
// c.childNodes.with(c => [
// c.name.key(),
// c.childNodes.with(c => [c.name]),
// ]),
// ])
// await sqlClient.save(INPUT, payload, {
// associated: {
// "childNodes": "VIOLENTLY_REPLACE",
// "childNodes.childNodes": "APPEND_IF_ABSENT",
// },
// })
一页小结
- 多态 →
$instanceOf(Child, body):一个 Input 吃下整个继承族; - 引用 →
$ref(key, body)只给键;$flatRef(key, body).prefix(p)平铺带前缀; - 自引用集合 → 递归
.with(),关联路径自然嵌套。