27

Can I refer to angular component class as a type? I see Ionic uses any for components. Is it possible in Typescript to declare an argument type, that expects only component classes?

I saw this question, but components don't have anything in common in constructors: Passing class as parameter causes "is not newable" error

Ebuall
  • 1,306
  • 1
  • 12
  • 14
  • What about the components is it that you care about in this context? Could you use an existing interface like `OnInit` for your needs? In general, components are written as unrelated classes with interfaces mixed in as required. – jonrsharpe Aug 22 '17 at 17:11
  • I care about classes wrapped in Component decorator. – Ebuall Aug 22 '17 at 17:31
  • But that doesn't give them a type, it just attaches some metadata. So, again, what do you actually care about? Are you trying to call methods on them? Accessing properties? Think duck typing - what's the quack? – jonrsharpe Aug 22 '17 at 17:34
  • I am passing them to a router. It renders component. So it needs to be a Component. – Ebuall Aug 22 '17 at 17:50
  • There's only so many ways to say that's not a type. So: – jonrsharpe Aug 22 '17 at 17:50
  • AFAIK the only way to do that would be to override the object prototype with something like getName. I don't know if Angular or Ionic does this. I'd find it useful if it was baked in somewhere. Ionic lazy loading tabbed pages with deep linking... See: https://stackoverflow.com/questions/332422/how-do-i-get-the-name-of-an-objects-type-in-javascript – JGFMK Aug 22 '17 at 17:57
  • just define an interface `RouteComponent` and make all relevent components implement it – Max Koretskyi Aug 22 '17 at 19:12
  • An interface would affect only instances of a class, not a class. It would also involve adding a property to every component. I guess the only way is to write a decorator or override angular's one. I was hoping metadata somehow changes the class but looks like it stored outside of the class. – Ebuall Aug 22 '17 at 20:09

4 Answers4

9

There is ComponentType<T>. Maybe it will help.

import { ComponentType } from '@angular/cdk/overlay'; 
5

As it turns out this is not possible in TypeScript right now. Decorators cannot change type of a class, that means they are invisible for a type system.
More info can be found here:

Ebuall
  • 1,306
  • 1
  • 12
  • 14
3

If they are components that are created dynamically, Angular provides the ComponentRef class.

See here: https://angular.io/api/core/ComponentRef

A statically declared component won't have this class. Although, you can pass around Component identifiers as an untyped variable as needed, as long as you import them into the relevant components / services. If you're using dependency injection, i.e, to inject a component instance into its host directive, the 'type' would just be whatever its name is, like so -

 import { Directive } from '@angular/core'
 import { MyNavigatorComponent } from '../components/my-nav.component'

 constructor (private navigator: MyNavigatorComponent) {
diopside
  • 2,981
  • 11
  • 23
2

From: https://angular.io/api/core/ComponentRef

The Following represents a type that a Component or other object is an instance of.

An example of a Type is MyCustomComponent class, which in JavaScript is represented by the MyCustomComponent constructor function.

Code sample:

import { Type } from "@angular/core";

export type MyDynamicComponentType = Type<any>;
Arun Saini
  • 6,714
  • 1
  • 19
  • 22