【问题标题】:Optional generic that extends interface扩展接口的可选泛型
【发布时间】:2021-02-06 09:58:59
【问题描述】:

我有一个导出的抽象类,目前有一个泛型。然而,我现在需要两个泛型。我不想更改当前使用此类的所有切除类。所以我想添加一个扩展接口的可选泛型类。

这是我目前拥有的

export abstract class SharedShell<T extends IBase, T1 extends IBase> implements OnInit, OnDestroy {}

使 T1 成为可选的最佳方法是什么?我尝试执行以下操作

export abstract class SharedShell<T extends IBase, T1 extends IBase | Undefined = Undefined> implements OnInit, OnDestroy {}

但是这会导致类型错误。

'IBase' is assignable to the constraint of type 'T1', but 'T1' could be instantiated with a different subtype of constraint 'IBase'.

这就是我卡住的地方,我怎样才能最好地解决这个问题?

TS Playground example

【问题讨论】:

  • 您能否提供一个完整的可重现示例,即使用 TS 游乐场?从您的代码中我看不到错误:
  • @mbdavis 我在原帖中添加了一个示例。
  • 谢谢!所以澄清一下 - 当提供 T1 时,您希望 detailService 成为 ISharedService&lt;T | T1&gt;,否则只是 ISharedService&lt;T&gt;
  • @mbdavis 是的,没错。

标签: angular typescript generics


【解决方案1】:

如果我必须按照声明使用您的SharedShell,那么我会使用Extract utility type 之类的条件类型将T1 转换为合适的类型:

export abstract class SharedShell<T extends IBase, T1 extends IBase | undefined = undefined> {
    constructor(private detailService: ISharedService<T | Extract<T1, IBase>>,
        private listService: ISharedService<T>,
    ) { }
}

如果T1undefined,那么Extract&lt;T1, IBase&gt; 将是never,而T | never 只是T...这样就可以按照您的意愿工作。如果T1 是某个联合(例如SomeSubtypeOfIBase | undefined),那么Extract&lt;T1, IBase&gt; 将只包含可分配给IBase 的部分(例如SomeSubtypeOfIBase)。


我不确定第二个参数 T1 的用途是什么,因此以下建议可能不成立,但是:您可能希望将 T1 默认为 never 而不包括 undefined T1 的域。当您这样做时,T | T1 类型将始终可分配给 IBase,并且一切正常:

export abstract class SharedShell<T extends IBase, T1 extends IBase = never> {
    constructor(private detailService: ISharedService<T | T1>,
        private listService: ISharedService<T>,
    ) { }
}

同样,如果没有更多关于如何使用 T1 的示例,我无法确定这是否会有所帮助。但它要简单得多。


Playground link to code

【讨论】:

    猜你喜欢
    • 2018-04-09
    • 2015-04-01
    • 2021-08-28
    • 1970-01-01
    • 1970-01-01
    • 2019-04-06
    • 1970-01-01
    • 1970-01-01
    • 2020-07-19
    相关资源
    最近更新 更多