简体   繁体   English

如何从 TypeScript 函数返回一个类?

[英]How can I return a class from a TypeScript function?

I'm using TypeScript with a dependency injection library which works very similar to Angular 1 - basically: register a factory with your dependencies as arguments .我正在使用带有依赖注入库的 TypeScript,它的工作原理与 Angular 1 非常相似——基本上:用你的依赖项作为参数注册一个工厂

This is how I would register a class in ES6这就是我在 ES6 中注册一个类的方式

export let factory = () => {
    return class Foo {}
};

If I write the same in TypeScript:如果我在 TypeScript 中写同样的内容:

export let factory = () => {
    return class Foo {}
};

It fails to compile with the error它无法编译错误

error TS4025: Exported variable 'factory' has or is using private name 'Foo'.错误 TS4025:导出的变量“工厂”具有或正在使用私有名称“Foo”。

Is there any way to allow TypeScript to return a class from a factory function?有没有办法让 TypeScript 从工厂函数返回一个类?

Quick answer快速回答

change this:改变这个:

export let factory = () => {
    return class Foo {}
};

to that:对此:

export let factory = () : any => {
    return class Foo {}
};

Longer answer更长的答案

This error could be triggered/forced by to a tsconfig.json setting:此错误可能由tsconfig.json设置触发/强制:

{
    "compilerOptions": {
        ...
        "declaration": true // this should be false or omitted

But that is not the reason, it is just a trigger.但这不是原因,它只是一个触发器。 The real reason (as discussed here Error when exporting function that returns class: Exported variable has or is using private name ) comes from the Typescript compiler真正的原因(如此处讨论的导出返回类的函数时出错:导出的变量具有或正在使用私有名称)来自 Typescript 编译器

when TS compiler founds statement like this当 TS 编译器发现这样的语句时

let factory = () => { ...

it must start to guess what is the return type, because that information is missing (check the : <returnType> placeholder) :它必须开始猜测返回类型是什么,因为缺少该信息(检查: <returnType>占位符)

let factory = () : <returnType> => { ...

in our case, TS will quickly find out, that the returned type is easy to guess:在我们的例子中,TS 会很快发现,返回的type很容易猜到:

return class Foo {} // this is returned value, 
                    // that could be treated as a return type of the factory method

so, in case we would have that similar statement (this is not the same, as original statement at all, but let's just try to use it as an example to clarify what happens) we can properly declare return type:因此,如果我们有类似的语句(这与原始语句完全不同,但让我们尝试将其用作示例来阐明会发生什么),我们可以正确声明返回类型:

export class Foo {} // Foo is exported
export let factory = () : Foo => { // it could be return type of export function
    return Foo
};

that approach would be working, because the Foo class is exported, ie visible to external world.这种方法会起作用,因为Foo是导出的,即对外部世界可见。

Back to our case.回到我们的案例。 We want to return type which is not exported .我们想要返回未导出的类型 And then, we MUST help TS compiler to decide, what is the return type.然后,我们必须帮助 TS 编译器决定返回类型是什么。

It could be explicit any:它可以是明确的任何:

export let factory = () : any => {
    return class Foo {}
};

But even better would be to have some public interface但更好的是有一些公共接口

export interface IFoo {}

And then use such interface as return type :然后使用这样的接口作为返回类型

export let factory = () : IFoo => {
    return class Foo implements IFoo {}
};

I think this is a proper way to do it:我认为这是一个正确的方法:

export let factory = () => {
     class Foo {/* ... */}
     return Foo as (new () => { [key in keyof Foo]: Foo[key] })
};

Check it out on playground 在操场上看看

You need to export the class as well so that the consumer of the method can access the type.您还需要导出该类,以便该方法的使用者可以访问该类型。

Typically a factory will return an instance rather than a class or constructor.通常,工厂将返回一个实例而不是类或构造函数。

UPDATED EXAMPLE更新示例

export class Foo {}; 

export let factory = () => {
    return Foo;
};

With ES6 you don't need to export the class type, but with TypeScript you absolutely should exporting the type signatures.使用 ES6,您不需要导出类类型,但使用 TypeScript,您绝对应该导出类型签名。

I was struggling with the same error.我正在为同样的错误而苦苦挣扎。 The solution for me was to remove the我的解决方案是删除

"declaration": true

from tsconfig.json or to set it to false .tsconfig.json或将其设置为false

I've found separately provided solution satisfying:我发现单独提供的解决方案令人满意:

export class MyClass {
   ...
}

export type MyClassRef = new (...args: any) => MyClass;

Given that signature I can use MyClassRef as a type of return value:鉴于该签名,我可以使用MyClassRef作为返回值的类型:

exposeMyClass(): MyClassRef {
    return MyClass;
}

Late answer on old question:旧问题的迟到答案:

You need to have the class defined outside the factory method and define return value using 'typeof'.您需要在工厂方法之外定义类并使用“typeof”定义返回值。

class Foo {}

export const factory = (): typeof Foo => {
    return Foo;
};

Are you looking for returning Type of class from the function?您是否正在寻找从函数中返回类的类型? Below is one code snippet how we can implement factory in TypeScript similar to in other languages.下面是一个代码片段,我们如何像在其他语言中一样在 TypeScript 中实现工厂。

    class Greeter {
    greeting: string;
    constructor(message: string) {
        this.greeting = message;
    }
    greet() {
        return "Hello, " + this.greeting;
    }
}
class Factory{
    getObject(msg:string): Greeter {
        return new Greeter(msg);
    }
}
var greeter = new Factory().getObject("Hi");
console.log(greeter.greet());

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM