[
  {
    "title": "Iterating Through TypeScript Dictionaries",
    "body": "<p>When utilizing a <code>Dictionary</code> data structure in TypeScript, we often need to iterate through key/value pairs.</p>\n<p>One approach is to use a <code>for...in</code> loop:</p>\n<pre><code class=\"language-typescript\">for (const key in userDictionary) {\n    const value = userDictionary[key];\n    console.log(key, value)\n}\n</code></pre>\n<p>This works well, except that <code>tslint</code> will throw an error here. That's because <code>tslint</code>:</p>\n<blockquote>\n<p>requires a <code>for...in</code> statement to be filtered with an if statement.</p>\n</blockquote>\n<p>This <code>if</code> statement must be immediate:</p>\n<pre><code class=\"language-typescript\">for (const key in userDictionary) {\n    if (userDictionary.hasOwnProperty(key)) {\n        ...\n\t}\n}\n</code></pre>\n<p>This approach is a bit inflexible, so a better approach is to use <code>Object.entries</code>, which returns key value/pairs in a different way:</p>\n<pre><code class=\"language-typescript\">Object.entries(userDictionary)\n    .forEach(([key, value]) =&gt; console.log(key, value));\n</code></pre>\n<p>This avoids the <code>tslint</code> error, and is generally cleaner in my opinion.</p>\n<p>One caveat is that <code>Object.entries</code> was only officially added in the ES2017 specification, so it still doesn't have perfect support.</p>\n"
  },
  {
    "title": "Sorting Object Properties in JavaScript",
    "body": "<p>After receiving a JSON response from a server, it is often necessary to perform some front-end sorting.</p>\n<p>For example, let’s say we're working on an HR web app and want to sort employees by the number of holidays they have remaining.</p>\n<p>We query the employee database and receive the following response:</p>\n<pre><code class=\"language-json\">const response = [ \n   { \n      &quot;id&quot;:&quot;ITB89-001&quot;,\n      &quot;surname&quot;:&quot;Marone&quot;,\n      &quot;given_name&quot;:&quot;Peter&quot;,\n      &quot;title&quot;:&quot;Developer&quot;,\n      &quot;holidays&quot;:&quot;21&quot;\n   },\n   { \n      &quot;id&quot;:&quot;ITB89-008&quot;,\n      &quot;surname&quot;:&quot;Gallant&quot;,\n      &quot;given_name&quot;:&quot;Max&quot;,\n      &quot;title&quot;:&quot;Developer&quot;,\n      &quot;holidays&quot;:&quot;18&quot;\n   },\n   { \n      &quot;id&quot;:&quot;ITB89-006&quot;,\n      &quot;surname&quot;:&quot;Reyes&quot;,\n      &quot;given_name&quot;:&quot;Bernard&quot;,\n      &quot;title&quot;:&quot;Manager&quot;,\n      &quot;holidays&quot;:&quot;29&quot;\n   }\n]\n</code></pre>\n<p>To sort employees by remaining holidays in ascending order, we can use JavaScript's native <code>sort</code> function along with coercing the <code>holidays</code> property to a <code>Number</code>.</p>\n<pre><code class=\"language-javascript\">response.sort((a, b) =&gt; Number(a.holidays) - Number(b.holidays));\n</code></pre>\n<p>If we're looking to sort by string properties, such as <code>surname</code> in this case, we can use the <code>localeCompare()</code> method:</p>\n<blockquote>\n<p>The <strong>localeCompare()</strong> method returns a number indicating whether a reference string comes before or after or is the same as the given string in sort order.</p>\n</blockquote>\n<pre><code class=\"language-javascript\">response.sort((a, b) =&gt; a.localeCompare(b));\n</code></pre>\n<p>Note that the base <code>localeCompare()</code> is case insensitive, which works well for properties like names. If you need a case sensitive comparison, <code>localeCompare()</code> provides an <code>options</code> object which includes language and case options.</p>\n<pre><code class=\"language-javascript\">response.sort((a, b) =&gt; a.localeCompare(b, 'en', { sensitivity: 'case' }));\n</code></pre>\n<p>It is worth mentioning that <code>localCompare()</code> can also be used to sort numbers by setting the <code>numeric</code> property to <code>true</code> on the <code>options</code> object. However, using the <code>sort</code> with coerced numbers is a more common pattern.</p>\n"
  },
  {
    "title": "Angular Dependency Injection and Code Execution",
    "body": "<p>Because of Angular's use of a rather complex compiler, it's not always clear when dependency injection actually occurs, and when certain services or properties become available.</p>\n<p>As a general rule, anything injected in the constructor is available when class properties are initialized.</p>\n<p>For example this class:</p>\n<pre><code class=\"language-typescript\">export class Example {\n    exampleProperty = &quot;hello world&quot;;\n\n    constructor(private store: Store) {}\n\n}\n</code></pre>\n<p>Gets compiled into this IIFE by Angular:</p>\n<pre><code class=\"language-typescript\">var Example = (function() {\n    function Example(store) {\n        this.store = store;\n        this.exampleProperty = &quot;hello world&quot;;\n\t}\n})();\n</code></pre>\n<p>Whatever is injected in the constructor is assigned first, so is available when any subsequent properties are initialized.</p>\n<p>That's why something like this works fine:</p>\n<pre><code class=\"language-typescript\">export class Example {\n    exampleStore = this.store;\n\n    constructor(private store: Store) {}\n\n}\n</code></pre>\n<p>Although this works, it is usually a better practice to initialize properties that rely on dependency injection in the <code>ngOnInit()</code> method.</p>\n<pre><code class=\"language-typescript\">export class Example implements OnInit {\n    exampleStore: Store | undefined;\n\n    constructor(private store: Store) {}\n\n    ngOnInit() {\n        this.exampleStore = store;\n    }\n}\n</code></pre>\n<p>The assignment to <code>exampleStore</code> here is more explicit and generally easier to follow.</p>\n"
  },
  {
    "title": "Generating a Specific Number of Elements or Iterations in JavaScript",
    "body": "<p>Many situations require you to generate a specific number of elements or iterations.</p>\n<p>For example, let's say we needed to generate a table with exactly 45 rows.</p>\n<pre><code class=\"language-typescript\">const rows = 45;\n\nfunction addRow() {\n    ..adds a row to the table\n}\n</code></pre>\n<p>Many developers prefer chainable higher-order functions like <code>forEach</code>, <code>map</code>, and <code>filter</code> over counting loops.</p>\n<p>It's perfectly possible to do this.</p>\n<p>Here are some examples:</p>\n<p>Using the <code>new</code> keyword (not recommended):</p>\n<pre><code class=\"language-typescript\">new Array(rows).map(() =&gt; addRow());\n</code></pre>\n<p>Using <code>Array.fill()</code>:</p>\n<pre><code class=\"language-typescript\">Array(rows).fill(undefined).map(() =&gt; addRow());\n</code></pre>\n<p>Using <code>Array.from()</code>:</p>\n<pre><code class=\"language-typescript\">Array.from({ length: rows }, () =&gt; addRow());\n</code></pre>\n<p>Using the <code>spread</code> operator:</p>\n<pre><code class=\"language-typescript\">[...Array(rows)].map(() =&gt; addRow());\n</code></pre>\n"
  },
  {
    "title": "Automatic Semicolon Insertion in JavaScript",
    "body": "<p>JavaScript's <em>Automatic Semicolon Insertion</em> (ASI) is like a built-in linter that goes through your code and inserts semicolons in their proper places.</p>\n<p>For the most part ASI is silent and harmless. There is one case though (described below) where it is prone to causing issues.</p>\n<p>Some of the most common places semicolons are inserted include the following:</p>\n<ol>\n<li>\n<p>After the <code>return</code> keyword:</p>\n<pre><code class=\"language-js\">return ouput\n// is parsed as\nreturn ouput;\n</code></pre>\n</li>\n<li>\n<p>After an expression:</p>\n<pre><code class=\"language-js\">(a + b) * c\n// is parsed as\n(a + b) * c;\n</code></pre>\n</li>\n<li>\n<p>After variable declarations:</p>\n<pre><code class=\"language-js\">const exampleFlag = true\n// is parsed as\nconst exampleFlag = true;\n</code></pre>\n</li>\n<li>\n<p>After <code>continue</code> and <code>break</code> statements:</p>\n<pre><code class=\"language-js\">for (const value of values) {\n  console.log(value)\n  break\n}\n// is parsed as\nfor (const value of values) {\n  console.log(value);\n  break;\n}\n</code></pre>\n</li>\n<li>\n<p>After <code>debugger</code> statements:</p>\n<pre><code class=\"language-js\">function testCode() {\n  debugger\n}\n// is parsed as\nfunction testCode() {\n  debugger;\n}\n</code></pre>\n</li>\n</ol>\n<p>Now for the problem. As the JavaScript engine is parsing your code and inserting semicolons, if it encounters an illegal line break or closing bracket <code>}</code>, it will insert a semicolon on the previous valid statement or before the closing bracket.</p>\n<p>For example:</p>\n<pre><code class=\"language-js\">{ 1 2 } 3\n// is parsed as\n{ 1 2 ;} 3;\n</code></pre>\n<p>And:</p>\n<pre><code class=\"language-js\">return;\n{\n  position: 'developer';\n}\n// is parsed as\nreturn;\n{\n  position: 'developer';\n}\n</code></pre>\n<p>Developers who choose not to use semicolons (relying purely on ASI) should at least use a good linter that will fix line breaks and prevent these types of bugs.</p>\n"
  },
  {
    "title": "Understanding the Difference Between null and undefined in JavaScript",
    "body": "<p><code>Undefined</code> means that a reference has not been declared or has not been given a value.</p>\n<p><code>Null</code> is an assigned value that represents a null, empty, or non-existent reference.</p>\n<p>In general, <code>null</code> is used to set something to empty, while <code>undefined</code> is empty because it has not been set.</p>\n<p>Both <code>null</code> and <code>undefined</code> are falsy.</p>\n<h2>Nuances</h2>\n<p>Consider <code>undefined</code> and <code>null</code> in relation to the following types of variables:</p>\n<h3>Undeclared Variables</h3>\n<p>If you check an undeclared variable with <code>typeof</code> it will return <code>undefined</code>.</p>\n<p>Any other operation will throw a Reference Error.</p>\n<h3>Declared But Unassigned Variables</h3>\n<p>The JavaScript engine sets declared variables to <code>undefined</code> during the Creation Phase, before assigning them values during the Execution Phase. For declared but unassigned variables, <code>typeof</code> will return <code>undefined</code>.</p>\n<h3>Variables Set to <code>undefined</code></h3>\n<p>Variables set explicitly to <code>undefined</code> will behave the same as declared variables that have not been given values. This is the one case where an <code>undefined</code> value isn't coming from the JavaScript engine.</p>\n<h3>Variables Set to <code>null</code></h3>\n<p>Variables set explicitly to <code>null</code> will have a <code>typeof</code> of <code>object</code>. <code>Null</code> is not set by the JavaScript engine and must be set explicitly.</p>\n"
  },
  {
    "title": "Filtering Objects for Specific Values",
    "body": "<p>It is often useful to filter objects in order to extract out relevant data, leaving a smaller object that is easier to work with.</p>\n<p>Consider a simple object containing the number of customers per month for an online store.</p>\n<pre><code class=\"language-typescript\">const customerCount = {\n  &quot;Jan&quot;: 1484,\n  &quot;Feb&quot;: 2536,\n  &quot;Mar&quot;: 1260,\n  &quot;Apr&quot;: 2431,\n  &quot;May&quot;: 2261,\n  &quot;Jun&quot;: 1242,\n  &quot;Jul&quot;: 2664,\n  &quot;Aug&quot;: 2348,\n  &quot;Sep&quot;: 3006,\n  &quot;Oct&quot;: 2161,\n  &quot;Nov&quot;: 1421,\n  &quot;Dec&quot;: 1290\n}\n</code></pre>\n<p>Let's say we're only interested in customers during the first quarter of the year, i.e. January, February and March.</p>\n<p>We can extract this data by first creating an array of the data we need:</p>\n<pre><code class=\"language-typescript\">const relevantMonths = [&quot;Jan&quot;, &quot;Feb&quot;, &quot;Mar&quot;];\n</code></pre>\n<p>We can then use <code>reduce</code> to filter for the relevant months:</p>\n<pre><code class=\"language-typescript\">relevantMonths.reduce((previousResult, month) =&gt; ({ ...previousResult, [month]: customerCount[month] }), {})\n</code></pre>\n<p>What's happening here?</p>\n<p>The second argument of <code>reduce</code> takes an initial value, and here we're passing an empty object, which is what we'll start with.</p>\n<p>For every month in the <code>relevantMonths</code> array, we then build onto the initial empty object by combining the object created during the previous iteration (if there was one), with a new <code>month</code> property that has the same value as <code>month</code> in the <code>customerCount</code> object.</p>\n<p>The end result is a single object that contains only the properties specified in our <code>relevantMonths</code> array.</p>\n"
  },
  {
    "title": "Generating a List of Months",
    "body": "<p>When working with months, it's common for developers to write out a literal list of month names:</p>\n<pre><code class=\"language-typescript\">const months = [&quot;January&quot;, &quot;February&quot;, &quot;March&quot;, ...];\n</code></pre>\n<p>Instead of doing this, we can take advantage of JavaScript's built-in <code>Date</code> objects to generate a list for us:</p>\n<pre><code class=\"language-typescript\">const months = [...Array(12)].map((month, index) =&gt; new Date(0, index).toLocaleDateString('en-US', { month: 'long' }));\n</code></pre>\n<p>Here we're creating an Array object with a length of <code>12</code> and spreading those 12 empty slots into an iterable array, which is then mapped over.</p>\n<p>On each iteration, we're creating a new <code>Date</code> object and passing in a year and a month.</p>\n<p>Passing in <code>0</code> for the year defaults to <code>1900</code> and the month value is zero-indexed, so we're generating dates of <code>1900-01-01</code>, <code>1900-01-02</code>, etc.</p>\n<p>These dates are then formatted to only include the month name.</p>\n<p>Here's a function which can be used to generate months in different formats:</p>\n<pre><code class=\"language-typescript\">function generateMonths(format: string = &quot;long&quot;): string[] {\n  return [...Array(12)].map((month, index) =&gt; new Date(0, index).toLocaleDateString('en-US', { month: format }));\n}\n\ngenerateMonths(&quot;short&quot;); // [&quot;Jan&quot;, &quot;Feb&quot;, &quot;Mar&quot;, ... ]\ngenerateMonths(&quot;narrow&quot;); // [&quot;J&quot;, &quot;F&quot;, &quot;M&quot;, ... ]\ngenerateMonths(&quot;2-digit&quot;); // [&quot;01&quot;, &quot;02&quot;, &quot;03&quot;, ... ]\n</code></pre>\n"
  },
  {
    "title": "Swapping Variables with Destructuring",
    "body": "<p>Swapping two values often involves a temporary variable:</p>\n<pre><code class=\"language-typescript\">const a = 1;\nconst b = 2;\nconst temp = a;\nconst swappedA = b;\nconst swappedB = temp;\n</code></pre>\n<p>Destructuring can express the same idea in one line by binding new <code>const</code> values:</p>\n<pre><code class=\"language-typescript\">const a = 1;\nconst b = 2;\nconst [swappedA, swappedB] = [b, a];\n// swappedA is 2, swappedB is 1\n</code></pre>\n<p>The right-hand side is evaluated before assignment, so the original <code>a</code> and <code>b</code> are used correctly.</p>\n<p>If you truly need to reassign existing bindings in place, destructuring assignment works too, but that requires <code>let</code> or <code>var</code>. For <code>const</code>-only code, prefer new bindings as above.</p>\n"
  },
  {
    "title": "Debouncing a Function in Plain JavaScript",
    "body": "<p>Search boxes, resize handlers, and scroll listeners can fire many times in a short period. Running expensive work on every event is wasteful.</p>\n<p>Debouncing waits until the user pauses, then runs the handler once:</p>\n<pre><code class=\"language-typescript\">function debounce(fn, delayMs) {\n  const state = { timeoutId: undefined };\n\n  return (...args) =&gt; {\n    clearTimeout(state.timeoutId);\n    state.timeoutId = setTimeout(() =&gt; fn(...args), delayMs);\n  };\n}\n\nconst onSearchInput = debounce((value: string) =&gt; {\n  console.log(&quot;Searching for:&quot;, value);\n}, 300);\n</code></pre>\n<p>Each time the wrapped function is called, the previous timer is cleared and a new one is started. The inner function only runs after <code>delayMs</code> passes with no new calls.</p>\n<p>Hook it up to an input:</p>\n<pre><code class=\"language-typescript\">input.addEventListener(&quot;input&quot;, event =&gt; {\n  const target = event.target as HTMLInputElement;\n  onSearchInput(target.value);\n});\n</code></pre>\n<p>Three hundred milliseconds is a common starting point for typing. Resize handlers often use a slightly longer delay.</p>\n"
  },
  {
    "title": "Removing Duplicates from Arrays with Set",
    "body": "<p>When you need unique values from an array, a common approach is to loop and check whether each value was seen before.</p>\n<p>A shorter option is to use a <code>Set</code>, which only stores unique values:</p>\n<pre><code class=\"language-typescript\">const tags = [&quot;js&quot;, &quot;typescript&quot;, &quot;js&quot;, &quot;react&quot;, &quot;typescript&quot;];\n\nconst uniqueTags = [...new Set(tags)];\n// [&quot;js&quot;, &quot;typescript&quot;, &quot;react&quot;]\n</code></pre>\n<p>Here we pass the array into <code>Set</code>, then spread the result back into an array.</p>\n<p>If you need to filter objects by a property, <code>Set</code> still helps for the keys:</p>\n<pre><code class=\"language-typescript\">const users = [\n  { id: 1, team: &quot;A&quot; },\n  { id: 2, team: &quot;B&quot; },\n  { id: 3, team: &quot;A&quot; },\n];\n\nconst teams = [...new Set(users.map(user =&gt; user.team))];\n// [&quot;A&quot;, &quot;B&quot;]\n</code></pre>\n<p><code>Set</code> uses strict equality (<code>===</code>), so <code>{ id: 1 }</code> and <code>{ id: 1 }</code> are treated as different objects. For primitives like strings and numbers, it works well.</p>\n"
  },
  {
    "title": "Nullish Coalescing vs || for Default Values",
    "body": "<p>The <code>||</code> operator is often used to provide a default when a value is &quot;missing&quot;:</p>\n<pre><code class=\"language-typescript\">const count = 0;\nconst displayCount = count || 10;\n// displayCount is 10\n</code></pre>\n<p>That works for <code>null</code> and <code>undefined</code>, but it also treats <code>0</code>, <code>&quot;&quot;</code>, and <code>false</code> as missing. Sometimes that is what you want. Often it is not.</p>\n<p>The nullish coalescing operator (<code>??</code>) only falls back when the value is <code>null</code> or <code>undefined</code>:</p>\n<pre><code class=\"language-typescript\">const count = 0;\nconst displayCount = count ?? 10;\n// displayCount is 0\n\nconst name = &quot;&quot;;\nconst displayName = name ?? &quot;Guest&quot;;\n// displayName is &quot;&quot;\n</code></pre>\n<p>A practical pattern is combining optional chaining with nullish coalescing:</p>\n<pre><code class=\"language-typescript\">const city = user.address?.city ?? &quot;Unknown&quot;;\n</code></pre>\n<p>Use <code>||</code> when any falsy value should trigger the default. Use <code>??</code> when only <code>null</code> or <code>undefined</code> should.</p>\n"
  },
  {
    "title": "Negative Array Indexes with at()",
    "body": "<p>To get the last item in an array, many developers write:</p>\n<pre><code class=\"language-typescript\">const items = [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;];\nconst last = items[items.length - 1];\n</code></pre>\n<p>That works, but it is awkward when you want the second-to-last item or a dynamic offset from the end.</p>\n<p><code>Array.prototype.at()</code> accepts negative indices:</p>\n<pre><code class=\"language-typescript\">const items = [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;];\n\nitems.at(-1); // &quot;c&quot;\nitems.at(-2); // &quot;b&quot;\nitems.at(0);  // &quot;a&quot;\n</code></pre>\n<p>If the index is out of range, <code>at()</code> returns <code>undefined</code> instead of throwing:</p>\n<pre><code class=\"language-typescript\">items.at(10); // undefined\n</code></pre>\n<p>For positive indices, <code>at()</code> behaves like bracket notation. The main benefit is readable access from the end without repeating <code>length</code>.</p>\n"
  },
  {
    "title": "Shallow vs Deep Copying Objects",
    "body": "<p>The spread operator copies an object one level deep:</p>\n<pre><code class=\"language-typescript\">const original = {\n  name: &quot;Ada&quot;,\n  scores: [10, 20],\n};\n\nconst copy = { ...original };\ncopy.name = &quot;Grace&quot;;\ncopy.scores.push(30);\n\nconsole.log(original.scores); // [10, 20, 30]\n</code></pre>\n<p>Changing <code>copy.name</code> did not affect <code>original</code>. Pushing to <code>copy.scores</code> did, because both objects share the same array reference.</p>\n<p>When you need a full clone, <code>structuredClone()</code> is built in:</p>\n<pre><code class=\"language-typescript\">const deep = structuredClone(original);\ndeep.scores.push(30);\n\nconsole.log(original.scores); // [10, 20]\n</code></pre>\n<p><code>structuredClone()</code> handles nested objects, arrays, dates, and many other types. It does not clone functions or DOM nodes.</p>\n<p>The older <code>JSON.parse(JSON.stringify(obj))</code> trick still appears in legacy code, but it drops <code>undefined</code>, functions, and <code>Date</code> objects. Prefer <code>structuredClone()</code> when you need a true deep copy in modern browsers and Node.</p>\n"
  },
  {
    "title": "Grouping Array Items by a Property",
    "body": "<p>Given a flat list of records, it is common to group them by a field—for example, tasks by status or orders by customer.</p>\n<p><code>Object.groupBy()</code> makes this straightforward:</p>\n<pre><code class=\"language-typescript\">const tasks = [\n  { title: &quot;Write tests&quot;, status: &quot;todo&quot; },\n  { title: &quot;Ship feature&quot;, status: &quot;done&quot; },\n  { title: &quot;Fix bug&quot;, status: &quot;todo&quot; },\n];\n\nconst byStatus = Object.groupBy(tasks, task =&gt; task.status);\n</code></pre>\n<p>The result is an object whose keys are the group names and whose values are arrays of matching items:</p>\n<pre><code class=\"language-typescript\">// {\n//   todo: [{ title: &quot;Write tests&quot;, ... }, { title: &quot;Fix bug&quot;, ... }],\n//   done: [{ title: &quot;Ship feature&quot;, ... }]\n// }\n</code></pre>\n<p>Before <code>Object.groupBy()</code>, the same result was usually built with <code>reduce</code>:</p>\n<pre><code class=\"language-typescript\">const byStatus = tasks.reduce&lt;Record&lt;string, typeof tasks&gt;&gt;((groups, task) =&gt; {\n  const key = task.status;\n  groups[key] = groups[key] ?? [];\n  groups[key].push(task);\n  return groups;\n}, {});\n</code></pre>\n<p>Both approaches avoid manual loops and nested <code>filter</code> calls for each group.</p>\n"
  },
  {
    "title": "Promise.all vs Promise.allSettled",
    "body": "<p><code>Promise.all()</code> runs several async tasks in parallel and resolves when every one succeeds:</p>\n<pre><code class=\"language-typescript\">const [user, posts] = await Promise.all([\n  fetchUser(id),\n  fetchPosts(id),\n]);\n</code></pre>\n<p>If any promise rejects, <code>Promise.all()</code> rejects immediately and you do not get partial results.</p>\n<p>When you want every outcome—success or failure—use <code>Promise.allSettled()</code>:</p>\n<pre><code class=\"language-typescript\">const results = await Promise.allSettled([\n  fetchUser(id),\n  fetchPosts(id),\n  fetchComments(id),\n]);\n\nresults.forEach(result =&gt; {\n  if (result.status === &quot;fulfilled&quot;) {\n    console.log(result.value);\n  } else {\n    console.error(result.reason);\n  }\n});\n</code></pre>\n<p>This pattern is useful for dashboards or batch jobs where one failure should not cancel the rest.</p>\n<p><code>Promise.allSettled()</code> always resolves. It never rejects because an individual task failed. Check each <code>status</code> before using <code>value</code> or <code>reason</code>.</p>\n"
  },
  {
    "title": "Flattening Nested Arrays with flat()",
    "body": "<p>Nested arrays show up when mapping over lists that return arrays:</p>\n<pre><code class=\"language-typescript\">const teams = [\n  [&quot;Ada&quot;, &quot;Grace&quot;],\n  [&quot;Lin&quot;, &quot;Edsger&quot;],\n];\n\nteams.map(team =&gt; team);\n// [[&quot;Ada&quot;, &quot;Grace&quot;], [&quot;Lin&quot;, &quot;Edsger&quot;]]\n</code></pre>\n<p><code>flat()</code> collapses one level by default:</p>\n<pre><code class=\"language-typescript\">teams.flat();\n// [&quot;Ada&quot;, &quot;Grace&quot;, &quot;Lin&quot;, &quot;Edsger&quot;]\n</code></pre>\n<p>For deeper nesting, pass a depth:</p>\n<pre><code class=\"language-typescript\">const nested = [1, [2, [3, [4]]]];\n\nnested.flat(1); // [1, 2, [3, [4]]]\nnested.flat(2); // [1, 2, 3, [4]]\nnested.flat(Infinity); // [1, 2, 3, 4]\n</code></pre>\n<p>A common follow-up is <code>flatMap()</code>, which maps and flattens in one step:</p>\n<pre><code class=\"language-typescript\">const sentences = [&quot;hello world&quot;, &quot;foo bar&quot;];\n\nsentences.flatMap(sentence =&gt; sentence.split(&quot; &quot;));\n// [&quot;hello&quot;, &quot;world&quot;, &quot;foo&quot;, &quot;bar&quot;]\n</code></pre>\n<p>That is often cleaner than <code>map(...).flat()</code> when each item produces an array.</p>\n"
  },
  {
    "title": "Checking Object Properties Safely",
    "body": "<p>The <code>in</code> operator checks whether a key exists anywhere on an object, including inherited properties:</p>\n<pre><code class=\"language-typescript\">const user = { name: &quot;Ada&quot; };\n\n&quot;name&quot; in user;        // true\n&quot;toString&quot; in user;    // true (inherited from Object.prototype)\n</code></pre>\n<p><code>Object.hasOwn()</code> checks only own properties:</p>\n<pre><code class=\"language-typescript\">Object.hasOwn(user, &quot;name&quot;);      // true\nObject.hasOwn(user, &quot;toString&quot;);  // false\n</code></pre>\n<p>Use <code>hasOwn()</code> when you are iterating or copying keys and want to ignore prototype properties.</p>\n<p>For optional values, <code>undefined</code> checks are still common:</p>\n<pre><code class=\"language-typescript\">if (user.nickname !== undefined) {\n  // nickname was set (even if empty string)\n}\n</code></pre>\n<p>Combining these ideas avoids bugs when parsing JSON or merging config objects where missing keys and inherited keys mean different things.</p>\n"
  },
  {
    "title": "Communicating with postMessage",
    "body": "<p><code>window.postMessage()</code> lets scripts send data across windows, tabs, and iframes—even when they are on different origins. The receiving page listens with a <code>message</code> event.</p>\n<p>Parent sending to an iframe:</p>\n<pre><code class=\"language-typescript\">const iframe = document.querySelector(&quot;iframe&quot;);\niframe?.contentWindow?.postMessage(\n  { type: &quot;resize&quot;, height: 400 },\n  &quot;https://example.com&quot;,\n);\n</code></pre>\n<p>Child receiving:</p>\n<pre><code class=\"language-typescript\">window.addEventListener(&quot;message&quot;, (event) =&gt; {\n  if (event.origin !== &quot;https://example.com&quot;) {\n    return;\n  }\n\n  if (event.data?.type === &quot;resize&quot;) {\n    document.body.style.height = `${event.data.height}px`;\n  }\n});\n</code></pre>\n<p>Always validate <code>event.origin</code> before trusting the payload. The target origin argument on <code>postMessage</code> is not a security boundary on its own—it tells the browser which origin should receive the message.</p>\n<p>For same-origin communication between workers or windows you control, <code>postMessage</code> is still useful because it keeps the API consistent and decouples senders from receivers.</p>\n"
  },
  {
    "title": "CSS inherit",
    "body": "<p>The <code>inherit</code> keyword tells a property to use the same computed value as its parent element. It is useful when a child should explicitly pick up a value from above, especially inside components where local styles might otherwise reset things.</p>\n<pre><code class=\"language-css\">.card {\n  color: #333;\n}\n\n.card__label {\n  color: inherit;\n}\n</code></pre>\n<p>Some properties inherit by default (<code>color</code>, <code>font-family</code>, <code>line-height</code>). Others do not (<code>margin</code>, <code>border</code>, <code>background</code>). For those, <code>inherit</code> is the way to say &quot;use the parent's value&quot; without repeating it.</p>\n<pre><code class=\"language-css\">.sidebar {\n  border-color: #ccc;\n}\n\n.sidebar a {\n  border-color: inherit;\n}\n</code></pre>\n<p><code>inherit</code> is not the same as <code>initial</code> (browser default) or <code>unset</code> (inherit if the property normally inherits, otherwise initial). When you want the parent’s computed value specifically, reach for <code>inherit</code>.</p>\n"
  },
  {
    "title": "Inserting CSS Rules Dynamically",
    "body": "<p>Sometimes you need to add a stylesheet rule at runtime—for example, highlighting a search term or applying a theme token that was not known when the page loaded.</p>\n<p><code>CSSStyleSheet.insertRule()</code> adds a rule at a given index:</p>\n<pre><code class=\"language-typescript\">const sheet = document.styleSheets[0];\nsheet.insertRule(&quot;.highlight { background: yellow; }&quot;, sheet.cssRules.length);\n</code></pre>\n<p>The second argument is the index. Passing <code>cssRules.length</code> appends to the end. Rules are strings in full CSS syntax, including the selector.</p>\n<p>For styles attached via <code>&lt;style&gt;</code> or <code>new CSSStyleSheet()</code>, the same API applies. With constructable stylesheets adopted into the document, you can build rules before attaching:</p>\n<pre><code class=\"language-typescript\">const sheet = new CSSStyleSheet();\nsheet.replaceSync(&quot;body { margin: 0; }&quot;);\nsheet.insertRule(&quot;:root { --accent: #3366cc; }&quot;, sheet.cssRules.length);\ndocument.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet];\n</code></pre>\n<p><code>deleteRule(index)</code> removes a rule by position. Keep track of indices if you plan to remove rules later, since inserting at the end is the simplest approach when order does not matter.</p>\n"
  },
  {
    "title": "let, var, and const",
    "body": "<p>Modern JavaScript has three ways to declare variables. They differ in scope, hoisting, and whether rebinding is allowed.</p>\n<p><code>const</code> declares a binding that cannot be reassigned. The value can still change if it is an object or array:</p>\n<pre><code class=\"language-typescript\">const user = { name: &quot;Ada&quot; };\nuser.name = &quot;Grace&quot;; // allowed\n\nconst count = 1;\ncount = 2; // SyntaxError\n</code></pre>\n<p><code>let</code> declares a block-scoped binding that can be reassigned:</p>\n<pre><code class=\"language-typescript\">let total = 0;\nfor (let i = 0; i &lt; 3; i++) {\n  total += i;\n}\n</code></pre>\n<p><code>var</code> is function-scoped and hoisted with an initial value of <code>undefined</code>:</p>\n<pre><code class=\"language-typescript\">function example() {\n  console.log(x); // undefined (not a ReferenceError)\n  var x = 1;\n}\n</code></pre>\n<p>Prefer <code>const</code> by default and <code>let</code> when you need to reassign. Avoid <code>var</code> in new code—it does not respect block scope, which makes loops and conditionals harder to reason about.</p>\n<pre><code class=\"language-typescript\">for (var i = 0; i &lt; 3; i++) {\n  setTimeout(() =&gt; console.log(i), 0);\n}\n// logs 3, 3, 3\n\nfor (let i = 0; i &lt; 3; i++) {\n  setTimeout(() =&gt; console.log(i), 0);\n}\n// logs 0, 1, 2\n</code></pre>\n<p>Each <code>let</code> iteration gets its own binding. Each <code>var</code> iteration shares one.</p>\n"
  },
  {
    "title": "Map Versus Object",
    "body": "<p>Plain objects work well for fixed keys and JSON-shaped data. <code>Map</code> is often a better fit when keys are unknown at compile time, keys are not strings, or you need reliable size and iteration order.</p>\n<p>Objects coerce keys to strings:</p>\n<pre><code class=\"language-typescript\">const obj: Record&lt;string, number&gt; = {};\nobj[{} as unknown as string] = 1; // awkward; keys become &quot;[object Object]&quot;\n</code></pre>\n<p><code>Map</code> accepts any value as a key:</p>\n<pre><code class=\"language-typescript\">const map = new Map&lt;object, number&gt;();\nconst key = { id: 1 };\nmap.set(key, 42);\nmap.get(key); // 42\n</code></pre>\n<p><code>Map</code> exposes size directly and iterates in insertion order:</p>\n<pre><code class=\"language-typescript\">const map = new Map([\n  [&quot;a&quot;, 1],\n  [&quot;b&quot;, 2],\n]);\n\nmap.size; // 2\n\nfor (const [key, value] of map) {\n  console.log(key, value);\n}\n</code></pre>\n<p>Use a plain object when the shape is stable, you need JSON serialization, or you are modeling a record with named fields. Use <code>Map</code> for caches, indexes keyed by entities, or any collection where keys are dynamic or non-string.</p>\n"
  },
  {
    "title": "RegExp lastIndex",
    "body": "<p>Global and sticky regular expressions track where the last match ended using the <code>lastIndex</code> property. The next call to <code>exec()</code> or <code>test()</code> starts searching from that position.</p>\n<pre><code class=\"language-typescript\">const pattern = /a/g;\nconst text = &quot;aba&quot;;\n\npattern.test(text); // true, lastIndex is 1\npattern.test(text); // true, lastIndex is 3\npattern.test(text); // false, lastIndex resets to 0\n</code></pre>\n<p>Without the <code>g</code> or <code>y</code> flag, <code>lastIndex</code> is ignored and always stays at <code>0</code>.</p>\n<p>This matters when reusing the same <code>RegExp</code> instance in a loop:</p>\n<pre><code class=\"language-typescript\">const pattern = /\\d+/g;\nconst text = &quot;a1b22c333&quot;;\n\nlet match: RegExpExecArray | null;\nwhile ((match = pattern.exec(text)) !== null) {\n  console.log(match[0]);\n}\n// &quot;1&quot;, &quot;22&quot;, &quot;333&quot;\n</code></pre>\n<p>If you only need to know whether a string matches, create a fresh regex or reset <code>lastIndex</code> before each use:</p>\n<pre><code class=\"language-typescript\">pattern.lastIndex = 0;\npattern.test(text);\n</code></pre>\n<p>For one-off checks, <code>text.match(/pattern/g)</code> or <code>pattern.test(text)</code> on a new instance avoids <code>lastIndex</code> surprises entirely.</p>\n"
  },
  {
    "title": "The Temporal Dead Zone",
    "body": "<p><code>let</code> and <code>const</code> are hoisted like <code>var</code>, but they are not initialized until their declaration line runs. The span from the start of the block until that line is the temporal dead zone (TDZ).</p>\n<p>Accessing the binding in the TDZ throws a <code>ReferenceError</code>:</p>\n<pre><code class=\"language-typescript\">console.log(count); // ReferenceError\nconst count = 1;\n</code></pre>\n<p><code>typeof</code> behaves differently for undeclared variables versus TDZ variables:</p>\n<pre><code class=\"language-typescript\">typeof notDeclared; // &quot;undefined&quot;\n\ntypeof inTdz; // ReferenceError\nlet inTdz = 1;\n</code></pre>\n<p>The TDZ also applies to function parameters and default values, which are evaluated left to right:</p>\n<pre><code class=\"language-typescript\">function example(a = b, b = 1) {\n  return a + b;\n}\n\nexample(); // ReferenceError: Cannot access 'b' before initialization\n</code></pre>\n<p>This is why <code>let</code> loop variables work as expected—each iteration gets a fresh binding in its own scope—and why referencing a <code>const</code> before its declaration fails even though the name appears later in the same block.</p>\n"
  },
  {
    "title": "WeakMaps",
    "body": "<p>A <code>WeakMap</code> is like a <code>Map</code>, but its keys must be objects and they are held weakly. If nothing else references a key object, it can be garbage-collected and the entry disappears from the map.</p>\n<pre><code class=\"language-typescript\">let user = { id: 1 };\nconst metadata = new WeakMap&lt;object, { visits: number }&gt;();\n\nmetadata.set(user, { visits: 1 });\nmetadata.get(user); // { visits: 1 }\n\nuser = null;\n// The { id: 1 } object and its WeakMap entry can now be collected.\n</code></pre>\n<p>You cannot iterate a <code>WeakMap</code> and there is no <code>size</code> property. That is by design—the engine does not keep a strong list of weak keys.</p>\n<p>A common pattern is attaching private data to DOM nodes or class instances without polluting the object itself:</p>\n<pre><code class=\"language-typescript\">const privateData = new WeakMap&lt;HTMLElement, { listener: () =&gt; void }&gt;();\n\nfunction register(element: HTMLElement, listener: () =&gt; void) {\n  privateData.set(element, { listener });\n  element.addEventListener(&quot;click&quot;, listener);\n}\n\nfunction unregister(element: HTMLElement) {\n  const data = privateData.get(element);\n  if (data) {\n    element.removeEventListener(&quot;click&quot;, data.listener);\n    privateData.delete(element);\n  }\n}\n</code></pre>\n<p>When the element is removed from the document and no longer referenced, its metadata goes away with it. Use a regular <code>Map</code> when you need enumeration, primitive keys, or a known entry count.</p>\n"
  }
]