TSts-grm

多态与引用($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(),关联路径自然嵌套。