<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Kamran Ayub</title>
    <description>The latest articles on DEV Community by Kamran Ayub (@kamranayub).</description>
    <link>https://dev.to/kamranayub</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F65961%2Fd89a031f-8bda-47ee-be34-be818ae980fe.jpg</url>
      <title>DEV Community: Kamran Ayub</title>
      <link>https://dev.to/kamranayub</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kamranayub"/>
    <language>en</language>
    <item>
      <title>Hacktoberfest: Can I ask a question?</title>
      <dc:creator>Kamran Ayub</dc:creator>
      <pubDate>Thu, 08 Oct 2020 13:22:15 +0000</pubDate>
      <link>https://dev.to/kamranayub/hacktoberfest-can-i-ask-a-question-2akk</link>
      <guid>https://dev.to/kamranayub/hacktoberfest-can-i-ask-a-question-2akk</guid>
      <description>&lt;p&gt;I have a friend who is doing their first open source contribution through &lt;a href="https://hacktoberfest.digitalocean.com/" rel="noopener noreferrer"&gt;Hacktoberfest&lt;/a&gt; this year, which is a yearly event to encourage open source participation.&lt;/p&gt;

&lt;p&gt;In their email, they asked:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Is there any etiquette or expectation for how much coding help one can ask for when taking up an issue and contributing?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What a good question! Imagine yourself feeling pretty psyched to take on a Hacktoberfest issue and when you start to dig in to understand the codebase, you start to feel intimidated. &lt;/p&gt;

&lt;p&gt;Is it OK to ask for help? Would that be rude to the maintainers? &lt;/p&gt;

&lt;p&gt;The short answers are &lt;strong&gt;YES&lt;/strong&gt; and &lt;strong&gt;NO&lt;/strong&gt; (&lt;em&gt;hopefully&lt;/em&gt;). Here is my longer answer!&lt;/p&gt;

&lt;h2&gt;
  
  
  Hacktoberfest projects expect newcomers
&lt;/h2&gt;

&lt;p&gt;There was a little bit of drama this year because historically projects did not necessarily opt into Hacktoberfest and were being spammed with low-effort PRs (or outright useless PRs). However, the &lt;a href="https://hacktoberfest.digitalocean.com/hacktoberfest-update" rel="noopener noreferrer"&gt;rules have changed&lt;/a&gt; and now repositories can opt-in in several ways:&lt;/p&gt;

&lt;p&gt;They can have a &lt;code&gt;hacktoberfest&lt;/code&gt; topic in their GitHub project, like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F563819%2F95412517-bd885800-08ee-11eb-883a-6620f19d0c0e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F563819%2F95412517-bd885800-08ee-11eb-883a-6620f19d0c0e.png" alt="Screenshot of a repository with "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Or, maintainers can mark accepted PRs with the &lt;code&gt;hacktoberfest-accepted&lt;/code&gt;, like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F563819%2F95412776-5919c880-08ef-11eb-8a63-f58f6bc4e3e4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F563819%2F95412776-5919c880-08ef-11eb-8a63-f58f6bc4e3e4.png" alt="hacktoberfest-accepted label"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If one of these is true, the project is considered opted-in to Hacktoberfest.&lt;/p&gt;

&lt;p&gt;My expectation as a contributor would be that if a project opted into Hacktoberfest, especially with the &lt;strong&gt;topic&lt;/strong&gt; approach, they are &lt;em&gt;expecting&lt;/em&gt; to help you with making quality contributions.&lt;/p&gt;

&lt;p&gt;Now since we at &lt;a href="https://github.com/excaliburjs/Excalibur" rel="noopener noreferrer"&gt;Excalibur&lt;/a&gt; have always opted-in each year, I can tell you that &lt;strong&gt;we expect people to ask questions!&lt;/strong&gt; We try to triage and choose potential Hacktoberfest issues ahead of time (heh, in "Preptember") but we know that people will likely have questions.&lt;/p&gt;

&lt;p&gt;After all, first-time contributors can't be expected to have answers to everything, of course you will need some help along the way. This is especially true for anything beyond mere typos.&lt;/p&gt;

&lt;h2&gt;
  
  
  But will my question be welcomed?
&lt;/h2&gt;

&lt;p&gt;Now this is getting at a different issue, unrelated to Hacktoberfest specifically and more related to toxicity in the open source world. And let's be real: open source can be toxic.&lt;/p&gt;

&lt;p&gt;Here's what I recommend to help avoid a toxic project until it's too late: "scout" a potential project beforehand. Does it have a Code of Conduct? Do the maintainers seem to follow it? How do they react to external contributors asking questions? Are they helpful? How do they review their own code?&lt;/p&gt;

&lt;p&gt;Doing some prep work on your part beforehand I think will help having to ask this question in the first place.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where should I ask?
&lt;/h2&gt;

&lt;p&gt;Start with the CONTRIBUTING document of the project or the CODE_OF_CONDUCT document. An actively maintained project that works with external contributors will typically lay out the expectations for issues and pull requests and may tell you where the best place to get help is. With the recent &lt;a href="https://github.blog/2020-05-06-new-from-satellite-2020-github-codespaces-github-discussions-securing-code-in-private-repositories-and-more/" rel="noopener noreferrer"&gt;introduction of GitHub Discussions&lt;/a&gt;, that may also be the first place to look if the project is opted-into the beta.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F563819%2F95463793-d6b8f500-093e-11eb-9f77-2e3997cd5dc0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F563819%2F95463793-d6b8f500-093e-11eb-9f77-2e3997cd5dc0.png" alt="Screenshot of GitHub Discussions"&gt;&lt;/a&gt;&lt;/p&gt;
GitHub Discussions is slowly being made available on a opt-in basis



&lt;p&gt;If there's no clear place to start, I recommend first asking within issues, assuming there's a Hacktoberfest issue you're taking. This is also where you'd volunteer to take the issue (like, "🙋‍♂️ Hey, I'd love to try and take this on!").&lt;/p&gt;

&lt;p&gt;At that point, maintainers should see your interest and expect that you'll have questions as you get farther into it. If you have questions right away, like about the design, proposal, or a general question, the issue is where I'd ask.&lt;/p&gt;

&lt;p&gt;If you have a draft pull request (and I always recommend starting with a draft!) then that is where I'd start asking questions about the approach, feedback on your current solution, etc. A draft pull request is like your writing drafts -- do you send them to your friends to read or an editor? Of course! So get feedback early in the process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Time to explore the cave, don't go it alone!
&lt;/h2&gt;

