Enter Your Email Address to Watch This Lesson

Your link to unlock this lesson will be sent to this email address.

Unlock this lesson and all 1023 of the free egghead.io lessons, plus get TypeScript content delivered directly to your inbox!



Existing egghead members will not see this. Sign in.

Create a fluent API using TypeScript classes

3:09 TypeScript lesson by

You can create an easy to chain API using TypeScript classes. Learn about the this return type annotation and how it plays with function chaining and class inheritance.

Get the Code Now
click to level up

egghead.io comment guidelines

Avatar
egghead.io

You can create an easy to chain API using TypeScript classes. Learn about the this return type annotation and how it plays with function chaining and class inheritance.

Here I have a simple class called adder. It has protected member called accumulator which I'm going to go ahead and initialize to zero. It also has an add method which takes a value of type number, it adds this value to the accumulator, and finally it returns this.

Returning this from a method allows us to chain additional instance numbers after our method invocation. Finally, I will add a result getter which simply returns the current accumulator value.

Let's go ahead and create an instance of the class. If I go ahead and access the add method, you can see that because it returns this, the return value here is an instance of the class adder. That allows us to chain method calls for the add method. For example, we can add 1, then add 10, then add 100.

Whenever we want to get the result, we simply use the result getter. If I go ahead and console log the result of these additions, and then run the file, you can see that the result is 111.

If you go ahead and look at the inferred type for the add method, you can see that it's return annotation is this. If you wanted, you could go ahead and add an explicit annotation of type adder to the return for the add method. However, it would not be the same as the this annotation, which was being inferred, which we can also specify explicitly.

But since it's being inferred anyway, I'll go ahead and remove. The purpose of this return annotation becomes clear when you consider class inheritance.

As an example, let's go ahead and create a mobile [inaudible 1:52] class that extends the adder class. We will go ahead and another Fluent API member, called subtract, which takes a value of type number. The method body takes this value, subtracts it from the inherited accumulator member, and finally returns this.

Let's go ahead and create an instance of this new calculator class. If you go ahead and access the inherited add member, you will notice that the return type is inferred to be an instance of calculator instead of adder.

That is because the this return type changes its meaning based on how the function is invoked. Since here it is invoked on the calculator, TypeScript has gone ahead and inferred the return type to be a calculator. This allows us to chain calculator-specific methods on the return of the inherited add method.

For example, we can subtract, then we can add again, then we can subtract, and then we can get the result from the property that calculator inherited from adder.

If I go ahead and log the result and then run the file, it gives the result of the additions and subtractions as expected.

HEY, QUICK QUESTION!
Joel's Head
Why are we asking?