简体   繁体   English

在不指定类型的情况下实例化TypeScript通用类

[英]Instantiating TypeScript generic class without specifying type

If I create a generic class 如果我创建一个通用类

class Generic<T> {
     prop: T;
}

It won't allow me to type something without specifying T in the type 如果不在类型中指定T ,就不允许我输入内容

// Generic type 'Generic<T>' requires 1 type argument(s).
const val: Generic = new Generic(); 

But if I use type inference, it doesn't complain, it lets me instantiate it 但是如果我使用类型推断,它不会抱怨,它可以实例化它

const val = new Generic();
// field prop is not of type any, we can't access any properties on it
// val.prop.anything -> Compiler error
// val.prop.toString() -> No error, is it a string?
// val.prop.length -> Compiler error, not a string, just assumes that everything has a toString (based on boxing)

Is this behavior specified? 是否指定了此行为? What is the reasoning behind this? 这背后的原因是什么?

Background 背景

Angular2 has an EventEmitter which requires a type of the argument for the event. Angular2有一个EventEmitter ,它需要事件的参数类型。 However, for some events, you don't pass any arguments, in which case we had been using EventEmitter<void> . 但是,对于某些事件,您不传递任何参数,在这种情况下,我们一直在使用EventEmitter<void> However, I just noticed that you can just define emitters without specifying type and new EventEmitter() works. 但是,我刚刚注意到,您可以仅定义发射器而无需指定类型, new EventEmitter()可以工作。 The drawback of this approach is that the compiler won't complain if you pass an argument to emitter.emit('something') . 这种方法的缺点是,如果您将参数传递给emitter.emit('something') ,编译器将不会抱怨。 This is not what I'm interested in, just background so readers can understand where the question came from. 这不是我感兴趣的,只是背景,因此读者可以了解问题的出处。

Playground https://www.typescriptlang.org/play/#src=class%20Generic%3CT%3E%20%7B%0D%0A%20%20%20%20prop%3A%20T%3B%0D%0A%7D%0D%0A%0D%0Aconst%20val%3A%20Generic%20%3D%20new%20Generic()%3B%0D%0A%0D%0Aconst%20val2%20%3D%20new%20Generic()%3B%0D%0A%0D%0Aval2.prop.test%20%3D%201%3B 游乐场 https://www.typescriptlang.org/play/#src=class%20Generic%3CT%3E%20%7B%0D%0A%20%20%20%20prop%3A%20T%3B%0D%0A% 7D%0D%0A%0D%0Aconst%20val%3A%20Generic%20%3D%20new%20Generic()%3B%0D%0A%0D%0Aconst%20val2%20%3D%20new%20Generic()%3B% 0D 0A%%0D%0Aval2.prop.test%20%3D%201%3B

The following two statements are equivalent... 以下两个语句是等效的...

const val: Generic<{}> = new Generic();
const val2 = new Generic();

In the first case, the type argument that is omitted on the right-hand side is inferred from the type on the left-hand side. 在第一种情况下,从左侧的类型推断出在右侧省略的type参数。

In the second case, you end up with an object type, because nothing more specific can be inferred. 在第二种情况下,您最终得到的是对象类型,因为无法推断出更具体的信息。

The rule here is that the type of the variable must have the generic type parameter satisfied. 此处的规则是变量的类型必须满足通用类型参数。 When you use const val: Generic = new Generic(); 当您使用const val: Generic = new Generic(); the type parameter is not satisfied - you can't ask for it to be inferred because you have decided to annotate the variable. type参数不满足-您无法要求对其进行推断,因为您已决定对变量进行注释。

So the two allowable scenarios are: 因此,两个允许的方案是:

  1. Specify the (entire) type yourself with a type annotation 用类型注释自己指定(整个)类型
  2. Allow the (entire) type to be inferred by the compiler 允许(整个)类型由编译器推断

To make your later example work, you have two options. 为了使后面的示例生效,您有两个选择。

Option 1... if you really don't want to limit the type, go dynamic... 选项1 ...如果您真的不想限制类型,请动态选择...

const val2 = new Generic<any>();
val2.prop.test = 1;

Or... Option 2... if you do want to limit the type, specify it. 或者......选项2 ...如果想限制类型,指定它。

const val2 = new Generic<{ test: number }>();
val2.prop.test = 1;

And finally, in many contexts, you don't need to specify the type argument as it can be inferred contextually. 最后,在许多情况下,您无需指定type参数,因为可以根据上下文进行推断。

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

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