&lt;p&gt;I like to think of exploring a codebase like exploring a cave system (or "spelunking" if you're a fancypants). You reveal one area, then reveal the next and that might have any number of offshoot paths or trails back to previous areas, etc. You can get lost in a codebase just as you would a cave system.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F563819%2F95415964-3ee3e880-08f7-11eb-8290-4987f6d85952.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F563819%2F95415964-3ee3e880-08f7-11eb-8290-4987f6d85952.jpg" alt="Photo of a cave by Joshua Sortino (unsplash)"&gt;&lt;/a&gt;&lt;/p&gt;
Photo by &lt;a href="https://unsplash.com/@sortino?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Joshua Sortino&lt;/a&gt; on &lt;a href="https://unsplash.com/wallpapers/nature/cave?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;



&lt;p&gt;A maintainer is the cave guide. Or maybe just someone who's really been in and out of the cave a ton. Or maybe &lt;strong&gt;really, really&lt;/strong&gt; likes this one area of the cave and knows it blindfolded. The metaphor sort of falls apart because who made the cave, anyway? Nevermind. 🤫&lt;/p&gt;

&lt;p&gt;When you ask questions while you are working on a codebase (of any size), it's like you are wandering into the cave and &lt;em&gt;then&lt;/em&gt; asking for the maintainer to fill in parts of the cave map, throw you some new flashlight batteries, and tell you, "This is the safe path through. Avoid this one, though!"&lt;/p&gt;

&lt;p&gt;Being a newcomer though brings fresh perspective. You might find parts of the cave no one has been through in awhile that could use some dusting. Maybe there's a new pathway the cave has opened up that could be faster than an existing pathway that's well-trodden. You get the picture -- when you ask questions, you may inspire new and better solutions to existing problems maintainers haven't considered.&lt;/p&gt;

&lt;p&gt;It's definitely fun to explore a cave on your own at first but it won't be long until your flashlight dies. Ask for help and recharge those batteries! It results in a more agreeable outcome for everyone. Huzzah.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to avoid
&lt;/h2&gt;

&lt;p&gt;I can't speak for all maintainers but I think it's safe to say that generally maintainers welcome quality contributions (of any kind!).&lt;/p&gt;

&lt;p&gt;When you don't ask questions you may end up going down a road that could lead to maintainbility or design issues you haven't foreseen. Remember: this might be your first (and only) time in the cave, it's better to go in prepared!&lt;/p&gt;

&lt;h2&gt;
  
  
  Always Be Asking
&lt;/h2&gt;

&lt;p&gt;I'd be &lt;strong&gt;surprised&lt;/strong&gt; if you didn't have a question about a new codebase. Actually, it would be unbelievable. Of course you will.&lt;/p&gt;

&lt;p&gt;I get it, though. You might be listening to that voice in your head, "You can't ask a question like this, it's a silly question, I will look like a fool, and what will they think of me?" &lt;strong&gt;Don't listen!&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Listen, &lt;strong&gt;it is not a sign of weakness to ask questions, it is how we learn.&lt;/strong&gt; Doesn't matter if you're brand new to open source, new in your role, or a Principal Engineer -- we ask questions to understand better so &lt;strong&gt;Always Be Asking&lt;/strong&gt;. If anyone (person, company, etc.) expresses to you that asking a question is some sign of weakness, run the other way.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://bit.ly/PSContributingToOpenSource" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F563819%2F71635500-cd9a3b00-2bea-11ea-9729-a4b32d7a1284.png" alt="Course overview screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If this is your first time contributing to open source, first, how exciting! Second, I lay out everything I just mentioned in more detail in my course on &lt;a href="https://bit.ly/PSContributingToOpenSource" rel="noopener noreferrer"&gt;Contributing to an Open Source Project on GitHub&lt;/a&gt;. It's an A-to-Z guide geared toward new open source contributors with practical scenarios, workflows, and a guided process on choosing the right project for you to work on.&lt;/p&gt;

</description>
      <category>hacktoberfest</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Controlling Browser Permissions in Cypress End-to-End Tests</title>
      <dc:creator>Kamran Ayub</dc:creator>
      <pubDate>Fri, 17 Jul 2020 02:33:59 +0000</pubDate>
      <link>https://dev.to/kamranayub/controlling-browser-permissions-in-cypress-end-to-end-tests-5d7b</link>
      <guid>https://dev.to/kamranayub/controlling-browser-permissions-in-cypress-end-to-end-tests-5d7b</guid>
      <description>&lt;p&gt;I am excited to release a new open source package &lt;a href="https://npmjs.com/package/cypress-browser-permissions"&gt;cypress-browser-permissions&lt;/a&gt;. 🎉&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vJ70wriM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/kamranayub"&gt;
        kamranayub
      &lt;/a&gt; / &lt;a href="https://github.com/kamranayub/cypress-browser-permissions"&gt;
        cypress-browser-permissions
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A Cypress plugin to set launched browser preferences including permissions like Geolocation, Notifications, Microphone, etc.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
cypress-browser-permissions&lt;/h1&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://camo.githubusercontent.com/5c87fe48a2b8c43d73b968f49a4c92ac1013d6cc/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c616e6775616765732f636f64652d73697a652f6b616d72616e617975622f637970726573732d62726f777365722d7065726d697373696f6e732e737667"&gt;&lt;img src="https://camo.githubusercontent.com/5c87fe48a2b8c43d73b968f49a4c92ac1013d6cc/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c616e6775616765732f636f64652d73697a652f6b616d72616e617975622f637970726573732d62726f777365722d7065726d697373696f6e732e737667" alt="GitHub code size in bytes"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer" href="https://camo.githubusercontent.com/26a161c0d37c70af27510b784b696de4a20fbbad/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f7265706f2d73697a652f6b616d72616e617975622f637970726573732d62726f777365722d7065726d697373696f6e732e737667"&gt;&lt;img src="https://camo.githubusercontent.com/26a161c0d37c70af27510b784b696de4a20fbbad/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f7265706f2d73697a652f6b616d72616e617975622f637970726573732d62726f777365722d7065726d697373696f6e732e737667" alt="GitHub repo size"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer" href="https://camo.githubusercontent.com/ec491aa6d362174e67bbeeb73e02701b405f679a/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f64772f637970726573732d62726f777365722d7065726d697373696f6e732e737667"&gt;&lt;img src="https://camo.githubusercontent.com/ec491aa6d362174e67bbeeb73e02701b405f679a/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f64772f637970726573732d62726f777365722d7065726d697373696f6e732e737667" alt="npm"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer" href="https://camo.githubusercontent.com/79d769390f2b8ce1b9d4eae96da3bede623c1589/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f646d2f637970726573732d62726f777365722d7065726d697373696f6e732e737667"&gt;&lt;img src="https://camo.githubusercontent.com/79d769390f2b8ce1b9d4eae96da3bede623c1589/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f646d2f637970726573732d62726f777365722d7065726d697373696f6e732e737667" alt="npm"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer" href="https://camo.githubusercontent.com/32a0721d9f5b4755fa56f43402922f87b60c1ff8/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f64792f637970726573732d62726f777365722d7065726d697373696f6e732e737667"&gt;&lt;img src="https://camo.githubusercontent.com/32a0721d9f5b4755fa56f43402922f87b60c1ff8/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f64792f637970726573732d62726f777365722d7065726d697373696f6e732e737667" alt="npm"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer" href="https://camo.githubusercontent.com/8f561e3c0c9ea531a27a8ab29460673c5f118ac6/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f64742f637970726573732d62726f777365722d7065726d697373696f6e732e737667"&gt;&lt;img src="https://camo.githubusercontent.com/8f561e3c0c9ea531a27a8ab29460673c5f118ac6/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f64742f637970726573732d62726f777365722d7065726d697373696f6e732e737667" alt="npm"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer" href="https://camo.githubusercontent.com/285636c026179c04d6635a4feec0018b0ce8bf84/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f6c2f637970726573732d62726f777365722d7065726d697373696f6e732e737667"&gt;&lt;img src="https://camo.githubusercontent.com/285636c026179c04d6635a4feec0018b0ce8bf84/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f6c2f637970726573732d62726f777365722d7065726d697373696f6e732e737667" alt="NPM"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer" href="https://camo.githubusercontent.com/857d78bac23082b19bcc63bff7798be1042a830c/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f637970726573732d62726f777365722d7065726d697373696f6e732e737667"&gt;&lt;img src="https://camo.githubusercontent.com/857d78bac23082b19bcc63bff7798be1042a830c/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f637970726573732d62726f777365722d7065726d697373696f6e732e737667" alt="npm"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer" href="https://camo.githubusercontent.com/f894bbacc133236415b060fd81b022fcd774d891/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6173742d636f6d6d69742f6b616d72616e617975622f637970726573732d62726f777365722d7065726d697373696f6e732e737667"&gt;&lt;img src="https://camo.githubusercontent.com/f894bbacc133236415b060fd81b022fcd774d891/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6173742d636f6d6d69742f6b616d72616e617975622f637970726573732d62726f777365722d7065726d697373696f6e732e737667" alt="GitHub last commit"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer" href="https://camo.githubusercontent.com/825d8d0960ed7667c6c4d744128980a980e1db3f/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f636f6c6c61626f7261746f72732f637970726573732d62726f777365722d7065726d697373696f6e732e737667"&gt;&lt;img src="https://camo.githubusercontent.com/825d8d0960ed7667c6c4d744128980a980e1db3f/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f636f6c6c61626f7261746f72732f637970726573732d62726f777365722d7065726d697373696f6e732e737667" alt="npm collaborators"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A Cypress plugin to manage browser launch permissions for various APIs such as Notifications, Geolocation, Cookies, Images, and more.&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://user-images.githubusercontent.com/563819/87746293-d254c400-c7b5-11ea-9d22-d5613b9dae47.gif"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yEaBGL-6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://user-images.githubusercontent.com/563819/87746293-d254c400-c7b5-11ea-9d22-d5613b9dae47.gif" alt="Video of notification being displayed"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;These APIs can be controlled using browser profile preferences which this plugin will generate and pass for you, as well as resetting them for each test run (otherwise they will be persisted).&lt;/p&gt;
&lt;p&gt;This enables you to effectively test permissions-based APIs in continuous integration environments and in headed browsers &lt;em&gt;without prompts.&lt;/em&gt; 🎉&lt;/p&gt;
&lt;h2&gt;
Table of Contents&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://raw.githubusercontent.com/kamranayub/cypress-browser-permissions/master/#usage"&gt;Usage&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://raw.githubusercontent.com/kamranayub/cypress-browser-permissions/master/#install-the-package"&gt;Install the package&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://raw.githubusercontent.com/kamranayub/cypress-browser-permissions/master/#npm"&gt;npm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://raw.githubusercontent.com/kamranayub/cypress-browser-permissions/master/#yarn"&gt;yarn&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://raw.githubusercontent.com/kamranayub/cypress-browser-permissions/master/#import-and-initialize-the-plugin"&gt;Import and initialize the plugin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://raw.githubusercontent.com/kamranayub/cypress-browser-permissions/master/#setting-permissions"&gt;Setting Permissions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://raw.githubusercontent.com/kamranayub/cypress-browser-permissions/master/#in-cypressjson"&gt;In &lt;code&gt;cypress.json&lt;/code&gt;&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://raw.githubusercontent.com/kamranayub/cypress-browser-permissions/master/#in-cypressenvjson"&gt;In &lt;code&gt;cypress.env.json&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://raw.githubusercontent.com/kamranayub/cypress-browser-permissions/master/#via-cypress-open-or-cypress-run"&gt;Via &lt;code&gt;cypress open&lt;/code&gt; or &lt;code&gt;cypress run&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://raw.githubusercontent.com/kamranayub/cypress-browser-permissions/master/#via-machine-environment-variables"&gt;Via machine environment variables&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://raw.githubusercontent.com/kamranayub/cypress-browser-permissions/master/#supported-permissions"&gt;Supported Permissions&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://raw.githubusercontent.com/kamranayub/cypress-browser-permissions/master/#chrome--edge-chromium"&gt;Chrome / Edge (Chromium)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://raw.githubusercontent.com/kamranayub/cypress-browser-permissions/master/#firefox"&gt;Firefox&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://raw.githubusercontent.com/kamranayub/cypress-browser-permissions/master/#supported-values"&gt;Supported Values&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://raw.githubusercontent.com/kamranayub/cypress-browser-permissions/master/#checking-permissions"&gt;Checking Permissions&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://raw.githubusercontent.com/kamranayub/cypress-browser-permissions/master/#usage-example"&gt;Usage Example&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://raw.githubusercontent.com/kamranayub/cypress-browser-permissions/master/#api-reference"&gt;API Reference&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://raw.githubusercontent.com/kamranayub/cypress-browser-permissions/master/#resetting-permissions"&gt;Resetting Permissions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://raw.githubusercontent.com/kamranayub/cypress-browser-permissions/master/#details"&gt;Details&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://raw.githubusercontent.com/kamranayub/cypress-browser-permissions/master/#how-it-works"&gt;How It Works&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://raw.githubusercontent.com/kamranayub/cypress-browser-permissions/master/#chrome--edge--chromium-preferences"&gt;Chrome / Edge / Chromium Preferences&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://raw.githubusercontent.com/kamranayub/cypress-browser-permissions/master/#firefox-1"&gt;Firefox&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://raw.githubusercontent.com/kamranayub/cypress-browser-permissions/master/#credits"&gt;Credits&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://raw.githubusercontent.com/kamranayub/cypress-browser-permissions/master/#mit-license"&gt;MIT License&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
Usage&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;👋 Read the &lt;a href="https://dev.to/kamranayub/controlling-browser-permissions-in-cypress-end-to-end-tests-5d7b" rel="nofollow"&gt;dev.to introduction post for a quick start guide and an example&lt;/a&gt;!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
Install the&lt;/h3&gt;…&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/kamranayub/cypress-browser-permissions"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;This package solves a real need when testing more sophisticated applications when using &lt;a href="https://cypress.io"&gt;Cypress&lt;/a&gt;, the end-to-end testing framework. It helps control the permission level of various browser features such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Desktop Notifications&lt;/li&gt;
&lt;li&gt;Geolocation&lt;/li&gt;
&lt;li&gt;Images&lt;/li&gt;
&lt;li&gt;Camera&lt;/li&gt;
&lt;li&gt;Microphone&lt;/li&gt;
&lt;li&gt;etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VbXHWGn6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/563819/87500464-2169f000-c622-11ea-8dbb-a480a6f137ac.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VbXHWGn6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/563819/87500464-2169f000-c622-11ea-8dbb-a480a6f137ac.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Use It
&lt;/h2&gt;

&lt;p&gt;To get started, you'll need to install the package and you'll need Cypress installed already.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i cypress cypress-browser-permissions &lt;span class="nt"&gt;--save-dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;If this is your first time installing Cypress, you'll need to run it once to generate a project structure:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;npx cypress open
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Then, you need to initialize the plugin to hook it into Cypress' plugin pipeline. In &lt;code&gt;cypress/plugins/index.js&lt;/code&gt;, modify it as follows:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gi"&gt;+ const { cypressBrowserPermissionsPlugin } = require('cypress-browser-permissions')
&lt;/span&gt;
/**
 * @type {Cypress.PluginConfig}
 */
&lt;span class="p"&gt;module.exports = (on, config) =&amp;gt; {
&lt;/span&gt;  // `on` is used to hook into various events Cypress emits
  // `config` is the resolved Cypress config
&lt;span class="gi"&gt;+ config = cypressBrowserPermissionsPlugin(on, config);
+ return config;
&lt;/span&gt;&lt;span class="err"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Now you will have the ability to control various permissions for Chrome, Edge, and Firefox using &lt;a href="https://docs.cypress.io/guides/guides/environment-variables.html"&gt;Cypress environment variables&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For example, if you want to just set permissions for your project you can do so in &lt;code&gt;cypress.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"browserPermissions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"notifications"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"geolocation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"allow"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The plugin will read the permission settings and apply them when launching the browser. It will also reset between launches since modifying the browser profile is persisted across sessions.&lt;/p&gt;

&lt;p&gt;You can read more about &lt;a href="https://github.com/kamranayub/cypress-browser-permissions"&gt;supported permissions and values in the README&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Writing an End-to-End Notification Test
&lt;/h3&gt;

&lt;p&gt;So let's try it out! Once I finish my &lt;strong&gt;Testing Progressive Web Apps&lt;/strong&gt; &lt;a href="http://bit.ly/KamranOnPluralsight"&gt;Pluralsight course&lt;/a&gt;, it will come with an open source sample app. In the meantime, we can write a basic test to see if permissions are working. This same test is included in the repo.&lt;/p&gt;

&lt;p&gt;First, we have an HTML file that uses &lt;code&gt;window.Notification&lt;/code&gt; to display a desktop notification:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;cypress/html/notification.html&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"viewport"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"width=device-width, initial-scale=1.0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Cypress Notification Test&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/javascript"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Notification&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;This is a test!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;show&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;__CypressNotificationShown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;You can learn more about how the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/notification"&gt;Notification API&lt;/a&gt; works but what we are doing is immediately triggering a notification. Once the browser shows the toast, it triggers the &lt;code&gt;show&lt;/code&gt; event on the &lt;code&gt;Notification&lt;/code&gt; instance. Since Cypress is awesome and we can hook directly into the &lt;code&gt;window&lt;/code&gt; object, we set a callback value globally that we can then inspect/wait for in our test.&lt;/p&gt;

&lt;p&gt;If you have a blank Cypress project you do not even need a server as Cypress will automatically host the root of the project when there is no other configuration.&lt;/p&gt;

&lt;p&gt;Save the &lt;code&gt;notification.html&lt;/code&gt; file under &lt;code&gt;cypress/html&lt;/code&gt; and then we can visit that page in the test.&lt;/p&gt;

&lt;p&gt;We can create a test suite in &lt;code&gt;cypress/integration&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;cypress/integration/notification.test.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;isPermissionAllowed&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cypress-browser-permissions&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;notifications&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should be enabled&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isPermissionAllowed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;notifications&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;be&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="c1"&gt;// Only test notification showing in "headed" browsers, which also&lt;/span&gt;
    &lt;span class="c1"&gt;// works in CI :tada:&lt;/span&gt;
    &lt;span class="nx"&gt;Cypress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isHeaded&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should display desktop notification&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="c1"&gt;// Visit the page we created previously&lt;/span&gt;
        &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;visit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/cypress/html/notification.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;// Wait for the window callback to populate with the event data&lt;/span&gt;
        &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;its&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;__CypressNotificationShown&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;should&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;exist&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Now we can run our tests:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;npx cypress open
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;That's all! If &lt;code&gt;browserPermissions.notifications&lt;/code&gt; is set to &lt;code&gt;allow&lt;/code&gt; then our test should pass:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--y5cLdo2Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/563819/87737665-3620c200-c7a1-11ea-8429-73bd40c99bed.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--y5cLdo2Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/563819/87737665-3620c200-c7a1-11ea-8429-73bd40c99bed.png" alt="test run"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And a notification will be shown!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---7a7uevU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/563819/87737706-52bcfa00-c7a1-11ea-893e-9f6f8dec1e2e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---7a7uevU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/563819/87737706-52bcfa00-c7a1-11ea-893e-9f6f8dec1e2e.png" alt="toast"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  How It Works
&lt;/h3&gt;

&lt;p&gt;In Cypress, &lt;a href="https://docs.cypress.io/api/plugins/browser-launch-api.html#Modify-browser-launch-arguments-preferences-and-extensions"&gt;you have control over the launch preferences for browsers&lt;/a&gt;, so the magic lies in &lt;em&gt;what preferences to pass to each browser.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This topic is not heavily documented &lt;a href="https://github.com/cypress-io/cypress/issues/2671"&gt;as evidenced by this open issue in the Cypress repo&lt;/a&gt; I came across while researching this. It has been open since 2018 with no one mentioning the ability to control launch preferences.&lt;/p&gt;

&lt;p&gt;Thanks to BrowserStack for &lt;a href="https://www.browserstack.com/automate/handle-popups-alerts-prompts-in-automated-tests"&gt;documenting some of these permissions&lt;/a&gt; as well as these StackOverflow posts:&lt;/p&gt;


&lt;div class="ltag__stackexchange--container"&gt;
  &lt;div class="ltag__stackexchange--title-container"&gt;
    
      &lt;div class="ltag__stackexchange--title"&gt;
        &lt;h1&gt;
          &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pTF_nE4a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/stackoverflow-logo-b42691ae545e4810b105ee957979a853a696085e67e43ee14c5699cf3e890fb4.svg" alt=""&gt;
            &lt;a href="https://stackoverflow.com/questions/55435198/selenium-python-allow-firefox-notifications" rel="noopener noreferrer"&gt;
               Selenium + Python Allow Firefox Notifications
            &lt;/a&gt;
        &lt;/h1&gt;
        &lt;div class="ltag__stackexchange--post-metadata"&gt;
          &lt;span&gt;Mar 30 '19&lt;/span&gt;
            &lt;span&gt;Comments: &lt;/span&gt;
            &lt;span&gt;Answers: 1&lt;/span&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;a class="ltag__stackexchange--score-container" href="https://stackoverflow.com/questions/55435198/selenium-python-allow-firefox-notifications" rel="noopener noreferrer"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5MiFESHx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/stackexchange-arrow-up-eff2e2849e67d156181d258e38802c0b57fa011f74164a7f97675ca3b6ab756b.svg" alt=""&gt;
        &lt;div class="ltag__stackexchange--score-number"&gt;
          0
        &lt;/div&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Rk_a5QFN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/stackexchange-arrow-down-4349fac0dd932d284fab7e4dd9846f19a3710558efde0d2dfd05897f3eeb9aba.svg" alt=""&gt;
      &lt;/a&gt;
    
  &lt;/div&gt;
  &lt;div class="ltag__stackexchange--body"&gt;
    
&lt;p&gt;there is such a question how to implement so that Selenium resolves in that case 
notifications like this photo
&lt;a href="https://prod-cdn.sumo.mozilla.net/uploads/gallery/images/2017-10-18-05-45-38-20e1d7.png" rel="nofollow noreferrer"&gt;https://prod-cdn.sumo.mozilla.net/uploads/gallery/images/2017-10-18-05-45-38-20e1d7.png&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;it is desirable that he press himself I will be very grateful&lt;/p&gt;

    
  &lt;/div&gt;
  &lt;div class="ltag__stackexchange--btn--container"&gt;
    
      &lt;a href="https://stackoverflow.com/questions/55435198/selenium-python-allow-firefox-notifications" rel="noopener noreferrer"&gt;Open Full Question&lt;/a&gt;
    
  &lt;/div&gt;
&lt;/div&gt;




&lt;div class="ltag__stackexchange--container"&gt;
  &lt;div class="ltag__stackexchange--title-container"&gt;
    
      &lt;div class="ltag__stackexchange--title"&gt;
        &lt;h1&gt;
          &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pTF_nE4a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/stackoverflow-logo-b42691ae545e4810b105ee957979a853a696085e67e43ee14c5699cf3e890fb4.svg" alt=""&gt;
            &lt;a href="https://stackoverflow.com/questions/48007699/how-to-allow-or-deny-notification-geo-location-microphone-camera-pop-up" rel="noopener noreferrer"&gt;
               How to allow or deny notification geo-location microphone camera pop up
            &lt;/a&gt;
        &lt;/h1&gt;
        &lt;div class="ltag__stackexchange--post-metadata"&gt;
          &lt;span&gt;Dec 28 '17&lt;/span&gt;
            &lt;span&gt;Comments: 5&lt;/span&gt;
            &lt;span&gt;Answers: 2&lt;/span&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;a class="ltag__stackexchange--score-container" href="https://stackoverflow.com/questions/48007699/how-to-allow-or-deny-notification-geo-location-microphone-camera-pop-up" rel="noopener noreferrer"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5MiFESHx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/stackexchange-arrow-up-eff2e2849e67d156181d258e38802c0b57fa011f74164a7f97675ca3b6ab756b.svg" alt=""&gt;
        &lt;div class="ltag__stackexchange--score-number"&gt;
          6
        &lt;/div&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Rk_a5QFN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/stackexchange-arrow-down-4349fac0dd932d284fab7e4dd9846f19a3710558efde0d2dfd05897f3eeb9aba.svg" alt=""&gt;
      &lt;/a&gt;
    
  &lt;/div&gt;
  &lt;div class="ltag__stackexchange--body"&gt;
    
&lt;p&gt;I'm not able to click on &lt;strong&gt;Allow&lt;/strong&gt; button of access camera authentication pop up.&lt;/p&gt;

&lt;p&gt;Here is the look of pop up.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--R7Toogp5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.stack.imgur.com/HHHVF.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--R7Toogp5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.stack.imgur.com/HHHVF.png" alt="here"&gt;&lt;/a&gt;&lt;/p&gt;

    
  &lt;/div&gt;
  &lt;div class="ltag__stackexchange--btn--container"&gt;
    
      &lt;a href="https://stackoverflow.com/questions/48007699/how-to-allow-or-deny-notification-geo-location-microphone-camera-pop-up" rel="noopener noreferrer"&gt;Open Full Question&lt;/a&gt;
    
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;I was able to piece together the information needed to tackle this with a Cypress plugin. Since each browser family uses different preferences, I thought it would be best to abstract it.&lt;/p&gt;

&lt;h3&gt;
  
  
  What's Next?
&lt;/h3&gt;

&lt;p&gt;My hope is that this package is &lt;em&gt;actually short-lived&lt;/em&gt; and the Cypress team can incorporate these permission settings into the core of the product, since it's such an important feature especially when testing new, modern APIs.&lt;/p&gt;

&lt;p&gt;There will be a &lt;strong&gt;full sample&lt;/strong&gt; of using Cypress with this plugin (as well as other black magicks such as bypassing service workers and more!) in my &lt;em&gt;Testing Progressive Web Apps&lt;/em&gt; course soon on &lt;a href="https://bit.ly/KamranOnPluralsight"&gt;Pluralsight&lt;/a&gt;. It should be released in August, you can follow me there to get notified when it releases. The sample app will be open source on GitHub so you'll be able to reference it 👍 &lt;/p&gt;

</description>
      <category>news</category>
      <category>showdev</category>
      <category>javascript</category>
      <category>cypress</category>
    </item>
    <item>
      <title>Storyflow: Using Storybook to Build a Better... Game Engine?</title>
      <dc:creator>Kamran Ayub</dc:creator>
      <pubDate>Tue, 26 May 2020 14:08:00 +0000</pubDate>
      <link>https://dev.to/kamranayub/storyflow-using-storybook-to-build-a-better-game-engine-296l</link>
      <guid>https://dev.to/kamranayub/storyflow-using-storybook-to-build-a-better-game-engine-296l</guid>
      <description>&lt;p&gt;Do you use &lt;a href="https://storybook.js.org"&gt;Storybook&lt;/a&gt;? Do you use it to test game engines? Didn't think so! But we do for &lt;a href="https://excaliburjs.com"&gt;Excalibur.js&lt;/a&gt; and I presented how and why we did it. The genesis for the talk came from a workflow I've been using recently that you can implement in your own projects which I call "Storyflow."&lt;/p&gt;

&lt;h3&gt;
  
  
  Watch the talk
&lt;/h3&gt;

&lt;p&gt;I gave this talk at MN Dev Con on May 4 and again at React Minneapolis on May 21:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/biSFvQmMJsc"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Storyflow?
&lt;/h3&gt;

&lt;p&gt;The Storybook workflow (ahem, &lt;em&gt;Storyflow&lt;/em&gt;) we follow puts Storybook stories at the center of our workflow. The concept is simple in practice: write your unit and functional tests &lt;em&gt;against Storybook&lt;/em&gt; instead of importing directly from component files like other workflows.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9NrySq17--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/tcrbegs7jiankdzl3fi5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9NrySq17--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/tcrbegs7jiankdzl3fi5.png" alt="Storyflow diagram, write tests against Storybook"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The "normal" component-based workflow goes like:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Write my component in &lt;code&gt;MyComponent.js&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Write my unit test, &lt;code&gt;MyComponent.test.js&lt;/code&gt; and import &lt;code&gt;MyComponent&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Write a functional test, against my running app, which may test one aspect of &lt;code&gt;MyComponent&lt;/code&gt; in use or maybe a few different behaviors/states&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;But with &lt;a href="https://storybook.js.org"&gt;Storybook&lt;/a&gt; the workflow instead flips the script and centers your testing on isolated components through stories:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Write my component in &lt;code&gt;MyComponent.js&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Write my Storybook story &lt;code&gt;DefaultState&lt;/code&gt; in &lt;code&gt;MyComponent.stories.js&lt;/code&gt; and import &lt;code&gt;MyComponent&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Write my unit test, &lt;code&gt;MyComponent.test.js&lt;/code&gt; &lt;strong&gt;and import &lt;code&gt;DefaultState&lt;/code&gt; from stories&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Write a functional test against &lt;code&gt;DefaultState&lt;/code&gt; story in Storybook&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It's comes down to a &lt;em&gt;slight&lt;/em&gt; shift in thinking. Without Storybook, normally you'd be putting your component into different states &lt;em&gt;within&lt;/em&gt; your unit tests. &lt;em&gt;With&lt;/em&gt; Storybook, you're already showcasing your component in different states, which makes your unit tests a lot trimmer. Finally, you can add UI testing on top of it to ensure your component works in the browser (without having to manually verify in Storybook).&lt;/p&gt;

&lt;p&gt;There are 3 major benefits we've seen from this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;One source of truth for all our tests (stories)&lt;/li&gt;
&lt;li&gt;Incentivizes writing more stories&lt;/li&gt;
&lt;li&gt;Promotes more testability&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  One source of truth
&lt;/h3&gt;

&lt;p&gt;Since your unit and functional tests are run against stories, Storybook becomes the source of truth for any tests. Contrast that to developing without stories, where each test could render components in different states and the only way to know would be to examine each test. Having a published Storybook as a static site makes things a lot more discoverable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Incentivizes writing more stories
&lt;/h3&gt;

&lt;p&gt;Since tests are written &lt;em&gt;against&lt;/em&gt; stories, in order to write more tests... you'll need to write more stories. Having more stories means better documentation (even if it's just code!).&lt;/p&gt;

&lt;h3&gt;
  
  
  Promotes more testability
&lt;/h3&gt;

&lt;p&gt;In order to write a solid Storybook story, it has to run in isolation. That means that you will likely lift up more heavy concerns like data fetching, state management, and other stuff higher and have more atomic reusable components. We actually still write stories against our "container" components but it requires a lot more mocking using &lt;a href="https://storybook.js.org/docs/basics/writing-stories/#decorators"&gt;Storybook decorators&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example
&lt;/h2&gt;

&lt;p&gt;If you're curious to see this in action, I have a GitHub Repository set up you can clone and run and I showcase this workflow within the video above.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vWogaON8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-28d89282e0daa1e2496205e2f218a44c755b0dd6536bbadf5ed5a44a7ca54716.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/kamranayub"&gt;
        kamranayub
      &lt;/a&gt; / &lt;a href="https://github.com/kamranayub/example-storyflow"&gt;
        example-storyflow
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Created with CodeSandbox
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h2&gt;
Storyflow Example&lt;/h2&gt;
&lt;p&gt;Companion demo to my talk, &lt;a href="https://bit.ly/StorybookForGameEnginesMDC2020" rel="nofollow"&gt;Using Storybook to Build a Better... Game Engine?&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Showcases using Storybook as the basis for unit and functional tests aka "Storyflow" workflow. Uses Storybook, Jest, and Cypress.&lt;/p&gt;
&lt;h2&gt;
Getting Started&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Prerequisites&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://yarnpkg.com" rel="nofollow"&gt;Yarn&lt;/a&gt; 1.x (or replace &lt;code&gt;yarn&lt;/code&gt; with &lt;code&gt;npm&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nodejs.org" rel="nofollow"&gt;Node&lt;/a&gt; 12.x&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight highlight-source-shell"&gt;&lt;pre&gt;&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Install dependencies&lt;/span&gt;
yarn

&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Start Storybook&lt;/span&gt;
yarn start

&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Run Jest tests&lt;/span&gt;
yarn &lt;span class="pl-c1"&gt;test&lt;/span&gt;

&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Run Cypress test runner&lt;/span&gt;
yarn cypress open

&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Run Cypress tests headless&lt;/span&gt;
yarn cypress run&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/kamranayub/example-storyflow"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;p&gt;You can view a working demo &lt;a href="https://codesandbox.io/github/kamranayub/example-storyflow/tree/master/"&gt;on CodeSandbox&lt;/a&gt; using the repository!&lt;/p&gt;

&lt;p&gt;Does this sound interesting to you? If you're using Storybook, are you writing tests against it or not right now?&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally posted on my blog, &lt;a href="https://kamranicus.com/posts/2020-05-21-storybook-for-game-engines"&gt;Kamranicus.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>storybook</category>
      <category>react</category>
    </item>
    <item>
      <title>Why You Don't Need Types in JSDoc when Documenting TypeScript</title>
      <dc:creator>Kamran Ayub</dc:creator>
      <pubDate>Wed, 05 Feb 2020 16:53:27 +0000</pubDate>
      <link>https://dev.to/kamranayub/why-you-don-t-need-types-in-jsdoc-when-documenting-typescript-1pb0</link>
      <guid>https://dev.to/kamranayub/why-you-don-t-need-types-in-jsdoc-when-documenting-typescript-1pb0</guid>
      <description>&lt;p&gt;I work with many folks who are coming from native JavaScript and learning TypeScript and I've noticed one small thing during code reviews that can save some time. Here's a quick tip if you're used to writing "regular" JSDoc!&lt;/p&gt;

&lt;p&gt;One huge benefit of using TypeScript and documenting with JSDoc syntax is that &lt;strong&gt;you can avoid having to specify JSDoc types in your docs&lt;/strong&gt;! If you want to read the full specification check out Microsoft's standard, &lt;a href="https://github.com/microsoft/tsdoc" rel="noopener noreferrer"&gt;tsdoc&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here's an example of a native JavaScript function with JSDocs:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="cm"&gt;/**
 * Clamps a `value` between a `min` and `max` inclusive
 *
 * @param {Number} value The value to clamp between `min` and `max`
 * @param {Number} min The minimum number of the range
 * @param {Number} max The maximum number of the range
 *
 * @returns {Number} The clamped value
 */&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;clamp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;min&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;max&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;min&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;max&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In TypeScript, you're already statically typing your arguments and return type so there's no need to repeat them in the JSDoc. Lose 'em!&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="cm"&gt;/**
 * Clamps a `value` between a `min` and `max` inclusive
 *
 * @param value The value to clamp between `min` and `max`
 * @param min The minimum number of the range
 * @param max The maximum number of the range
 *
 * @returns The clamped value
 */&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;clamp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;min&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;max&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;min&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;max&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bonuses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A refactor-rename (&lt;code&gt;F2&lt;/code&gt; in Visual Studio Code) of a param will sync the JSDoc param names for you&lt;/li&gt;
&lt;li&gt;VS Code has autocomplete suggestions for parameter names as you type your JSDocs&lt;/li&gt;
&lt;li&gt;VS Code and many other tools support Markdown in JSDoc&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's what you'll see in your editor now:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fo2073t682qoiohovl0qd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fo2073t682qoiohovl0qd.png" alt="Visual studio code showing JSDoc on popover"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.typescriptlang.org/v2/en/play#code/PQKhCgAIUhhAbAhgWwA4GdKMgAwG6LwCuApjpAEYkAuA7iSQHZa7ICWj5ijAJq4gA9yHAMbF0bPCSgRokAAKpEAJxSQCxEpAAqACy0bSkagHtIYlKko16TVhy69+QmQqWrkkdsz1bvbZCJPRiCqZUgTADNjfUhVRgBzaTlFFTVkQR1YjIEAoMgQ5DCI6OpY+KSZV3llGiJlRkxfcyQ0Ej5DZJBgcBIBVBNlakhIokYRajYTZgs0AApOgC4C0JJlABovDmXCsM2cndXlAEpIAG8oOLqGyABZRDKAOm85+6ecue9NzuP9wWOANzgAC+QA" rel="noopener noreferrer"&gt;View in TypeScript playground&lt;/a&gt;&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>documentation</category>
    </item>
    <item>
      <title>Using Storybook in a Monorepo</title>
      <dc:creator>Kamran Ayub</dc:creator>
      <pubDate>Tue, 17 Sep 2019 12:41:22 +0000</pubDate>
      <link>https://dev.to/kamranayub/using-storybook-in-a-monorepo-38l0</link>
      <guid>https://dev.to/kamranayub/using-storybook-in-a-monorepo-38l0</guid>
      <description>&lt;p&gt;I'm currently working in a small monorepo and we have multiple packages set up for shared components, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;packages/
  atoms/
  molecules/
  organisms/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each package has React components under a &lt;code&gt;src&lt;/code&gt; directory and since each directory &lt;em&gt;is&lt;/em&gt; a package, they also contain &lt;code&gt;node_modules&lt;/code&gt; (more on why that's important below).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;packages/
  atoms/
    node_modules/
    src/
      components/
        Hello.js
        Hello.stories.js
    package.json
  molecules/
  organisms/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is different than other posts I've seen that use a root &lt;code&gt;stories/&lt;/code&gt; directory -- that is not how we'd like to set up our repo, we'd prefer stories to live right next to the components they describe.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up Storybook
&lt;/h2&gt;

&lt;p&gt;You can follow the same steps on the &lt;a href="https://storybook.js.org/docs/guides/guide-react/" rel="noopener noreferrer"&gt;getting started page&lt;/a&gt; for setting up Storybook in a monorepo.&lt;/p&gt;

&lt;p&gt;Once it's done, you should have a new folder at the root:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.storybook/
  config.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If not, make sure that gets created. We need to make some changes to &lt;code&gt;config.js&lt;/code&gt; to read stories within each package in the monorepo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuring Storybook for a Monorepo
&lt;/h2&gt;

&lt;p&gt;The key issue I ran into that prompted me to write about this is that we need to import stories using the &lt;a href="https://github.com/webpack/docs/wiki/context" rel="noopener noreferrer"&gt;Webpack context&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;context&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../packages&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sr"&gt;/stories.jsx&lt;/span&gt;&lt;span class="se"&gt;?&lt;/span&gt;&lt;span class="sr"&gt;$/&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This prompts Webpack to scan a &lt;code&gt;src&lt;/code&gt; directory for paths containing &lt;code&gt;stories.js&lt;/code&gt; or &lt;code&gt;stories.jsx&lt;/code&gt; anywhere in the string.&lt;/p&gt;

&lt;p&gt;Since Webpack &lt;em&gt;statically analyzes&lt;/em&gt; this code it means we &lt;strong&gt;cannot&lt;/strong&gt; dynamically read the file system and iterate through each package directory (I tried that 😔).&lt;/p&gt;

&lt;p&gt;There's another problem. Remember I mentioned each package directory has &lt;code&gt;node_modules&lt;/code&gt; which means that the following paths will match the regular expression:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./atoms/node_modules/@storybook__react/src/stories/blah.stories.js
./molecules/lcov-report/_html/src/components/Hello.stories.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And you can imagine more paths like that can match. Webpack will attempt to import these files into the bundle it generates but these will most likely cause build errors. That isn't what we want! We need to &lt;em&gt;exclude&lt;/em&gt; everything but the &lt;code&gt;src&lt;/code&gt; directory in a package when matching files.&lt;/p&gt;

&lt;p&gt;The solution, as it turns out is fairly straightforward, since we have a convention where each package has components within a &lt;code&gt;src&lt;/code&gt; directory, we really just need to match that inner &lt;code&gt;src&lt;/code&gt; after the package name, so we can write a regular expression like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;context&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../packages&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;\.\/[^\/]&lt;/span&gt;&lt;span class="sr"&gt;+&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sr"&gt;src&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sr"&gt;.*stories&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;jsx&lt;/span&gt;&lt;span class="se"&gt;?&lt;/span&gt;&lt;span class="sr"&gt;$/&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's break it down:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;^               # match beginning of path
\.\/            # the path will begin with a "./", like ./atoms
[^\/]+          # get the first path segment (match characters up to first /)
\/src\/         # ensure we match under the `src` directory
.*              # match any character
stories\.jsx?   # match anything with "stories.js(x)" in it
$               # match end of string
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's an example using my favorite regex tool &lt;a href="https://regexr.com" rel="noopener noreferrer"&gt;RegExr&lt;/a&gt; on which paths match and which don't:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Ftdt8u9xa3kwlku94d6yu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Ftdt8u9xa3kwlku94d6yu.png" alt="Regular expression match example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Handy! &lt;/p&gt;

&lt;h2&gt;
  
  
  The Final Config
&lt;/h2&gt;

&lt;p&gt;Here's our final &lt;code&gt;config.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;configure&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@storybook/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;loadStories&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;context&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../packages&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;\.\/[^\/]&lt;/span&gt;&lt;span class="sr"&gt;+&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sr"&gt;src&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sr"&gt;.*stories&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;jsx&lt;/span&gt;&lt;span class="se"&gt;?&lt;/span&gt;&lt;span class="sr"&gt;$/&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filename&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;req&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;configure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loadStories&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I hope this helps someone else and saves them the few hours I spent performing the correct rites to get this to work!&lt;/p&gt;




&lt;p&gt;If you thought this was helpful, you can follow me or &lt;a href="https://kamranicus.com/newsletter" rel="noopener noreferrer"&gt;subscribe to my blog&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Originally posted at &lt;a href="https://kamranicus.com/posts/2019-09-12-using-storybook-in-a-monorepo" rel="noopener noreferrer"&gt;Kamranicus&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>storybook</category>
    </item>
    <item>
      <title>Handling Safe Destructuring in TypeScript</title>
      <dc:creator>Kamran Ayub</dc:creator>
      <pubDate>Wed, 26 Jun 2019 13:50:40 +0000</pubDate>
      <link>https://dev.to/kamranayub/handling-safe-destructuring-in-typescript-3iln</link>
      <guid>https://dev.to/kamranayub/handling-safe-destructuring-in-typescript-3iln</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally posted on my blog at &lt;a href="https://kamranicus.com/posts/2019-06-26-typescript-safe-destructuring-patterns" rel="noopener noreferrer"&gt;kamranicus.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;When migrating from JavaScript to TypeScript, you will often run into scenarios that seem difficult to statically type related to destructuring objects.&lt;/p&gt;

&lt;h2&gt;
  
  
  Destructuring an empty object
&lt;/h2&gt;

&lt;p&gt;This pattern is showcased using the following code snippet, which reflects the semantics of some code we reviewed recently:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;transformSearchResults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="nx"&gt;queryParams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;searchTerm&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;queryParams&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;searchTerm&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nf"&gt;isSearchPayload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;transformedResults&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;anotherProp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="p"&gt;}));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This function essentially takes a payload, transforms it, and returns the modified payload object.&lt;/p&gt;

&lt;p&gt;Specifically, notice in the function arguments the expressions &lt;code&gt;= {}&lt;/code&gt; which in JavaScript will set a default value of &lt;code&gt;{}&lt;/code&gt; for the parameter if it is &lt;code&gt;undefined&lt;/code&gt;. This is done because on the next 2 lines, we attempt to destructure and pull out some key props of the objects. If &lt;code&gt;payload&lt;/code&gt; or &lt;code&gt;queryParams&lt;/code&gt; is &lt;code&gt;undefined&lt;/code&gt; then the destructuring would blow up and &lt;em&gt;we don't want this code to blow up.&lt;/em&gt; That is pretty reasonable!&lt;/p&gt;
&lt;h2&gt;
  
  
  Converting to TypeScript
&lt;/h2&gt;

&lt;p&gt;If we want to migrate this function to TypeScript, it would make sense to add a type annotation for each parameter like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ResponsePayload&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SearchResult&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;OtherResult&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;transformSearchResults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ResponsePayload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
  &lt;span class="nx"&gt;queryParams&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;QueryStringParams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We are trying to annotate our types properly by telling TypeScript what types we expect these parameters to be. We've declared our API type &lt;code&gt;ResponsePayload&lt;/code&gt; with a &lt;code&gt;results&lt;/code&gt; property.&lt;/p&gt;

&lt;p&gt;But alas, TypeScript will throw an error immediately:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Property 'results' is missing in type '{}' but required in type 'ResponsePayload'. ts(2741)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;While this might seem wrong at first on the surface, TypeScript is actually pointing out a &lt;em&gt;code smell&lt;/em&gt; in this function.&lt;/p&gt;

&lt;p&gt;The reason that TypeScript doesn't allow this is because the &lt;code&gt;ResponsePayload&lt;/code&gt; type has a &lt;code&gt;results&lt;/code&gt; property that is &lt;em&gt;required&lt;/em&gt; (cannot be undefined). We know this because we typed it that way, presumably because the API doesn't return undefined. If it did, we could change &lt;code&gt;results&lt;/code&gt; to be optional.&lt;/p&gt;

&lt;p&gt;When converting destructuring code to TypeScript, you will be encouraged to consider the code more critically than before, otherwise you will run into type errors.&lt;/p&gt;

&lt;p&gt;Here's what I ask in this situation:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Can the function be simplified to pass a specific primitive value for the parameter?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If I need to pass an object, can I refactor the function to avoid it?&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These questions are dependent on the specific case but in the &lt;em&gt;majority&lt;/em&gt; of cases, you can usually remove the need to destructure by asking these questions.&lt;/p&gt;

&lt;p&gt;For example, let's take it step-by-step.&lt;/p&gt;
&lt;h2&gt;
  
  
  Simplifying Function Parameters
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Can the function be simplified to pass a specific primitive value for the parameter?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here's the code again:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;transformSearchResults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ResponsePayload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; 
  &lt;span class="nx"&gt;queryParams&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;QueryStringParams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt; 
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;searchTerm&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;queryParams&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;searchTerm&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nf"&gt;isSearchPayload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;transformedResults&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;anotherProp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="p"&gt;}));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;A quick look will tell us that the answer is &lt;strong&gt;No&lt;/strong&gt; for &lt;code&gt;payload&lt;/code&gt; but &lt;strong&gt;Yes&lt;/strong&gt; for &lt;code&gt;queryParams&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Only &lt;code&gt;results&lt;/code&gt; in &lt;code&gt;payload&lt;/code&gt; is used but &lt;code&gt;payload&lt;/code&gt; is also being mutated, so the function needs the object passed, let's set that aside. &lt;/p&gt;

&lt;p&gt;For &lt;code&gt;queryParams&lt;/code&gt;, only &lt;code&gt;searchTerm&lt;/code&gt; is actually referenced, so let's simplify this function to pass only that:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;transformSearchResults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ResponsePayload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; 
  &lt;span class="nx"&gt;searchTerm&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;searchTerm&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nf"&gt;isSearchPayload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;transformedResults&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;anotherProp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="p"&gt;}));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Great! The rest of the code remains the same and we eliminated one unnecessary destructuring.&lt;/p&gt;
&lt;h2&gt;
  
  
  Approaches to Refactoring for Destructuring
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;If I need to pass an object, can I refactor the function to avoid it?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Right now the function requires &lt;code&gt;payload&lt;/code&gt; to be provided directly. There are two approaches we could now take:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Specifying a default value for required properties&lt;/li&gt;
&lt;li&gt;Removing the need to mutate an object so we can just pass &lt;code&gt;results&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Providing default values for properties
&lt;/h3&gt;

&lt;p&gt;If we intend to keep the logic in the function intact, we need to provide a value for all required properties of &lt;code&gt;ResponsePayload&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We can do this inline within the function which works well for a small list of parameters:.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;transformSearchResults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ResponsePayload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; 
  &lt;span class="nx"&gt;searchTerm&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;All fixed; since we provide a default value for &lt;code&gt;results&lt;/code&gt; which isn't &lt;code&gt;undefined&lt;/code&gt; TypeScript is happy.&lt;/p&gt;

&lt;p&gt;We could also choose to provide a default object for more complex situations:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;defaultPayload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ResponsePayload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;transformSearchResults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ResponsePayload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;defaultPayload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nx"&gt;searchTerm&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This works just as well but introduces a dangling object that might not add a ton of value. Can we remove the need for providing &lt;code&gt;payload&lt;/code&gt; in the first place?&lt;/p&gt;
&lt;h3&gt;
  
  
  Removing the object altogether
&lt;/h3&gt;

&lt;p&gt;The fact that the function mutates the original incoming object is a smell itself. There are cases where that makes sense but in this case, we are transforming results--we should just return the newly mapped results and &lt;em&gt;push the concern of mutating &lt;code&gt;payload&lt;/code&gt;&lt;/em&gt; to a higher-level.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;transformSearchResults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SearchResults&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;OtherResults&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; 
  &lt;span class="nx"&gt;searchTerm&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;searchTerm&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nf"&gt;isSearchPayload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;anotherProp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="p"&gt;}));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;em&gt;Nearly there.&lt;/em&gt; We will now receive an error because &lt;code&gt;isSearchPayload&lt;/code&gt; was testing the payload itself. We have two options:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Modify &lt;code&gt;isSearchPayload&lt;/code&gt; to inspect results&lt;/li&gt;
&lt;li&gt;Push the concern of checking payload higher&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We could certainly do option 1 but I like option 2 better. It will end up simplifying the &lt;code&gt;results&lt;/code&gt; typing even more because we can &lt;em&gt;know&lt;/em&gt; the results are &lt;em&gt;search results&lt;/em&gt;! This also makes the function name much more accurate:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;transformSearchResults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SearchResults&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; 
  &lt;span class="nx"&gt;searchTerm&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;searchTerm&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;anotherProp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="p"&gt;}));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;There we go; we've totally removed the need for destructuring with this function by simplifying the requirements and avoiding mutation of objects.&lt;/p&gt;
