这是基本的DI模式:
class Foo {
foo = 1;
}
class Bar {
constructor(public Foo: typeof Foo) {
const foo = new Foo();
}
}
class Baz extends Foo {}
new Bar(Baz);
它出错了:
'Foo'在其自己的类型注释中直接或间接引用。
但它显然不是自我引用的,因为public Foo
是属性名称,而typeof Foo
是类型。
这里发生了什么?是否预计将来会解决TypeScript错误?有记录吗?
可以在某种程度上保存Foo
属性名称而不重命名吗?这样命名是有道理的。
public Foo: Foo
似乎不会产生类型问题,而Foo
会引用Foo
中的原始public AnotherFoo: Foo
界面:
class Bar {
constructor(public Foo: Foo, public AnotherFoo: Foo) {
const foo: Foo = AnotherFoo;
foo.foo;
}
}
typeof Foo
引用Foo
参数类型而不是原始Foo
接口:
class Bar {
constructor(public Foo: number, Quux: typeof Foo) {
const quux: number = Quux;
}
}
答案 0 :(得分:5)
问题是构造函数Foo
内部将引用参数而不是类,因此您不能仅通过名称引用Foo
。执行此操作并保留参数名称的最简单方法是声明类型别名:
class Foo {
foo = 1;
}
type FooType = typeof Foo
class Bar {
constructor(public Foo: FooType) {
}
}
Foo : Foo
有效但Foo: typeof Foo
不起作用的原因是在类型:
之后需要类型注释。如果注释是搜索符号时的名称,则只有类型被视为只有它们才有效。
在typeof
之后,期望具有类型的符号的名称(类,局部变量,参数等)。那么搜索必须包含参数,Foo
参数在范围内,因此必须考虑它。
修改强>
@artem提出了一个很好的观点,我没有明确地在上面提到:
[此行为]并非特定于构造函数。在
typeof Foo
中,Foo
引用范围中名为Foo
的最近值(非类型)。一旦你有一个名为Foo
的参数,它就在范围内(你甚至可以用它作为默认值来初始化其他参数),并且它会遮蔽任何名为的外部值。