function getMyComponent(hostFixture: ComponentFixture<any>): MyComponent { const debugElement = hostFixture.debugElement.query(By.directive(MyComponent)); return (debugElement && debugElement.componentInstance) || null; }
这完美无瑕.现在我想概括一下这个函数,以便它可以按需查询任何类型.我认为这可以用泛型类型完成.函数将被调用如下:
const instance: MyComponent = getDirective<MyComponent>(fixture);
我不能让它工作;这是破碎的功能:
function getDirective<T>(hostFixture: ComponentFixture<any>): T { const debugElement = hostFixture.debugElement.query(By.directive(T)); return (debugElement && debugElement.componentInstance) || null; }
TS2693: ‘T’ only refers to a type,but is being used as a value here
这里的语法是什么?我正在调用的Angular函数 – By.directive() – 接受Type< any>类型的参数,并且是documented here
解决方法
function getDirective<T>( hostFixture: ComponentFixture<any>,ComponentConstructor: new (...args: any[]) => T ): T { const debugElement = hostFixture.debugElement.query(By.directive(ComponentConstructor)); return debugElement && debugElement.componentInstance || undefined; }
然后这样称呼它
const instance = getDirective(fixture,MyComponent);
备注:
TypeScript类型纯粹是设计时构造.语言的整个类型系统经过精心设计,可以在转换过程中完全擦除,特别是对程序的运行时行为没有影响.
为什么我要说名称Type< T>是不负责任的?因为成千上万的程序员在Angular的上下文中第一次学习TypeScript.通过命名类型Type,他们很容易误解.
这尤其重要,因为类型Type< T>通常归结为一个类的值,很多人已经将类型与TypeScript和vanilla JavaScript中的类混淆了.
Angular想要将这些概念混为一谈,它希望JavaScript中的类类似于许多其他语言中的类,但它们根本不是.值得注意的是,我更喜欢的Aurelia这样的框架也鼓励这种混淆,但是,因为它们不会尝试强制使用TypeScript,因为它们允许通过类上的属性指定依赖项(可能具有讽刺意味的是AngularJS,混淆)不太可能.无论如何,TypeScript类型,ECMAScript类和依赖注入都是完全正交的概念.
鉴于TypeScript的性质,它只提供设计时类型,这会导致严重的混淆.
值得注意的是,Angular团队设计了他们自己的编程语言,专门用于开发Angular 2的@Script.@ Script是JavaScript和TypeScript的衍生物,它通过添加某种程度的类型设置来区分自己,同时避开装饰器然后竞争注释功能.他们在2014年末放弃了这种语言,而选择使用TypeScript.
我仍然有时认为启发@Script的相同哲学仍会影响Angular.