&lt;h3&gt;
  
  
  Where did the complexity go?
&lt;/h3&gt;

&lt;p&gt;By refactoring the function we pushed two concerns higher in the call stack:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Is this a search payload (&lt;code&gt;isSearchPayload&lt;/code&gt;)?&lt;/li&gt;
&lt;li&gt;Handling &lt;code&gt;transformedResults&lt;/code&gt; for &lt;code&gt;payload&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That logic still has to exist somewhere but now it can be lifted higher. There is a principle at work here called the &lt;a href="https://en.wikipedia.org/wiki/Command%E2%80%93query_separation" rel="noopener noreferrer"&gt;Command-Query Separation&lt;/a&gt; principle, which says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"every method should either be a command that performs an action, or a query that returns data to the caller, but not both. In other words, &lt;strong&gt;Asking a question should not change the answer.&lt;/strong&gt;"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Before we refactored this function, it violated this principle because it both &lt;em&gt;returned new results&lt;/em&gt; (a query) &lt;strong&gt;and&lt;/strong&gt; had a side effect by mutating the object (a command). Now we've refactored it into a "query" function only.&lt;/p&gt;

&lt;p&gt;If we had inspected the previous way this function was called, you would have seen this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;ResponsePayload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Missing response payload!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;transformSearchResults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;queryParams&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This should raise a yellow flag since it is returning the object again which implies it may be mutating it (in other words, "it smells").&lt;/p&gt;

