【问题标题】:Typescript allows to use proper multiple inheritance with mixins, but fails to create delcaration filesTypescript 允许对 mixins 使用适当的多重继承,但无法创建声明文件
【发布时间】:2019-08-10 01:13:27
【问题描述】:

我正在玩 TypeScript 中的“多重继承”,或者更确切地说是对 mixin 有很好的理解。经过许多弯路,我发现最简单的方法是尽可能少地显式转换,并且能够创建如下所示的内容(完整的示例可以在此gist 中找到)。

我的问题是:为什么 TypeScript 允许我构建它,但是却无法为此创建声明文件?

export function TaggedMixin<Super extends Ctor>(superClass: Super) {
  class Tagged extends superClass {
    public static TAG_PUBLIC: string;
    protected static TAG_PROTECTED: string;
    private static TAG_PRIVATE: string;

    public tag_public!: string;
    protected tag_protected!: number;
    private tag_private!: number;
  }

  return Tagged;
}

const Tagged = TaggedMixin(class {
    public static ANON_PUBLIC: string;
    protected static ANON_PROTECTED: string;
    private static ANON_PRIVATE: string;

    public anon_public!: string;
    protected anon_protected!: number;
    private anon_private!: number;
});

class TaggedClass extends Tagged {
    constructor() {
        super();

        TaggedClass.ANON_PUBLIC;
        TaggedClass.ANON_PROTECTED;
        TaggedClass.TAG_PUBLIC;
        TaggedClass.TAG_PROTECTED;

        this.anon_public;
        this.anon_protected;
        this.tag_public;
        this.tag_protected;
    }
}


编辑:

该TS的错误无法创建声明文件:

Property 'tag_protected' of exported class expression may not be private or protected.ts(4094)
Property 'tag_private' of exported class expression may not be private or protected.ts(4094)
Property 'TAG_PROTECTED' of exported class expression may not be private or protected.ts(4094)
Property 'TAG_PRIVATE' of exported class expression may not be private or protected.ts(4094)

【问题讨论】:

  • 您能详细说明一下“未能创建声明文件”是什么意思吗?您确定声明文件中包含您不export 的内容吗?
  • 我将错误输出添加到问题中。示例已完成,没有其他导出或导入的东西。

标签: typescript multiple-inheritance encapsulation mixins


【解决方案1】:

发出声明和混入存在限制。类表达式不能有私有成员或受保护成员,因为正如 here 所述:

如果启用了声明发射,则导出的匿名类不能有私有或受保护成员,因为无法在 .d.ts 文件中表示。

Typescript 会将 mixin 的实例类型表示为对象类型,而对象类型不能有标记为 privateprotected 的成员,因此会报错。

删除非公开成员将解决问题。

您还可以添加一些手动输入和类声明,这将使您接近目标:

type Ctor = new (...a: any[]) => any
declare class TaggedMixinInstance { // just a dummy, never call new TaggedMixinInstance() or extend this directly 
    public tag_public: string;
    protected tag_protected: number;
    private tag_private: number;
}

export function TaggedMixin<Super extends Ctor>(superClass: Super): {
    new(...a: any[]): TaggedMixinInstance;
    TAG_PUBLIC: string
} & Super {
    class Tagged extends superClass {
        public static TAG_PUBLIC: string;
        protected static TAG_PROTECTED: string;
        private static TAG_PRIVATE: string;

        public tag_public!: string;
        protected tag_protected!: number;
        private tag_private!: number;
    }

    return Tagged;
}

const Tagged = TaggedMixin(class {
    public static ANON_PUBLIC: string;
    protected static ANON_PROTECTED: string;
    private static ANON_PRIVATE: string;

    public anon_public!: string;
    protected anon_protected!: number;
    private anon_private!: number;
});

class TaggedClass extends Tagged {
    constructor() {
        super();

        TaggedClass.ANON_PUBLIC;
        TaggedClass.ANON_PROTECTED;
        TaggedClass.TAG_PUBLIC;
        TaggedClass.TAG_PROTECTED; // still an error

        this.anon_public;
        this.anon_protected;
        this.tag_public;
        this.tag_protected;
    }
}

【讨论】:

  • 是的,经过长时间的研究,这是我发现的。但是,我想知道为什么他们声明他们支持 mixin 类并且忘记提到这个重要的事情。 TypeScript 团队有什么理由吗?他们是否打算添加它,或者它是没有人真正需要的东西,所以没有记录?
  • 编译器给你的错误信息是告诉你私有和受保护的方法不能在这里使用。您可以说错误消息是文档,只是没有任何解释为什么它不可能..
  • @FlorianBachmann 有一个未解决的问题,所以它可能会发生github.com/Microsoft/TypeScript/issues/17293。我添加了一个您可能会觉得有用的解决方法
  • @TitianCernicova-Dragomir 这是一个很好的解决方法。我会密切关注这个问题:)
猜你喜欢
  • 2021-07-07
  • 1970-01-01
  • 1970-01-01
  • 2020-02-03
  • 1970-01-01
  • 2020-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多