[英]new EventEmitter() vs new EventEmitter<Something>()
Let's say I have this code: 假设我有以下代码:
export class ProductsListComponent {
@Output() onProductSelected: EventEmitter<Product>;
constructor() {
this.onProductSelected = new EventEmitter();
}
}
This is some example of EventEmitter
usage. 这是EventEmitter
用法的一些示例。 I don't understand why first we declare onProductSelect explicitly stating that it is EventEmitter
that carries Product instance, and then we instantiate it with just new EventEmitter()
. 我不明白为什么我们首先明确声明onProductSelect声明它是携带Product实例的EventEmitter
,然后仅使用new EventEmitter()
实例化它。 Why not new EventEmitter<Product>()
? 为什么不new EventEmitter<Product>()
?
I think that in C# I would have to go with the second way, because otherwise it wouldn't compile if EventEmitter
was generic. 我认为在C#中,我将不得不采用第二种方式,因为如果EventEmitter
是通用的,否则它将无法编译。 Why doesn't TypeScript require that? 为什么TypeScript不要求?
//EDIT: //编辑:
Further clarification fo my question. 我的问题需要进一步澄清。 What's the difference between: 之间有什么区别:
@Output() onProductSelected: EventEmitter<Product>;
this.onProductSelected = new EventEmitter();
and 和
@Output() onProductSelected: EventEmitter;
this.onProductSelected = new EventEmitter();
As explained in documentation chapter , type argument inference occurs when type isn't specified for generic class or function. 如文档章节所述 ,当未为通用类或函数指定type时,将发生类型实参推断。
A function can infer T
type from its argument or return types, and a class can infer T
type from constructor argument or return types: 函数可以推断T
从它的参数类型或返回类型,而一个类可以推断T
从构造器参数类型或返回类型:
function foo<T>(v: T) { return v }
foo(1); // T inferred to number
class Foo<T> {
constructor(v: T) {}
}
new Foo(1); // T inferred to number
If there's nothing to infer, T
is inferred to empty object {}
for some reason : 如果没有什么可以推断的,则出于某种原因 , T
被推断为空对象{}
:
class Foo<T> {
foo(v: T) {}
}
new Foo().foo(1); // T inferred to {}
In order to avoid inference to {}
, default type can be provided: 为了避免推论{}
,可以提供默认类型:
class Foo<T = string> {
foo(v: T) {}
}
new Foo().foo(1); // type error
If generic class or function isn't supposed to be used with default type, some impossible type can be specified: 如果不应将通用类或函数与默认类型一起使用,则可以指定一些不可能的类型:
class Foo<T = never> {
foo(v: T) {}
}
new Foo(); // no type error, T isn't involved
new Foo().foo(<any>1); // type error
Since EventEmitter
generic class has no default type specified, the latter is inferred to {}
. 由于EventEmitter
泛型类未指定默认类型,因此后者被推断为{}
。 There usually won't be problems with that, because emit
is the only method that is affected by generic type . 通常不会有任何问题,因为emit
是唯一受泛型类型影响的方法 。 Since all non-nully types can be coerced to object type, this usually won't cause type errors - as long as nully types are ignored. 由于所有非null类型都可以强制转换为对象类型,因此只要忽略null类型,通常就不会导致类型错误。
strictNullChecks
compiler option will be a problem for EventEmitter
with default type and nully values: 对于使用默认类型和空值的EventEmitter
, strictNullChecks
编译器选项将是一个问题:
const ee = new EventEmitter();
ee.emit(null); // type error
So for all-round EventEmitter
it shouldn't rely on default type and be instantiated as: 因此,对于全方位EventEmitter
它不应依赖默认类型,而应实例化为:
const ee = new EventEmitter<any>();
EventEmitter()
will work the same as EventEmitter<any>()
. EventEmitter()
与EventEmitter<any>()
。 If you draw this in HTML on the selector of ProductsListComponents
, then you can listen to onProductSelected
event and assign an action like onSelected
when that happens. 如果您在HTML上在ProductsListComponents
的选择器上绘制此内容,则可以侦听onProductSelected
事件,并在发生这种情况时分配类似onSelected
的操作。 By default you'll get a new EventEmitter<any>()
, and defining a variable of any
type is the generic approach in Typescript. 默认情况下,您将获得一个新的EventEmitter<any>()
,并且定义any
类型的变量都是Typescript中的通用方法。
<product-list (onProductSelected)="onSelected($event)"> </product-list>
So every time in your child you call 所以每次你的孩子你打电话
this.onProductSelected.emit("hello");
this.onProductSelected.emit(1);
Parent's function onSelected($event)
will get called and you can do anything with that data. Parent的函数onSelected($event)
将被调用,您可以使用该数据执行任何操作。
If you're only expecting one type of data to get outputted to the parent so it can further handle it, then you'd want to stick to a specific data type. 如果您只希望将一种类型的数据输出到父级以便可以进一步处理它,那么您就希望坚持使用一种特定的数据类型。
onProductSelected: Product = new EventEmitter<Product>();
products: Product[];
then somewhere in your code you can trigger to emit 然后您可以在代码中的某处触发发出
this.onProductSelected.emit(this.products[1]);
Added an example in stackblitz 在stackblitz中添加了一个示例
Regarding your updated question 关于您更新的问题
@Output() onProductSelected: EventEmitter;
is an error, because here you're declaring a type (after :
, before =
), as oppose to defining a type (after =
), when you declare it as an EventEmitter you do need an argument <type>
是一个错误,因为在这里您声明一个类型(在:
之后, =
之前),与定义一个类型(在=
之后)相反,当您将其声明为EventEmitter时,确实需要一个参数<type>
If you declare the type of EventEmitter, then the compiler will make sure you don't emit anything other than Product type, or what type you declare it to be. 如果声明了EventEmitter的类型,则编译器将确保您不发出除Product类型或声明为哪种类型以外的任何东西。
@Output() onProductSelected: EventEmitter<Product>;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.