&lt;p&gt;Now that we've refactored the function above, some responsibilities have been pushed higher, which may result in a change like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;ResponsePayload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Missing response payload!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;isSearchPayload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;transformedResults&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;transformSearchResults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We avoid mutating the payload directly instead opting to merge the new property in. We now have options to extract this logic, refactor it, etc. which you can decide!&lt;/p&gt;
&lt;h2&gt;
  
  
  Handling Nested Destructuring
&lt;/h2&gt;

&lt;p&gt;If we're able to remove the need to destructure by simplifying functions that is a win but what if we really need to safely destructure and more specifically, in a nested way?&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;field1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;field2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;field3&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This is slightly more complicated and subsequently harder to type &lt;em&gt;and it should be&lt;/em&gt;. One thing I have come to appreciate about TypeScript is that it makes you feel the pain a little more which in turn encourages you to take a step back and question why the code is structured the way it is.&lt;/p&gt;

&lt;p&gt;In this example, we can ask the same question we originally asked: &lt;em&gt;Do we really need &lt;code&gt;data&lt;/code&gt; or can we be more specific?&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Keeping &lt;code&gt;data&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Let's say we must keep &lt;code&gt;data&lt;/code&gt; as a parameter. If &lt;code&gt;meta&lt;/code&gt; and all the &lt;code&gt;field*&lt;/code&gt; properties &lt;em&gt;can truly be &lt;code&gt;undefined&lt;/code&gt;&lt;/em&gt; and are marked as so, this code will work.&lt;/p&gt;

