How to Declare Object Literals in TypeScript the Right Way
Tags: typescript, programming, codenewbie, computerscience
Published: 2022-01-11 22:11:33

<!-- wp:heading {"level":4} -->
<h4>In this article, you will look at different ways to declare Object Literals in TypeScript</h4>
<!-- /wp:heading -->

<!-- wp:heading {"level":3} -->
<h3>What are Object Literals?</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>They are a comma-separated list of name-value pairs. Think of JSON Objects. Below is an Object Literal which contains the information for a user.</p>
<!-- /wp:paragraph -->

<!-- wp:image -->
<figure class="wp-block-image"><img src="https://cdn-images-1.medium.com/max/1600/1*h5Zd4hxmJOemRej0GKDwBA.png" alt=""/><figcaption>An example of an Object&nbsp;Literal</figcaption></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>Let’s look at different ways to declare object literals in TypeScript and some caveats associated with them.</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":3} -->
<h3>1. Declaring an Object Literal with No&nbsp;Type</h3>
<!-- /wp:heading -->

<!-- wp:image -->
<figure class="wp-block-image"><img src="https://cdn-images-1.medium.com/max/1600/1*neRKwUkIeWJcBrYFluxHZQ.png" alt=""/><figcaption>Declaring Object Literal with no Type Declaration</figcaption></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>This is the most straightforward way and you declare the object in the same way as you would in javascript. However, this also means you are not using TypeScript as it is supposed to be used.&nbsp;</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>In the first two statements, I tried to access the object’s members name and <strong>email</strong> and it worked fine. When I try to access a non-existing member <strong>number</strong>, TypeScript threw an error. I wasn’t able to add to any new members either.</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":3} -->
<h3>2. Declaring an Object Literal with Type&nbsp;any</h3>
<!-- /wp:heading -->

<!-- wp:image -->
<figure class="wp-block-image"><img src="https://cdn-images-1.medium.com/max/1600/1*8jK-gswJC9d_dfKPUKjs8A.png" alt=""/></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>If you use type any, you do not get an error when you try to access a non-existing member and you can add new members to your object literal as well.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>So this must be the correct way, right? No!</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>When you use the type <strong>any</strong> to declare, it is like a wild card. Although it would ‘fix’ the errors from the previous section, using any would make the type system kind of worthless.&nbsp;</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":3} -->
<h3>3. Declaring an Object Literal with Type&nbsp;object</h3>
<!-- /wp:heading -->

<!-- wp:image -->
<figure class="wp-block-image"><img src="https://cdn-images-1.medium.com/max/1600/1*kM1YokzSLxGhe89PDT0CaQ.png" alt=""/><figcaption>Declaring an Object Literal with Type&nbsp;object</figcaption></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>If you use the type <strong>object</strong>, your object literal is not going to work as you expect it to. In the first console statement, although I try to access a member of <strong>user, </strong>I got an error. Although typescript doesn't throw an error if you declare your object literal with the type error, it will not be able to find the members of the class when you try to access them. Similar to the previous case, you can add any new members either.</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":3} -->
<h3>4. Using type Record&lt;string, any&gt;</h3>
<!-- /wp:heading -->

<!-- wp:image -->
<figure class="wp-block-image"><img src="https://cdn-images-1.medium.com/max/1600/1*v25e64fiOVZsYsNV9pObqQ.png" alt=""/><figcaption>Declaring Object Literal with type Record&lt;string, any&gt;</figcaption></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>This case is similar to case #2 where we declared the object literal with type <strong>any. </strong>You will get undefined if you try to access a non-existing member and can add new members to your object. However, this is better than using a type of <strong>any.&nbsp;</strong></p>
<!-- /wp:paragraph -->

<!-- wp:image -->
<figure class="wp-block-image"><img src="https://cdn-images-1.medium.com/max/1600/1*u-FZNmotJPw3LjOgubl8ag.png" alt=""/><figcaption>Declaring object literal with type Record&lt;string, string&gt;</figcaption></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>Instead of using <strong>Record&lt;string,any&gt;</strong>, you could use <strong>Record&lt;string,string&gt;</strong> or <strong>Record&lt;string, string | number&gt;</strong></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>In the above code snippet since I used Record&lt;string,string&gt;, TypeScript throws an error when I try to add a member which has a number value. This is useful when you do not know the structure of your object literal, eg: the response object from an API.&nbsp;</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":3} -->
<h3>5. Using a custom Type while declaration</h3>
<!-- /wp:heading -->

<!-- wp:image -->
<figure class="wp-block-image"><img src="https://cdn-images-1.medium.com/max/1600/1*A5O3S-qnUy1aQX9V36wmsQ.png" alt=""/><figcaption>Declaring Object Literal with Custom Type declaration</figcaption></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>If you know the structure of your object literal, you can specify the type while you are declaring it. TypeScript will throw an error when you try to add new members or when you try to access non-existing members. Although this is a good use of typescript, it is better to use Interfaces to make your code look cleaner.</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":3} -->
<h3>6. Using Interfaces</h3>
<!-- /wp:heading -->

<!-- wp:image -->
<figure class="wp-block-image"><img src="https://cdn-images-1.medium.com/max/1600/1*8mseZEh9LgwXax4Yj6zUQg.png" alt=""/><figcaption>Declaring Object Literal with Interface</figcaption></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>This case will show the same behavior as case #5 but it makes your code look much cleaner and you will be able to re-use the interface to declare multiple object literals. You can also extend from an existing interface, create unions of multiple interfaces, etc.&nbsp;</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>In my interface, I also added age as an optional member therefore TypeScript doesn't throw an error although <strong>user1</strong> has no member age but <strong>user2</strong> does.</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":3} -->
<h3>So what is the right&nbsp;way?</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>This is my opinion.&nbsp;</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>In most cases, you should try to use interfaces wherever possible. This ensures that you are using TypeScript the way it is supposed to be and it also helps in type checking and autocomplete suggestions. You can have a separate file for all your type declarations and simply import the interfaces to separate the interfaces and your code logic.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>However, in some cases when the object literal’s structure is too big or not known, I’d suggest using <strong>Record&lt;string, any&gt; </strong>or if you can be more specific, use Record&lt;string, string|number&gt; or something similar based on your use-case.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>I would recommend not using type <strong>any </strong>or<strong> </strong>not declaring a type as shown in case #1 and case #2. This reduces the powers of TypeScript.</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":3} -->
<h3>Conclusion</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>I hope you found this article helpful. Please let me know if you have any feedback or use different logic for declaring object literals.&nbsp;If you are interested, check out <a href="https://www.realpythonproject.com/from-javascript-to-typescript-crash-course-cheatsheet-basics/" target="_blank" rel="noreferrer noopener">this article I wrote about moving from javascript to typescript</a></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p></p>
<!-- /wp:paragraph -->