【问题标题】:TypeScript 3.9.5- The intersection '...' was reduced to 'never' because property 'usage' has conflicting types in some constituentsTypeScript 3.9.5- 交集 '...' 减少为 'never' 因为属性 'usage' 在某些成分中具有冲突类型
【发布时间】:2020-10-01 21:23:58
【问题描述】:

我有一个函数,它接受一个类定义并使用它来返回一个新的抽象类。直到 TS v3.8.3 这工作得很好。现在,在升级到 TS v3.9.5 时,Typescript 似乎获得了与传递给函数的类不同的类型。最好是把代码复制到这里。

enum AttributeUsageModel {
  ContractHash = 0x00,
  ECDH02 = 0x02,
  ECDH03 = 0x03,
  Script = 0x20,
  Vote = 0x30,
  DescriptionUrl = 0x81,
  Description = 0x90,
  Hash1 = 0xa1,
  Hash2 = 0xa2,
  Hash3 = 0xa3,
  Hash4 = 0xa4,
  Hash5 = 0xa5,
}

type BufferAttributeUsageModel =
  | 0x81
  | 0x90
  | 0xf0
  | 0xfa
  | 0xfb
  | 0xfc
  | 0xfd
  | 0xfe
  | 0xff;

type Constructor<T> = new (...args: any[]) => T;

abstract class AttributeBaseModel<T extends AttributeUsageModel> {
  public abstract readonly usage: T;
}

class AttributeModel extends AttributeBaseModel<BufferAttributeUsageModel> {
  public readonly usage: BufferAttributeUsageModel;

  public constructor(usage: BufferAttributeUsageModel) {
    super();
    this.usage = usage;
  }
}

function AttributeBase<
  Usage extends AttributeUsageModel,
  TBase extends Constructor<AttributeBaseModel<Usage>>
>(Base: TBase) {
  // Replacing `Base` with `AttributeModel` apparently fixes it
  abstract class AttributeBaseClass extends Base {} // Base constructor return type is apparently 'never'

  return AttributeBaseClass;
}

// Base constructor return type 'never' is not an object type or intersection of object types with
// statically known members.
//   The intersection 'AttributeBase<AttributeUsageModel, typeof
//   AttributeModel>.AttributeBaseClass & AttributeModel' was
//   reduced to 'never' because property 'usage' has conflicting types in some constituents.
class BufferAttribute extends AttributeBase(AttributeModel) {
  public constructor(usage: BufferAttributeUsageModel) {
    super(usage);
  }
}

来自 Typescript 的错误在 AttributeBase(AttributeModel) 上突出显示。在此示例中,AttributeModel 作为 Base 参数传递给函数。如果我们直接在函数内部使用AttributeModel 而不是Base 参数,错误就会消失。但这是一回事,对吧?

我还不是 Typescript 方面的专家,但我们确实需要某种方法来使用此 AttributeBase 函数或其他方法来动态扩展多个基类。也许答案是显而易见的,但这似乎是相当奇怪的行为。我尝试了很多其他的东西,但没有任何东西能保持我们从这个设置中获得的相同类型严格性。

那么有人可以向我解释这里发生了什么以及我如何解决这个问题,以便我们在没有来自AttributeBase(AttributeModel)never 返回类型的情况下获得相同的类型安全?

如果有帮助,我也已将此代码发布到 repo here

【问题讨论】:

    标签: typescript


    【解决方案1】:

    问题是您的BufferAttributeUsageModel 没有扩展AttributeUsageModel

    您的AttributeBaseModel&lt;T extends AttributeUsageModel&gt; 需要T extends AttributeUsageModel,但随后您将class AttributeModel extends AttributeBaseModel&lt;BufferAttributeUsageModel&gt; 定义为不扩展AttributeUsageModelBufferAttributeUsageModel。这就是您的usage 属性“在某些成分中具有冲突类型”的地方。 - 如错误所述。

    要解决这个问题,您可以将BufferAttributeUsageModel 定义为:

    type BufferAttributeUsageModel =
        AttributeUsageModel
        | 0x81
        | 0x90
        | 0xf0
        | 0xfa
        | 0xfb
        | 0xfc
        | 0xfd
        | 0xfe
        | 0xff;
    

    也许,您应该尝试简化这些类型定义。

    【讨论】:

    • 谢谢!这解决了我的问题。 BufferAttributeUsageModel 中的数字都包含在 enum AttributeUsageModel 中,因此我可以通过将 BufferAttributeUsageModel 定义为 AttributeUsageModel 枚举的必要成员之间的联合来保持更严格的类型安全(并在其他地方做同样的事情)。写出来给其他发现这个的人。
    猜你喜欢
    • 1970-01-01
    • 2017-06-12
    • 2021-07-06
    • 1970-01-01
    • 2018-09-13
    • 1970-01-01
    • 1970-01-01
    • 2018-08-19
    • 1970-01-01
    相关资源
    最近更新 更多