{"id":7138,"date":"2019-06-08T19:56:19","date_gmt":"2019-06-08T19:56:19","guid":{"rendered":"http:\/\/putridparrot.com\/blog\/?p=7138"},"modified":"2019-06-08T19:56:19","modified_gmt":"2019-06-08T19:56:19","slug":"typescript-constructor-parameter-properties","status":"publish","type":"post","link":"https:\/\/putridparrot.com\/blog\/typescript-constructor-parameter-properties\/","title":{"rendered":"TypeScript constructor parameter properties"},"content":{"rendered":"<p>TypeScript offers a short-cut to creating properties\/fields from the parameters declared on the constructor. <\/p>\n<p>For example, if we declare our class and constructor like this<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nclass Person {\r\n    constructor(name: string, age: number) {\r\n    }\r\n}\r\n\r\nlet p = new Person(&quot;Scooby&quot;, 10);\r\np.name = &quot;Doo&quot;;\r\n<\/pre>\n<p>The TypeScript transpiler will display the error <em>&#8220;Property &#8216;name&#8217; does not exist on type &#8216;Person'&#8221;<\/em> and obviously the parameters name and age will not exist within the Person class as they&#8217;ve not been declared. <\/p>\n<p>However if we prefix the parameters with either <em>public<\/em>, <em>private<\/em>, <em>protected<\/em> or <em>readonly<\/em> then TypeScript generates properties on the Person object automatically for us.<\/p>\n<p><strong>protected parameter properties<\/strong><\/p>\n<p>As you&#8217;d probably expect, with the accessor of <em>protected<\/em> properties are generated which are visible to the Person object and any subclass of the Person. <\/p>\n<p>For example<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nclass Person {\r\n    constructor(protected name: string, protected age: number) {\r\n    }\r\n}\r\n<\/pre>\n<p>When we run this through the transpiler we get the following<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nvar Person = \/** @class *\/ (function () {\r\n    function Person(name, age) {\r\n        this.name = name;\r\n        this.age = age;\r\n    }\r\n    return Person;\r\n}());\r\n<\/pre>\n<p>If we attempt to access the properties name and age from outside the class (using TypeScript) then we&#8217;ll get the error <em>&#8220;Property &#8216;name&#8217; is protected and only accessible within class &#8216;Person&#8217; and its subclasses.&#8221;<\/em>.<\/p>\n<p><strong>private parameter properties<\/strong><\/p>\n<p>If we now change the accessors to private, for example<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nclass Person {\r\n    constructor(private name: string, private age: number) {\r\n    }\r\n}\r\n<\/pre>\n<p>The transpiler will, again, create the same output as the previous JavaScript code, but the generated properties, from the TypeScript point of view, are only accessible from the Person class. Trying to access them from outside of the Person class will result in the following error, <em>&#8220;Property &#8216;name&#8217; is private and only accessible within class &#8216;Person&#8217;.<\/em>.<\/p>\n<p><strong>public parameter properties<\/strong><\/p>\n<p>Changing the accessors to <em>public<\/em> will, as you probably expected, create public properties\/fields which are accessible outside of the Person class, here&#8217;s the altered source code.<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nclass Person {\r\n    constructor(public name: string, public age: number) {\r\n    }\r\n}\r\n<\/pre>\n<p>Ofcourse, the JavaScript code is unchanged.<\/p>\n<p><strong>readonly parameter properties<\/strong><\/p>\n<p>Finally, if we now change the accessors to <em>readonly<\/em>, for example<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nclass Person {\r\n    constructor(readonly name: string, readonly age: number) {\r\n    }\r\n}\r\n<\/pre>\n<p>The transpiler will generate, what appears to be, getters only. Hence trying to interact with these properties outside of the class will result in the following error <em>&#8220;Cannot assign to &#8216;name&#8217; because it is a read-only property.&#8221;<\/em><\/p>\n<p>Whilst JavaScript can support the concept of readonly properties, the transpiler does not go this route (shown below)<\/p>\n<p><strong>Readonly properties in JavaScript<\/strong><\/p>\n<p>If we take the code generated by the transpiler, we could add the following<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nObject.defineProperty(Person.prototype, &quot;name&quot;, {\r\n    value: &quot;name&quot;,\r\n    writable: false\r\n});\r\n<\/pre>\n<p>and when run (assuming we try to assign a value to <em>name<\/em>), we&#8217;ll get the following error <em>&#8220;Cannot assign to read only property &#8216;name&#8217; of object &#8216;#<Person>&#8216;&#8221;<\/em>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>TypeScript offers a short-cut to creating properties\/fields from the parameters declared on the constructor. For example, if we declare our class and constructor like this class Person { constructor(name: string, age: number) { } } let p = new Person(&quot;Scooby&quot;, 10); p.name = &quot;Doo&quot;; The TypeScript transpiler will display the error &#8220;Property &#8216;name&#8217; does not [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[45,46],"tags":[],"class_list":["post-7138","post","type-post","status-publish","format-standard","hentry","category-javascript","category-typescript"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/7138","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/comments?post=7138"}],"version-history":[{"count":2,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/7138\/revisions"}],"predecessor-version":[{"id":7147,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/7138\/revisions\/7147"}],"wp:attachment":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/media?parent=7138"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/categories?post=7138"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/tags?post=7138"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}