TypeScript classes support static properties that are shared by all instances of the class. A natural place to put (and access) them is on the class itself and that is what TypeScript does: class Something. Static instances = 0; constructor. TypeScript has some special inference rules for accessors: If no set exists, the property is automatically readonly The type of the setter parameter is inferred from the return type of the getter If the setter parameter has a type annotation, it must match the return type of the getter. Note: this story goes into some advanced TypeScript. I’m going to assume you know what decorators, type aliases and generics are. How do I create a mapped type that extracts only the properties that have been annotated by my property decorator? This question is a little abstract so let’s look at it through an example. TypeScript supports the abstract keyword for classes and their methods, properties, and accessors. An abstract class may have methods, properties, and accessors with no implementation, and cannot be constructed. See Abstract classes and methods and Abstract properties and accessors for more information. Mixins and Compositional Classes.
- Typescript Abstract Class Method
- Typescript Abstract Static Property
- Typescript Abstract Property Examples
- Typescript Private Abstract Property
- Typescript Static Method
Typescript Abstract Class Method
If you are doing traditional OOP with TypeScript, the structural features of TypeScript mightsometimes get in your way. Look at the following class hierachy for instance:
The FilterItem
abstract class needs to be implemented by other classes. In this example byAFilter
and BFilter
. So far, so good. Classical typing works like you are used to fromJava or C#:
When we need the structural information, though, we leave the realms of traditional OOP.Let’s say we want to instantiate new filters based on some token we get from an AJAX call.To make it easier for us to select the filter, we store all possible filters in a map:
The map’s generics are set to a string (for the token from the backend), and everythingthat complements the type signature of FilterItem
. We use the typeof
keyword hereto be able to add classes to the map, not objects. We want to instantiate them afterwards,after all.
Typescript Abstract Static Property
So far everything works like you would expect. The problem occurs when you want tofetch a class from the map and create a new object with it.
What a problem! TypeScript only knows at this point that we get a FilterItem
back,and we can’t instantiate FilterItem
. Since abstract classes mix type information andactualy language (something that I try to avoid), a possible solution is to move tointerfaces to define the actual type signature, and be able to create properinstances afterwards:
Note the new
keyword. This is a way for TypeScript to define the type signatureof a constructor function.
Lots of 💣s start appearing now. No matter where you put the implements IFilter
command, no implementation seems to satisfy our contract:
What’s happening here? Seems like neither the implementation, nor theclass itself seem to be able to get all the properties and functionswe’ve defined in our interface declaration. Why?
JavaScript classes are special: They have not only one type we could easilydefine, but two types! The type of the static side, and the type of the instanceside. It might get clearer if we transpile our class to what it was before ES6:a constructor function and a prototype:
One type to create the object. One type for the object itself. So let’s splitit up and create two type declarations for it:
Typescript Abstract Property Examples
The first type FilterConstructor
is the constructor interface. Here are all static properties,and the constructor function itself. The constructor function returns an instance: IFilter
.IFilter
contains type information of the instance side. All the functions we declare.
Typescript Private Abstract Property
By splitting this up, our subsequent typings also become a lot clearer:
Typescript Static Method
- We add
FilterConstructor
s to our map. This means we only can add classes thatprocude the desired objects. - What we want in the end is an instance of
IFilter
. This is what the constructorfunction returns when being called withnew
.
Our code compiles again and we get all the auto completion and tooling we desire.Even better: We are not able to add abstract classes to the map. Because they don’tprocude a valid instance:
Traditional OOP, weaved in into our lovely type system. ✅
☕️ Was this helpful? Leaving a small tip helps me a lot!