&lt;p&gt;As soon as one of them is non-optional, TypeScript will throw an error since we haven't provided defaults.&lt;/p&gt;

&lt;p&gt;For example, let's say &lt;code&gt;data&lt;/code&gt; is typed as:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Data&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Metadata&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Metadata&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;field1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;field2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;field3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;meta&lt;/code&gt; is not optional, it must be provided so the code above will throw an error as no default &lt;code&gt;meta&lt;/code&gt; value is provided and neither are the &lt;code&gt;field*&lt;/code&gt; defaults. Yikes!&lt;/p&gt;

&lt;p&gt;The best approach is to do a refactoring like we did above to simplify the parameters, if possible.&lt;/p&gt;

&lt;p&gt;The next best thing is to &lt;em&gt;remove the default&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;field1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;field2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;field3&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This matches how we've described the types -- that no property can be &lt;code&gt;undefined&lt;/code&gt; so there's no &lt;em&gt;reason&lt;/em&gt; to use a default parameter anymore. If this matches what you expect, there's nothing additional to do.&lt;/p&gt;

&lt;p&gt;What if in practice, things could potentially be &lt;code&gt;undefined&lt;/code&gt; but we still want to ensure the types remain "pure"?&lt;/p&gt;

&lt;p&gt;Then we should push the "guarding" of potentially &lt;code&gt;undefined&lt;/code&gt; values higher up the stack:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;checkData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Data&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Data shouldn't be undefined&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;handleData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// No longer can be undefined&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="c1"&gt;// This is safe to do now&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;field1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;field2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;field3&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In general, you should guard as close to the source as possible. This keeps downstream functions simpler and with TypeScript, you can ensure they get passed values that don't &lt;em&gt;need&lt;/em&gt; defaults to be provided.&lt;/p&gt;
&lt;h3&gt;
  
  
  Supporting partial objects
