Blocked-by: #18116
⚠️ 重建卡 —— 原卡 #17878 因 os-musk 账户停用而被 GitHub 隐藏(404)。
隐藏不是删除:停用解除后原卡会自行恢复,届时请以 #17878 为准并关闭本卡。
本卡正文重建自该席位发出前的原始字节(决策箱移交评论),⛔ 非凭记忆复述。原卡定级为 priority:p2 / domain:engine / needs-user-decision,⛔ 本卡裸立不分级,由分诊重新判。
一句话
TursoDriver.beginTransaction() 在 remote 模式下返回 libsql 事务,而它继承来的声明承诺 Promise<Knex.Transaction> —— 那个 any 掩盖的是一个真实的 Liskov 违例,不是一扇没收窄的门。
本卡承载的是一个选择,⛔ 不是一份可实现的修法。任何 dev 轮次派下去都只会重新发现这一点然后回 needs_decision。
读数
| 读数 |
值 |
| 基类约束声明(TS 按基类查,⛔ 不按接口) |
SqlDriver.beginTransaction(): Promise<Knex.Transaction>(sql-driver.ts:8752) |
| 契约声明 |
IDataDriver.beginTransaction(): Promise<unknown>(data-driver.ts:322) |
| 该门现在发布 |
Promise<any> |
| remote 分支实际返回 |
RemoteTransport.beginTransaction() → this.client!.transaction(),libsql 事务 |
| ⭐ 为什么不能用既定修复形状关掉 |
换成 Promise<unknown> 不编译:TS2416,unknown 比基类声明更宽 |
⭐ 控制项(同一轮):把 RemoteTransport.beginTransaction 从 Promise<any> 收窄到 Promise<unknown> 成功落地(它实现的是接口,不是 override)⇒ 收窄手法本身有效;这一格不同是因为约束声明不同,⛔ 不是手法不灵。
两条出路,各自的价
| 选项 |
做什么 |
实测代价 |
| A |
把 SqlDriver.beginTransaction 放宽成 Promise<unknown>,再把两个 override 收窄到它 |
⚠️ 消费端站点 11 → 25(+14);⚠️ 反转一次诚实的收窄 —— 每个 driver-sql 消费者从此拿不到 knex 事务类型;⚠️ 与 #17690「Not findings」逐字保护的那条直接冲突 |
| C |
重构 remote 事务句柄,让 TursoDriver 真的答出基类的类型 |
运行期改动,超出 #17690 的声明面;⇒ 代价未被量过 |
⚠️⚠️ 源头 #17690 在这一格上自相矛盾:它的「Not findings」小节逐字保护了 SqlDriver.beginTransaction publishes Promise<Knex.Transaction> … 比声明更窄 —— the honest direction,同时又要求这个 override 换成契约类型。两者不能同时成立 —— 这正是本卡存在的原因,也是 A 之所以不是「显然正确」的原因。
现状(⛔ 不是未处理)
该门在 #17876 落地后保持 Promise<any>,但已在代码里被点名:站点注释写明它是 LSP 违例、附 TS2416 收据与两条出路的定价。⛔ 未 re-mask、⛔ 未加 !、⛔ 未 cast。⇒ 今天没有隐瞒,只有未决。
需要维护者 / 总监席回答的那一问
SqlDriver.beginTransaction 的声明该服从谁:让基类放宽到契约(A,买回 LSP 合规,卖掉 11→25 个消费点的 knex 类型),还是让实现答出基类(C,保住收窄,付一次运行期重构)?
⛔ 不推荐任何一方:A 的代价是已量的,C 的代价是未量的;在两个未同量纲的代价之间选,是维护者的口径问题,⛔ 不是席位的测量问题。
⚠️ 若判断需要先把 C 的价量出来再选,请直说 —— 那是一个可派发的测量任务。
Refs
原卡 #17878(已隐藏)· 源头 #17690 · 落地轮 #17876 · packages/drivers/driver-sql/src/sql-driver.ts:8752 · packages/spec/src/data/data-driver.ts:322
Generated by Claude Code
Blocked-by: #18116
一句话
TursoDriver.beginTransaction()在 remote 模式下返回 libsql 事务,而它继承来的声明承诺Promise<Knex.Transaction>—— 那个any掩盖的是一个真实的 Liskov 违例,不是一扇没收窄的门。本卡承载的是一个选择,⛔ 不是一份可实现的修法。任何 dev 轮次派下去都只会重新发现这一点然后回
needs_decision。读数
SqlDriver.beginTransaction(): Promise<Knex.Transaction>(sql-driver.ts:8752)IDataDriver.beginTransaction(): Promise<unknown>(data-driver.ts:322)Promise<any>RemoteTransport.beginTransaction()→this.client!.transaction(),libsql 事务Promise<unknown>不编译:TS2416,unknown比基类声明更宽⭐ 控制项(同一轮):把
RemoteTransport.beginTransaction从Promise<any>收窄到Promise<unknown>成功落地(它实现的是接口,不是 override)⇒ 收窄手法本身有效;这一格不同是因为约束声明不同,⛔ 不是手法不灵。两条出路,各自的价
SqlDriver.beginTransaction放宽成Promise<unknown>,再把两个 override 收窄到它driver-sql消费者从此拿不到 knex 事务类型;TursoDriver真的答出基类的类型SqlDriver.beginTransaction publishes Promise<Knex.Transaction> … 比声明更窄 —— the honest direction,同时又要求这个 override 换成契约类型。两者不能同时成立 —— 这正是本卡存在的原因,也是 A 之所以不是「显然正确」的原因。现状(⛔ 不是未处理)
该门在 #17876 落地后保持
Promise<any>,但已在代码里被点名:站点注释写明它是 LSP 违例、附TS2416收据与两条出路的定价。⛔ 未 re-mask、⛔ 未加!、⛔ 未 cast。⇒ 今天没有隐瞒,只有未决。需要维护者 / 总监席回答的那一问
⛔ 不推荐任何一方:A 的代价是已量的,C 的代价是未量的;在两个未同量纲的代价之间选,是维护者的口径问题,⛔ 不是席位的测量问题。
⚠️ 若判断需要先把 C 的价量出来再选,请直说 —— 那是一个可派发的测量任务。
Refs
原卡 #17878(已隐藏)· 源头 #17690 · 落地轮 #17876 ·
packages/drivers/driver-sql/src/sql-driver.ts:8752·packages/spec/src/data/data-driver.ts:322Generated by Claude Code