给定具有静态Foo<T>
方法的通用类factory
:
class Foo<T>
{
public static factory(item: T): Foo<T>
{
return null;
}
}
为什么不编译?
var f = Foo<number>.factory(1);
错误消息:
错误TS2069:参数列表必须遵循泛型类型参数列表。 &#39;(&#39;预期。
但这确实可以编译:
var f = Foo<number>().factory(1);
为什么需要括号?这是调用构造函数吗?
答案 0 :(得分:18)
正如静态方法无法访问实例成员一样,静态方法也不能使用实例类型参数。
因此,您的静态方法必须是通用的并接受类型参数。我通过在静态函数中使用U
和在类中使用T
来强调这一点。请务必记住,T
的实例类型与U
的静态方法类型不同。
class Foo<T>
{
public static factory<U>(item: U): Foo<U>
{
return new Foo<U>();
}
instanceMethod(input: T) : T
{
return input;
}
}
然后通过在括号之前传递类型参数来调用它,如下所示:
var f: Foo<number> = Foo.factory<number>(1);
当可以进行类型推断时,可以删除类型注释:
var f: Foo<number> = Foo.factory(1);
变量f
是Foo
的实例,其类型参数为number
,因此instanceMethod
方法只接受number
类型的值(或any
)。
f.instanceMethod(123); // OK
f.instanceMethod('123'); // Compile error
答案 1 :(得分:1)
这里的要点是,静态通用模板与类(因此实例)模板无关。因此,我们必须区分它们(如在C#I中所说的那样)
// generic here is T
class Foo<T>
{
public TheT: T;
constructor(t: T)
{
this.TheT = t;
}
// the static one is U
public static factory<U>(item: U): Foo<U>
{
var result = new Foo<U>(item);
// the U here will be T inside of the instance
return result;
}
}
我们可以这样称呼:
var f = Foo.factory(<Number> 1);
答案 2 :(得分:0)
我认为正在发生的事情是TypeScript编译器正在看Foo<number>
,并期望这是一个对象类型,即
var f: Foo<number>;
由于在javascript中将类编译为范围函数,因此在添加括号时,您实际上是在初始化对象是。
Typescript可能会在没有()
的情况下引发编译错误,因为它不能假设您打算初始化该类。