Choosing classes as types over interfaces & type aliases in TypeScript.

Thabo Ambrose
2 min readOct 29, 2022


Typed code is a breeze to work with

Why would I use a class as a type?

Because interfaces and type aliases are not present at runtime.

Example usecases

Type guards

@Input() content!: Type<unknown> | TemplateRef<Element>

In place of Type<unknown>, you can also use ComponentType<unknown>
imported from the CDK (@angular/cdk/portal) or maybe that’s a bad idea. I dunno.

With the above declaration, I can do the following because classes and functions exists at runtime. Type and TemplateRef are both construct-able types.

Type<T> represent a constructable type T which can be a Component class or some other type representing a type of an object. We do not know T or what will be T at this point so we use the unknown type. Because Component is an interface, we cannot use it in type guards. That is why we use the FunctionConstructor type Type to guard for a component input which will result to typeof === ‘function’.

TemplateRef<T> represents an abstract class type therefore we can use the instanceof TemplateRef to guard for a template input.

if(typeof this.content === 'function') {
console.log('Handle component instantiation');

if(this.content instanceof TemplateRef) {
this.contentTemplate = this.content;

TypeScript will give an error if the type guard is used with an interface or a type alias. Some error like below

SomeType only refers to a type, but is being used as a value here

Initial class property values

Another benefit of using classes as types is that you can avoid the below TS error in classes when defining class properties.

Property 'someProperty' has no initializer and is not definitely assigned in the constructor.

With classes you can quiet the error by using the class type initial instance as the default value by instantiating it like below.

someProp: SomeClass = new SomeClass();

And then what????