&lt;/h3&gt;

&lt;p&gt;Let's assume that &lt;code&gt;meta&lt;/code&gt; fields &lt;em&gt;can&lt;/em&gt; be partially available, we can simplify and statically type the function like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Data&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Metadata&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Metadata&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;field1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;field2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;field3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="c1"&gt;// This is safe now as `meta` can be partially undefined&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;field1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;field2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;field3&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now we've &lt;em&gt;explicitly&lt;/em&gt; declared that &lt;code&gt;meta&lt;/code&gt; can be partially defined. This does two things: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;it allows the safe destructuring without compiler errors and,&lt;/li&gt;
&lt;li&gt;it tells the reader to &lt;em&gt;expect&lt;/em&gt; to guard against partially defined fields.&lt;/li&gt;
&lt;li&gt;we have made &lt;a href="https://fsharpforfunandprofit.com/posts/designing-with-types-making-illegal-states-unrepresentable/" rel="noopener noreferrer"&gt;an illegal state unrepresentable&lt;/a&gt; meaning that &lt;code&gt;Metadata&lt;/code&gt; should not have any fields optional &lt;em&gt;ideally&lt;/em&gt; but the function can support partial properties in an isolated way&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Static types are documentation and now we've called out to expect that &lt;code&gt;meta&lt;/code&gt; can have partial fields. It also allows us to safely set the default object to &lt;code&gt;{}&lt;/code&gt; to avoid errors while destructuring.&lt;/p&gt;
&lt;h2&gt;
  
  
  The last resort: type assertions
