在打字稿中,如何在不导出类本身的情况下导出私有类的类型

cod*_*eto 6 typescript typescript-typings

我有一个模块,其中公共类的公共方法创建并返回私有类的新实例。要求是MyClassPrivateHelper必须只能由 实例化MyClass

class MyClassPrivateHelper {
    constructor(private cls: MyClass) {
    }

    public someHelperMethod(arg): void {
        this.cls.someMethod();
    }
}
export class MyClass {
    public createHelper(): MyClassPrivateHelper {  // error here
        return new MyClassPrivateHelper(this);
    }

    public someMethod(): void {
        /**/
    }
}
Run Code Online (Sandbox Code Playgroud)

通过这种安排,TypeScript 报告错误:

[ts] Return type of public method from exported class has or is using private name 'MyClassPrivateHelper'.

我的目标是只导出私有类的“类型”,而不让使用代码的模块能够直接实例化它。例如

const mycls = new module.MyClass();

// should be allowed
const helper: MyClassPrivateHelper = mycls.createHelper();

// should not be allowed
const helper = new module.MyClassPrivateHelper();
Run Code Online (Sandbox Code Playgroud)

我试过typeof像这样使用但没有成功。

export type Helper = typeof MyClassPrivateHelper
Run Code Online (Sandbox Code Playgroud)

也许我不明白“typeof”是如何工作的。我的问题是:

  • 为什么导出类型 usingtypeof不起作用?
  • 如何在不暴露模块外的私有类的情况下导出类型?

Gre*_*reg 9

为什么使用 typeof 导出类型不起作用?

export type MyInterface = typeof MyClassPrivateHelper
Run Code Online (Sandbox Code Playgroud)

在这个例子中MyInterface是构造函数的类型,但你想导出这个构造函数可以产生的实例的类型。

如何在不暴露模块外的私有类的情况下导出类型?

像这样:

export type MyInterface = InstanceType<typeof MyClassPrivateHelper>
Run Code Online (Sandbox Code Playgroud)

InstanceType在这里简要描述:https : //www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html

或者,我发现以下方法也有效:

type Interface<T> = { [P in keyof T]: T[P] }
export interface MyInterface extends Interface<MyClassPrivateHelper> {}
Run Code Online (Sandbox Code Playgroud)

Interface类型基本上复制了 中的所有公共属性T,然后我们使用它们来声明一个新接口。

有关更多详细信息,请参阅https://github.com/Microsoft/TypeScript/issues/471#issuecomment-381842426


lwa*_*ent 6

您应该创建一个界面并导出:

export interface IMyHelper {
   someHelperMethod(arg): void;
}
Run Code Online (Sandbox Code Playgroud)

然后让 Helper 实现:

class MyClassPrivateHelper implements IMyHelper {
    constructor(private cls: MyClass) {
    }

    public someHelperMethod(arg): void {
        this.cls.someMethod();
    }
}
Run Code Online (Sandbox Code Playgroud)

公共类将返回接口

export class MyClass {
    public createHelper(): IMyHelper { 
        return new MyClassPrivateHelper(this);
    }

    public someMethod(): void {
        /**/
    }
}
Run Code Online (Sandbox Code Playgroud)

从外部,助手再次被其接口引用:

const helper: IMyHelper = mycls.createHelper();
Run Code Online (Sandbox Code Playgroud)