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

时间:2017-12-13 15:58:12

标签: angular typescript generics

如果我创建一个通用类

class Generic<T> {
     prop: T;
}

如果未在类型

中指定T,我将无法输入内容
// Generic type 'Generic<T>' requires 1 type argument(s).
const val: Generic = new Generic(); 

但如果我使用类型推断,它不会抱怨,它让我实例化它

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)

是否指定了此行为?这背后的原因是什么?

背景

Angular2有EventEmitter,需要一种事件参数。但是,对于某些事件,您不传递任何参数,在这种情况下,我们一直在使用EventEmitter<void>。但是,我只是注意到您可以在不指定类型和new EventEmitter()的情况下定义发射器。这种方法的缺点是如果你将参数传递给emitter.emit('something'),编译器就不会抱怨。这不是我感兴趣的,只是背景,所以读者可以理解问题的来源。

游乐场 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

1 个答案:

答案 0 :(得分:3)

以下两个陈述是等效的......

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

在第一种情况下,右侧省略的类型参数是从左侧的类型推断出来的。

在第二种情况下,您最终会得到一个对象类型,因为无法推断出更具体的内容。

此处的规则是变量的类型必须满足泛型类型参数。当您使用const val: Generic = new Generic();时,不满足type参数 - 您不能要求推断它,因为您已决定对变量进行注释。

所以两个允许的场景是:

  1. 使用类型注释
  2. 自行指定(整个)类型
  3. 允许编译器
  4. 推断(整个)类型

    要使您的后续示例有效,您有两种选择。

    选项1 ...如果你真的不想限制类型,那就去动态......

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

    或者......选项2 ...如果你想要限制类型,请指定它。

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

    最后,在许多情况下,您不需要指定类型参数,因为它可以在上下文中推断。