&lt;/h2&gt;

&lt;p&gt;There is a hammer we can use as a last resort. If we can't effectively refactor out destructuring or if we really need to force this pattern to avoid changing code, we can use type assertions:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;transformSearchResults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;ResponsePayload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;queryParams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;QueryStringParams&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This will force TS to treat the empty object &lt;em&gt;as&lt;/em&gt; the types we want--but this introduces potential for bugs as now we are opting out of the type safety. We are putting the responsibility of checking for &lt;code&gt;undefined&lt;/code&gt; on the developer writing the function vs. the TypeScript compiler.&lt;/p&gt;

&lt;p&gt;If you do this with ESLint rules enabled, you'll be greeted with an error:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Type assertion on object literals is forbidden, 
use a type annotation instead. 
eslint(@typescript-eslint/no-object-literal-type-assertion)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Again this is because it's best to &lt;em&gt;avoid this&lt;/em&gt; in the first place. In order to get this to compile, you'll need to disable the error:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/*  eslint-disable-next-line @typescript-eslint/no-object-literal-type-assertion */&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;transformSearchResults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;ResponsePayload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;queryParams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;QueryStringParams&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;At least now, you can later search for these disabled errors as an indication to revisit and refactor later.&lt;/p&gt;
&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;When migrating to TypeScript, you will run into a lot of issues like this that on the surface feel like you're battling the type system but what I hoped to get across is that &lt;em&gt;TypeScript is forcing you to think more explicitly about how your code is structured and what your intent is.&lt;/em&gt; It will force you to look &lt;em&gt;beyond&lt;/em&gt; the scope of a single function and think more holistically about usage and context.&lt;/p&gt;

