TypeScript 中的工厂返回类
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/42634116/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Factory returning classes in TypeScript
提问by Onur Y?ld?r?m
Wrote a library that, depending on the input data; creates classes and uses them inside a main class.
写了一个库,根据输入的数据;创建类并在主类中使用它们。
To make the code more maintainable and readable, I've moved the class generation logic into a separate file that exports a factory function.
为了使代码更易于维护和可读,我将类生成逻辑移到了一个单独的文件中,该文件导出了一个工厂函数。
Code was written in ES2015. Now I'm migrating to TypeScript.
代码是用 ES2015 编写的。现在我正在迁移到 TypeScript。
Here is a pseudo example:
这是一个伪示例:
factory.ts
工厂.ts
export default function (foo:string) => {
class A {
value:string = foo + '-A';
}
return { A };
};
Main.ts
主文件
import factory from './factory';
export default class Main {
private inner:any;
constructor(foo:string) {
this.inner = factory(foo);
}
get a() {
return new this.inner.A();
}
}
Usage:
用法:
let main = new Main('bar');
console.log(main.a.value); // "bar-A"
Problems:
问题:
- TS compiler error:
Default export of the module has or is using private name 'A'.
- Cannot define the type of the getter
a
asA
inMain
class (e.g.get a():A { ... }
- TS 编译器错误:
Default export of the module has or is using private name 'A'.
- 不能
a
像A
在Main
类中那样定义 getter 的类型(例如get a():A { ... }
How would you resolve this (keeping the factory classes in a separate file)? Or should I change the design pattern?
您将如何解决这个问题(将工厂类保存在单独的文件中)?还是我应该改变设计模式?
采纳答案by Nitzan Tomer
How about something like:
怎么样:
export interface Base {}
export interface IA extends Base {
value: string;
}
export type Builders = {
[name: string]: { new <T extends Base>(): T };
}
export function factory(foo: string): Builders {
class A implements IA {
value:string = foo + '-A';
}
return { A };
};
And:
和:
import { factory, IA, Builders } from './Factory';
export default class Main {
private inner: Builders;
constructor(foo:string) {
this.inner = factory(foo);
}
get a():IA {
return new this.inner.A() as IA;
}
}
Edit
编辑
What's wrong with this as factory.ts
:
这有什么问题factory.ts
:
export class Base {}
export type Builders = {
[name: string]: { new <T extends Base>(): T };
}
class A extends Base {
value: string;
constructor();
constructor(foo: string);
constructor(foo?: string) {
super();
this.value = foo + "-A";
}
}
// more classes...
export function factory(foo: string): Builders {
return { A: A.bind(A, foo) };
};
It's basically the same as what you did, just that the classes are not defined inside the class, and are exported so no need for the interfaces I suggested.
Also, this way all the classes will only be evaluated once and not every time the factory
function is invoked.
它与您所做的基本相同,只是类没有在类内部定义,而是导出的,因此不需要我建议的接口。
此外,这样所有的类只会被评估一次,而不是每次factory
调用函数时。
回答by Aidin
Your code (the OP's) is working just fine in July 2019 with Typescript 3.5.2.
您的代码(OP)在 2019 年 7 月使用 Typescript 3.5.2 运行良好。
PS. I got here when I was trying to create a Class Factory in Typescript.
附注。当我试图在 Typescript 中创建一个类工厂时,我来到了这里。
Things to keep in mind:
要记住的事情:
- The concept of Class definition in Typescript has two folds. One is the instance type, and the other one is the constructor function. (source in TS Docs)
- Since Typescript 2.8 released in March 2018, you can explicitly create the instance typefrom the constructor functionusing InstanceType. e.g.
type classType = InstanceType<typeof C>
. This should make the explicittype
definition in the selected answer simpler. - Finally, I got my code working using a simple trick as following:
- Typescript 中类定义的概念有两个方面。一种是实例类型,另一种是构造函数。(TS 文档中的来源)
- 自2018 年 3 月发布的Typescript 2.8 以来,您可以使用InstanceType从构造函数显式创建实例类型。例如。这应该使所选答案中的显式定义更简单。
type classType = InstanceType<typeof C>
type
- 最后,我使用一个简单的技巧让我的代码工作如下:
export default class MyNewClass
extends ClassFactory("custom param1") {}
This way I am actually defining the generated class as a new class by itself, so both the constructor function and the instance-type type are going to be implicitly created and will be valid. And I don't need to explicitly define the two separately.
通过这种方式,我实际上将生成的类定义为一个新类,因此构造函数和实例类型类型都将被隐式创建并且有效。而且我不需要分别明确定义两者。