typescript - 鉴于这种类型安全的方法接受一个参数,您能否将其推广到 N 个参数同时保持类型安全?
问题描述
背景:
接口Extendable在类型T上是通用的,并且具有方法extend接受U类型的参数并返回V类型的参数:
interface Extendable<T> {
extend<U, V>(x: U): V
}
方法extend具有以下约束:
- U必须可分配给T或T必须可分配给U。
- 如果U可分配给T则V具有类型T。否则V的类型为U。
Interface Extendable在下面更新以反映这些约束:
interface Extendable<T> {
extend<U extends (T extends U ? unknown : T)>(x: U): U extends T ? T : U
}
Interface Extendable测试如下:
interface A { a: string }
interface B extends A { b: string }
interface C extends B { c: string }
interface D extends A { d: string }
interface E { e: string }
declare let a: A, b: B, c: C, d: D, e: E
declare let t: Extendable<B>
t.extend(a) // return type A
t.extend(b) // return type B
t.extend(c) // return type B
t.extend(d) // error - D is not assignable to B
t.extend(e) // error - E is not assignable to B
现在事实证明,我正在构建一个类型化的 SQL 查询构建器,并且查询是可扩展的。以下是倒排查询类型层次结构:
+Root
+---Filter
| +---Select
| +---Update
| \---Delete
\---Insert
查询类型之间的继承是通过鸭子类型隐含的,而不是显式扩展。
Root 可分配给 Filter 和 Insert。过滤器可分配给选择、更新和删除。
您从查询类型 Root 开始。如果您构造 WHERE 子句,则新的查询类型将变为 Filter。如果随后构造 DELETE 子句,则新查询类型将变为 Delete。
接口如下。
interface Root extends Extendable<Root> {
where(): Filter
select(): Select
insert(): Insert
update(): Update
delete(): Delete
}
interface Filter extends Extendable<Filter> {
where(): Filter
select(): Select
update(): Update
delete(): Delete
}
interface Select extends Extendable<Select> {
where(): Select
select(): Select
}
interface Update extends Extendable<Update> {
where(): Update
update(): Update
}
interface Delete extends Extendable<Delete> {
where(): Delete
delete(): Delete
}
interface Insert extends Extendable<Insert> {
insert(): Insert
}
查询类型测试如下:
declare let root: Root
declare let filter: Filter
declare let select: Select
declare let insert: Insert
filter.extend(root) // return type Filter
filter.extend(filter) // return type Filter
filter.extend(select) // return type Select
filter.extend(insert) // error - Insert is not assignable to Filter
Extendable 接口的原始约束保证了这两个属性:
- 查询只能使用它自己的类型、祖先类型或后代类型进行扩展
- 扩展查询时,如果参数类型是基本类型的后代,则返回类型是参数类型。否则返回类型是基本类型。
问题:
我想添加一个额外的类型安全重载的扩展,它接受多个查询参数,例如extend(...args)
它将使以下两行等效:
a.extend(b).extend(c).extend(d)
a.extend(b, c, d)
我不知道如何以类型安全的方式编写重载。可能吗?
如果不可能,有没有办法为两个参数编写重载?对于三个论点?你能把这个过程概括为 N 个参数吗?
解决方案
推荐阅读
- kotlin-android-extensions - 如何在 Android Studio 中打开 AutoImport?
- javascript - 当使用 Javascript 的 Reflect API 构建扩展另一个类的实例时,为什么索引数组是共享范围?
- google-bigquery - Google BigQuery 中 MERGE 语句的性能?
- json - 'Type' 类型的值没有下标错误 Swift
- php - Google AndroidPublisher 订阅确认如何
- publish-subscribe - 如果未设置 DataSetWriterId,如何识别 NetworkMessage 中的 DataSet?
- laravel - Laravel 雄辩的复杂搜索查询问题
- react-native - 反应原生模态框内容溢出
- node.js - 节点,chrome 错误 [ERR_STREAM_DESTROYED]:流被销毁后无法调用 write
- arduino - Arduino Ethernet shield 未正确接收 UDP 数据包