&lt;p&gt;When you find yourself trying to disable rules or workaround TypeScript errors through type assertions, you need to take a step back and ask: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Is this the best way to structure this code or is TypeScript hinting that I may need to refactor it?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This type of mindset is a &lt;em&gt;shift in thinking&lt;/em&gt; when working with TypeScript, especially when you've come from JavaScript. It may be painful at first but ultimately it will lead to better, hopefully simpler code.&lt;/p&gt;

&lt;p&gt;If you're interested in furthering your understanding of principles like Command-Query Separation and refactoring code, I highly recommend the &lt;a href="https://app.pluralsight.com/library/courses/encapsulation-solid/table-of-contents" rel="noopener noreferrer"&gt;Encapsulation and SOLID course&lt;/a&gt; by Mark Seeman from Pluralsight.&lt;/p&gt;

&lt;p&gt;You can also check out my collection of React and TypeScript content!&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/kamranayub" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F65961%2Fd89a031f-8bda-47ee-be34-be818ae980fe.jpg" alt="kamranayub"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/kamranayub/how-to-get-started-using-react-with-typescript-21c" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;How to Get Started Using React with Typescript&lt;/h2&gt;
      &lt;h3&gt;Kamran Ayub ・ Mar 5 '19&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#react&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#typescript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#guides&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;



</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>refactoring</category>
      <category>softwarequality</category>
    </item>
    <item>
      <title>Copying to the clipboard using React, TypeScript &amp; Material UI</title>
      <dc:creator>Kamran Ayub</dc:creator>
      <pubDate>Thu, 11 Apr 2019 18:53:24 +0000</pubDate>
      <link>https://dev.to/kamranayub/copying-to-the-clipboard-using-react-typescript-material-ui-4fdb</link>
      <guid>https://dev.to/kamranayub/copying-to-the-clipboard-using-react-typescript-material-ui-4fdb</guid>
      <description>&lt;p&gt;It's common in apps to offer a way to "copy to clipboard" so users can paste content.&lt;/p&gt;

&lt;p&gt;I whipped up a quick example using TypeScript and React to make such a behavior that can be applied to any React element using the &lt;a href="https://pluralsight.pxf.io/x5PN5"&gt;render props pattern&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/x3564644kp?module=/src/CopyToClipboard.tsx"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;You can then use it like this, to wrap &lt;code&gt;&amp;lt;Button /&amp;gt;&lt;/code&gt; or any other element:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;CopyToClipboard&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;{({&lt;/span&gt; &lt;span class="nx"&gt;copy&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Button&lt;/span&gt;
      &lt;span class="nx"&gt;variant&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"contained"&lt;/span&gt;
      &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"primary"&lt;/span&gt;
      &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"some text!"&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nx"&gt;Copy&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)}&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/CopyToClipboard&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This is using the super simple &lt;a href="https://www.npmjs.com/package/clipboard-copy"&gt;clipboard-copy&lt;/a&gt; package.&lt;/p&gt;

&lt;p&gt;You can override the &lt;code&gt;&amp;lt;Tooltip /&amp;gt;&lt;/code&gt; props using the &lt;code&gt;TooltipProps&lt;/code&gt; prop:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;CopyToClipboard&lt;/span&gt; &lt;span class="nx"&gt;TooltipProps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Copied XYZ!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;leaveDelay&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Enjoy!&lt;/p&gt;

</description>
      <category>react</category>
      <category>typescript</category>
      <category>materialui</category>
      <category>programming</category>
    </item>
    <item>
      <title>How to Get Started Using React with Typescript</title>
      <dc:creator>Kamran Ayub</dc:creator>
      <pubDate>Tue, 05 Mar 2019 20:48:58 +0000</pubDate>
      <link>https://dev.to/kamranayub/how-to-get-started-using-react-with-typescript-21c</link>
      <guid>https://dev.to/kamranayub/how-to-get-started-using-react-with-typescript-21c</guid>
      <description>&lt;p&gt;I got started using &lt;a href="https://reactjs.org"&gt;React&lt;/a&gt; with &lt;a href="https://typescriptlang.org"&gt;TypeScript&lt;/a&gt; about 2 years ago now and have been working on several projects both at home and at work that utilize both technologies. I'm loving it but I also see a lot of questions around specific patterns around using TypeScript with React. Many of these questions I've tackled in my projects but haven't sat down to write about, though &lt;a href="https://www.youtube.com/watch?v=3ZbYCtnwPsY"&gt;I have talked about many of them&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In 2019 my goal was to write more about these topics and so far I have published three guides that cover the topics you need to get started from scratch and take you through statically typing React. &lt;/p&gt;

&lt;p&gt;The benefit to sharing these guides is primarily to help people and to see if there's enough interest to warrant pitching a course or other long-form content on the topic! I've been a TypeScript user for over 5 years and I love how much it's growing in the community!&lt;/p&gt;

&lt;h3&gt;
  
  
  Guides
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Disclosure: The guides are free to read without a Pluralsight subscription and I don't get any kickbacks.&lt;/em&gt; I've already gotten paid to write them initially which made them a good use of my time! Now I just want people to know they exist.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.pluralsight.com/guides/typescript-react-getting-started"&gt;Getting Started with React and TypeScript&lt;/a&gt;&lt;/strong&gt; - Zero to bootstrapped project using multiple ways like create-react-app, from scratch, Webpack, and Parcel.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.pluralsight.com/guides/how-to-statically-type-react-components-with-typescript"&gt;How to Statically Type React Components with TypeScript&lt;/a&gt;&lt;/strong&gt; - Covers patterns on statically typing React components, props, and state.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.pluralsight.com/guides/composing-react-components-with-typescript"&gt;Composing React Components with TypeScript&lt;/a&gt;&lt;/strong&gt; - Covers common patterns of composing React components such as inheritance, specialization, and render props.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://app.pluralsight.com/guides/how-to-test-react-components-in-typescript"&gt;How to Test React Components in TypeScript&lt;/a&gt;&lt;/strong&gt; - Covers using Jest with TypeScript to test React components&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://dev.to/kamranayub/handling-safe-destructuring-in-typescript-3iln"&gt;Handling Safe Destructuring in TypeScript&lt;/a&gt;&lt;/strong&gt; - Covers patterns on avoiding excessive destructuring and how to effectively handle defaults/fallbacks with object destructuring&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Other resources I've created:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://www.youtube.com/watch?v=3ZbYCtnwPsY"&gt;Building Scalable, Maintainable Apps Using TypeScript and React&lt;/a&gt;&lt;/strong&gt; - Conference talk I gave recently on some patterns &amp;amp; practices I've picked up that I use in my apps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/kamranayub/sample-react-ts-app"&gt;Sample React &amp;amp; TypeScript Patterns Repo&lt;/a&gt;&lt;/strong&gt; - Companion repository for my talk that has all the code samples.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Other resources I've seen:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/piotrwitek/react-redux-typescript-guide"&gt;Complete React &amp;amp; TypeScript Guide&lt;/a&gt;&lt;/strong&gt; - This is pretty amazing work by &lt;/p&gt;
&lt;div class="ltag__user ltag__user__id__259906"&gt;
  
    .ltag__user__id__259906 .follow-action-button {
      background-color: #093656 !important;
      color: #ffffff !important;
      border-color: #093656 !important;
    }
  
    &lt;a href="/piotrwitek" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3BYQvjAD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/practicaldev/image/fetch/s--t6CUNhtN--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_150%2Cq_auto%2Cw_150/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/259906/c94672eb-cce7-437b-a100-0803fc8d5677.jpeg" alt="piotrwitek image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/piotrwitek"&gt;Piotrek Witek&lt;/a&gt;
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/piotrwitek"&gt;&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/sw-yx/react-typescript-cheatsheet"&gt;React &amp;amp; TypeScript Cheatsheet Repo&lt;/a&gt;&lt;/strong&gt; - Fantastic resource for lots of examples and recipes&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I hope this helps others to learn the nuances of using TypeScript with React and I'll be sure to update this post as I put out more guides or find more resources!&lt;/p&gt;

&lt;p&gt;Be sure to share other resources if you're also using React and TypeScript, I'd love to see them!&lt;/p&gt;

</description>
      <category>react</category>
      <category>typescript</category>
      <category>guides</category>
    </item>
  </channel>
</rss>
