繁体   English   中英

Typescript 中的 Angular:如何将泛型类型传递给函数

[英]Angular in Typescript: how to pass generic Type to function

使用 Typescript 编写 Angular 5 单元测试,我有一个函数可以查询 DOM 并在找到时返回MyComponent类的实例:

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' 仅指一种类型,但在此处用作值

这里的正确语法是什么? 我正在调用的 Angular 函数 -- By.directive() -- 接受类型为Type<any>的参数,并在此处记录

Angular 的Type<T>是一个糟糕的 API。 您是许多被其坦率不负责任的命名误导的人之一(见评论)。 Type<T>真正意味着可构造。 它是您可以使用new调用的值的类型。

By.directive接受一个而不是一个类型。 该值的类型是可以用new调用的,可以构造的。 这意味着一个类或一个函数。

但是,您可以编写您想要的功能。

这就是我的写法。

export function getDirective<T>(
  hostFixture: ComponentFixture<any>, 
  ComponentConstructor: new (...args: unknown[]) => T
): T {
  const debugElement = hostFixture.debugElement.query(By.directive(ComponentConstructor));

  return debugElement && debugElement.componentInstance || undefined;
}

然后像这样调用它

const instance = getDirective(fixture, MyComponent);

评论:

TypeScript 类型是纯粹的设计时构造。 该语言的整个类型系统经过精心设计,可以在编译期间完全擦除,尤其是对程序的运行时行为没有影响。

为什么说Typ​​e Type<T>这个名字不负责任呢? 因为成千上万的程序员是第一次在 Angular 的上下文中学习 TypeScript。 通过命名一个类型 Type,他们让事情变得很容易被误解。

这一点尤其重要,因为Type<T>通常被赋予一个类的值,并且许多人已经将类型与 TypeScript 和 vanilla JavaScript 中的类混淆了。

Angular 希望将这些概念混为一谈,它希望JavaScript 中的类与许多其他语言中的类型一样,但事实并非如此。 值得注意的是,我更喜欢 Aurelia 之类的框架也鼓励这种混淆,但是,因为它们不尝试强制使用 TypeScript,并且因为它们允许通过类上的属性来指定依赖项(可能具有讽刺意味的是,在方式或 AngularJS 中,混淆无论如何,TypeScript 类型、ECMAScript 类和依赖注入都是完全正交的概念。

鉴于 TypeScript 的性质,它只提供设计时类型,这会导致严重的混乱。

有趣的是,Angular 团队设计了他们自己的编程语言,称为 @Script 专门用于 Angular 2 的开发。@Script 是 JavaScript 和 TypeScript 的衍生品,它通过添加某种程度的类型具体化同时避开装饰器来区分自己。然后竞争注释功能。 他们在 2014 年底放弃了这种语言,转而使用 TypeScript。

尽管如此,我有时仍然认为激发@Script 的相同理念仍然影响着 Angular。

暂无
暂无

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

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