如何从 TypeScript 函数返回类?

问题描述 投票:0回答:8

我使用带有依赖注入库的 TypeScript,它的工作方式与 Angular 1 非常相似 - 基本上:使用依赖项作为参数注册一个工厂

这就是我在 ES6 中注册课程的方式

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

如果我在 TypeScript 中写同样的内容:

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

编译失败并出现错误

错误 TS4025:导出的变量“factory”具有或正在使用私有名称“Foo”。

有什么方法可以让 TypeScript 从工厂函数返回一个类吗?

javascript angularjs dependency-injection typescript
8个回答
23
投票

快速解答

更改此:

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

对此:

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

更长的答案

此错误可能由 tsconfig.json 设置触发/强制:

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

但这不是原因,这只是一个触发因素。真正的原因(如此处讨论的导出返回类的函数时出现错误:导出的变量具有或正在使用私有名称)来自 Typescript 编译器

当 TS 编译器发现这样的语句时

let factory = () => { ...

它必须开始猜测返回类型是什么,因为缺少该信息(检查

: <returnType>
占位符)

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

在我们的例子中,TS很快就会发现,返回的

type
很容易猜到:

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

所以,如果我们有类似的语句(这与原始语句完全不一样,但让我们尝试用它作为示例来阐明发生的情况)我们可以正确声明返回类型:

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

这种方法会起作用,因为

Foo

 class 是导出的,即对外部世界可见。

回到我们的案例。

我们想要返回类型,即未导出。然后,我们必须帮助 TS 编译器决定返回类型是什么。

可以是任何明确的:

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

但更好的是有一些公共接口

export interface IFoo {}

然后使用

返回类型这样的接口:

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

8
投票
老问题的迟到答案:

您需要在工厂方法外部定义类并使用“typeof”定义返回值。

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

7
投票
我认为这是正确的做法:

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

去游乐场看看吧


2
投票
您还需要导出该类,以便该方法的使用者可以访问该类型。

通常工厂会返回一个实例而不是类或构造函数。

更新示例

export class Foo {}; export let factory = () => { return Foo; };
使用 ES6,你不需要导出类类型,但使用 TypeScript,你绝对应该导出类型签名。


2
投票
我找到了

单独提供的解决方案令人满意:

export class MyClass { ... } export type MyClassRef = new (...args: any) => MyClass;
鉴于该签名,我可以使用 

MyClassRef

 作为返回值类型:

exposeMyClass(): MyClassRef { return MyClass; }
    

1
投票
我正在为同样的错误而苦苦挣扎。我的解决方案是删除

"declaration": true

tsconfig.json

 或将其设置为 
false


0
投票
如何创建返回类的函数。


包括静态函数!!!

我使用泛型来确保工厂的每个实现都有不同的结果,但没有什么可以阻止你在工厂函数中使用 if/else 语句

type Animal = { kind: string, age: number, } type AnimalFactory<T extends Animal> = { new(): { sayAge: () => number; }, validate: (obj: Record<string, unknown>) => obj is T; } function AnimalFactory<T extends Animal>(Base: T): AnimalFactory<T> { return class Animal { sayAge(): number { return Base.age; } static validate(obj: Record<string, unknown>): obj is T { return 'kind' in obj } } } const Dog = AnimalFactory({ kind: 'dog', age: 20 }) const dog = new Dog();
    

-4
投票
您是否正在寻找从函数返回类的类型?下面是一个代码片段,我们如何在 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());
    
© www.soinside.com 2019 - 2024. All rights reserved.