How inheritance in Typescript works behind the curtain? Typescript and JavaScript are both impressive languages. Typescript feels more familiar to a wide range of developers because it offers concepts we usually encounter in traditional languages. Inheritance is one of them. programming But TypeScript doesnât run in the Browser. We need to compile it to . Mostly ES5, which doesnât contain classes nor an extend keyword. JavaScript So how does this work then? Typescript uses syntactic sugar to the class and inheritance behavior. It creates kind of an illusion of those concepts. Letâs see what I mean by that. âmimicâ In this blogpost we will dive deep. On our way we will encounter a lot of concepts. It is important to wrap your head around those concepts. Take your time and make some breaks if necessary. You donât have to understand everything in one read. Letâs set up a new TypeScript project to illustrate what happens behind the curtain. To create a new empty Typescript project letâs run the following command: tsc --init This establishes us a which the TypeScript compiler will use to compile our code. Currently, it wonât do anything because we havenât written any code yet. Letâs go on and do so by adding an index.ts: tsconfig.json The class acts as a base class which derives of. accepts a name and favorite food as a constructor parameter. It passes the name via a super call to and assigns the favorite food parameter to private property. Foo Bar Bar Foo We then instantiate and and call greet and talk. is only able to greet because it extends . Nothing fancy here. bar1 bar2 Bar Foo The code above shows the syntactic sugar I was talking about in the beginning. It allows us to write inheritance in a classical way that we are used from other languages like Java or C#. But how does this work then? Letâs run the command to have a look at the âunsugaredâ version. tsc Donât spend too much time to investigate this codeâââwe will cover that later. Wow! Thatâs a lot of extra code. On first glance we can see that all the sugar disappearedâââno classes anymore. But at least we recognize some of the things we wrote before. We can still see Foo and Bar which now turned into IFFE stands for . As the name indicates it represents a function that gets immediately executed đ âiffeâsâ. âimmediately invoked function expressionâ But thereâs a lot of extra stuff added. Whatâs the purpose of this method? __extends To understand this code letâs first take a step back and write the same functionality in plain old JavaScript. Back to the roots! â€ïž Inheritance in vanilla JavaScript This code does the same as the Typescript version. Even though the code seems to be simple, there are a lot of things to understand. It is important that we get the mental concept behind it. To visualize those concepts, we will use the same graphical representation Kyle Simpson ( ) used on his âYou donât know JSâ series. Kyle By the way. If you havenât read them yet, I highly recommend you to do so. They are great! In his book about âthis and object prototypesâ Kyle represents functions with circles and object with squares. So letâs see how the JS code from above would be represented in such a graphical representation. đ or medium to get notified about the newest blog posts and interesting frontend stuff! Follow me on Twitter When line one executes, itâs going to create a function . Notice that it also creates an object which is the prototype of the function. Foo Foo Foo(name) { .name = name;} function this The function contains a linkage to an object. As the linkage indicates, the object acts as Fooâs prototype. But what about the property? Foo .prototype .constructor Donât get confused by its name. It has nothing to do with construction. Itâs just an internal linkage from the prototype back to the function. 2. Letâs go to line 5. In this line, we add the greet function to the prototype. Foo.prototype.greet = () {console.log(`Hi I am ${ .name}`);}; function this 3. Line 9 then creates the function: Bar Bar(name, favouriteFood) { .favouriteFood = favouriteFood;Foo.call( , name);} function this this 4. Line 14 is where things become interesting. Bar.prototype = Object.create(Foo.prototype); is a method thatâs around since ES5. It creates a brand new object and links it to the prototype we pass in as an argument. In other words, we create a brand new object that is linked to Fooâs prototype. Object.create We then take this Object and assign it to Barâs prototype. This results in the following picture. Notice that the linkage between and is represented by . The is just an internal linkage from one object to another object. Bar.prototype Foo.prototype [[Prototype]] [[Prototype]] Probably you already heard about âProtoype Chainâ? The prototype chain is the reason why instances of bar can call the greet function. It allows objects to delegate a method call to a different object. The is part of this chain. [[Prototype]] So basically if somebody calls greet on bar it will be checked if greet exists on . If notâââit follows the internal linkage until it finds a greet method or until the chain ends. If the chain ends it returns undefined. Bar.prototype [[Prototype]] While is an internal linkage there is also a public linkage called . This linkage was invented by Mozilla but has never been standardized. Nevertheless everybody adopted it except IE. đ€Ș [[Prototype]] __proto__ 5. Currently, is quite friendly, it is linked to and therefore able to greet. But it is still very shy. Line 16 to 18 changes that. will now tell you what his favorite food is, which indeed is very useful ;) bar Foo Bar Bar.prototype.talk = () {console.log(`${ .name}: I love ${ .favouriteFood}!`);}; function this this 6. Ok. Cool. We created this whole concept but the current code does nothing. So letâs create objects and call some methods on it. Bar('bar one'); Bar('bar two'); var bar1 = new var bar2 = new The picture is now complete đšâđš (actually there is still more stuff going on, but thatâs beyond the scope of this post) to tweet about this article đ„ Click here and also get linked to . Thanks to the linkages we now have the correct prototype chain and can call and on and . bar1 bar2 talk greet talk bar1 bar2 We now clearly understand what the vanilla JS code does and what the mental concept behind the code is. Cool, but what about the Typescript code? Yes, the goal of this blog post is to take a deep dive to Typescript inheritance. We will do so in a second. The things we have done so far were just necessary steps to better understand the next section. So now that we are ready, letâs dive! đ Letâs start by looking closer at the lines from 15 to 36. Our Typescript classes disappeared and almost turned into our ES5 code we wrote before. and are now wrapped inside an IIFE (Immediately-invoked function expression). The IIFE allows us to capture the base object as a variable. Foo Bar If we compare it with the plain JS code we wrote, we can see that our method is gone. Instead, we now see a method which is called inside . This method is important to understand as it is responsible for the âinheritanceâ magic. So letâs have a closer look. Object.create __extends Bar __extends We will split method into two parts. First, we have a look at the method, and then we move on to the function that gets returned. __extends extendStatics extendStatics is a function that gets called with two parametersââ and . represents the derived class ( ) and the base class ( ). extendStatics d b d Bar b Foo First, it is checked if exists. If not then Object.setPrototypeof ({ __proto__: [] } Array && (d, b) { d.__proto__ = b; }) instanceof function will be applied. If both checks return false we will apply the third function which is (d, b) { ( p b) (b.hasOwnProperty(p)) d[p] = b[p]; }; function for var in if All of those function achieve the same. The checks are necessary due to backward compatibility. The last method is the one that will be used if the first two are not supported. It is also the most readable and explains best what does. extendStatic It checks if a property exists on the base class. If so, this property will be copied to the derived class. Generally spoken it copies the static members of the base class to the child class. Ok. This was the easy part. Letâs have a look at the harder part. We can do this! đȘ Rebuild prototypical inheritance This part is quite tricky and may require some reads to understand it. We skip the first line as it is clear. We call the method described above. extendStatics On line 3 we create a named function called . We will discuss the meaning of it soon. I think the best way to understand this code is by looking at the last line first. __ d.prototype = b === ? Object.create(b) : (__.prototype = b.prototype, __()); null new Read this method carefully multiple times. Donât worry if you donât know what this method does. This line of code contains a lot of logic. To explain this method better, I prefer to refactor this line to a more readable version. Letâs refactor! (b === ) {d.prototype = Object.create(b);} {__.prototype = b.prototype;d.prototype = __();} if null else new Ok. As we already knowââ equals and equals . By the time we enter this function is and therefore defined, which results in the execution of the else part. b Foo d Bar b Foo To visualize things I am again going to use the notation of functions as circles and objects as squares. At the time we enter the function, and are already defined. b d Next we the following line gets executed: function __() { this.constructor = d } This results in another function called and its prototype. We also get the already covered and linkages. __ .constructor .prototype Then the first line inside the else statement of our refactored code gets called. __.prototype = b.prototype; We change the linkage of to . __.prototype b.prototype Great! Almost there. Only one line left. To understand the last line one more prerequisite is required. We need to understand the effects of the new keyword on a function call. The new keyword in JavaScript differs from the new keyword in traditional languages. In JavaScript, a constructor is just a function that gets called with a new Keyword. Each regular function can be called with a Keyword. There are four things happening when you call a function with the Keyword. new new A brand new object gets created. This object gets [[Prototype]] linked. [[Prototype]] The object gets set as this binding. The object gets returned. In the last line, we call with new __ d.prototype = __(); new By calling new on we create a brand new object out of thin air. This object then gets linked to the prototype of the function which is . We then take this object and assign it to . __ __ Foo.prototpye Bar.prototype Wow, looks quite familiar to the ES5 diagram, doesnât it? But what happened to the talk method? Shouldnât it be on âs prototype? Bar The reason it is not on is simple. It hasnât yet been added. Bar We can see that getâs added after we executed the extends method. In the end, we then create and . The complete diagram then looks like the following: Bar.prototype __ bar1 bar2 As you may have noticed it is the same as the plain ES5 diagram. Conclusion Typescript is an excellent language and offers us a lot of benefits over Javascript. Nevertheless, I have seen way too many frontend developers that use TypeScript but have no clue about JavaScript. Always remember that at runtime it is JavaScript that gets executed. Therefore, in my opinion, it is essential to have a solid JavaScript understanding. đ§â đ By the way, click on the đđ» clap đđ»button on the left side if you enjoyed this post. Claps help other people finding it and encourage me to write more posts đ Feel free to check out some of my other blogs: _Method overloading is a familiar concept from traditional programming languages like Java or C#. It basically allows aâŠ_medium.com Typescript method overloading _Alternate approaches to handle source maps_blog.angularindepth.com Debug Angular apps in production without revealing source maps _Different approaches with their pros and cons_medium.com Angular: Refetch data on same URL navigation