打字稿泛型约束

时间:2020-07-22 18:45:20

标签: typescript

对模糊的标题表示歉意,但我不知道该如何简洁地表达这个问题!

我正在尝试实现一个类:

class Stream<Template<T,K,I>>

我知道这在语法上是不正确的。到目前为止,我有...

class Stream<T extends object, K, I extends string> {
  constructor(ledger: Ledger, template: Template<T, K, I>) {
    this.ledger = ledger;
    this.stream = ledger.streamQuery(template);
  }

  private ledger: Ledger;
  private stream: DamlStream<T, K, I, readonly CreateEvent<T, K, I>[]>;
...

我想做的是制作一个通用流,这样就可以将流定义为:

stream: Stream<Record>

其中RecordTemplate<T,K,I>

我不想将类定义为Stream<T,K,I>,因为T的{​​{1}} KI看起来很讨厌,生成的哈希字符串。这看起来很丑。

TLDR: 我希望能够将流定义为Record,而不是stream: Stream<Record>

请告知您是否有话要说!

欢呼

编辑:(更多说明)

我想用如下构造函数实例化Stream类:stream: Stream<RecordT, RecordK, RecordI>。这里的stream = new Stream(ledger, StorageRecord)是从后端生成的类型,类型为StorageRecord,其中Template<T,K,I>KT有时名称很丑。

问题是当我想将I类成员定义为Stream时。

例如,我只想输入stream: Stream<...>

我无法将Stream<StorageRecord>定义为Stream,因为class Stream<T>需要一个ledger.streamQuery作为参数。

我无法将Template定义为Stream,因为class Stream<T extends Template>本身是通用的。

我需要跟踪TemplateTK,因为在班上也需要它们。

1 个答案:

答案 0 :(得分:1)

您可以使用条件infer语法来解决此问题,第一个泛型应以最通用的方式扩展Template,然后可以使用其他泛型来推断数据,以便您可以稍后在课堂上使用。

class Stream<Templ extends Template<any,any,any>, 
             T extends object=(Templ extends Template<infer A,any,any> ? A : never), 
             K extends  any  =(Templ extends Template<any,infer A,any> ? A : never),
             I extends string=(Templ extends Template<any,any,infer A> ? A : never)
             > {
    constructor(ledger: Ledger, template: Templ) {
        this.ledger = ledger;
        this.stream = ledger.streamQuery(template);
    }

    private ledger: Ledger;
    private stream: DamlStream<T, K, I, readonly CreateEvent<T, K, I>[]>;
}

这样Stream< StorageRecord>应该可以正确推断内部参数。请注意,Stream<StorageRecord, {}, 0, "hi">从技术上讲也是有效的,并且可能会破坏某些内容,因此要获得更严格的代码,您将必须执行以下操作:

type _inferT<Templ extends Template<any,any,any>> = Templ extends Template<infer A,any,any> ? A : never
type _inferK<Templ extends Template<any,any,any>> =(Templ extends Template<any,infer A,any> ? A : never)
type _inferI<Templ extends Template<any,any,any>> = (Templ extends Template<any,any,infer A> ? A : never)
class Stream<Templ extends Template<any,any,any>> {
    constructor(ledger: Ledger, template: Templ) {
        this.ledger = ledger;
        this.stream = ledger.streamQuery(template);
    }

    private ledger: Ledger;
    private stream: DamlStream<_inferT<Templ>, _inferK<Templ>, _inferI<Templ>, readonly CreateEvent<_inferT<Templ>, _inferK<Templ>, _inferI<Templ>>[]>;
}

但这真的很快就很烦人,这就是为什么我建议先将速记放在类泛型中,它为您提供对正确类型的更快引用。