<?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: Matt Priour</title>
    <description>The latest articles on DEV Community by Matt Priour (@mpriour).</description>
    <link>https://dev.to/mpriour</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%2F160800%2Fcd61a532-8e2f-437e-a65e-e6f2a90b529e.jpeg</url>
      <title>DEV Community: Matt Priour</title>
      <link>https://dev.to/mpriour</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mpriour"/>
    <language>en</language>
    <item>
      <title>An Introduction to High Contrast Accessibility</title>
      <dc:creator>Matt Priour</dc:creator>
      <pubDate>Wed, 19 Jan 2022 21:00:30 +0000</pubDate>
      <link>https://dev.to/mpriour/an-introduction-to-high-contrast-accessibility-4im4</link>
      <guid>https://dev.to/mpriour/an-introduction-to-high-contrast-accessibility-4im4</guid>
      <description>&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;High contrast mode is a special rendering mode on Windows that applies forced colors and simplifies visual elements throughout the entire platform. This mode is an accessibility feature of Windows and used by people with low vision or visual acuity issues. High contrast mode severely changes the way that websites are rendered on all Windows browsers.&lt;/p&gt;

&lt;p&gt;The following CSS properties are overwritten by the theme's system colors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;color&lt;/li&gt;
&lt;li&gt;background-color&lt;/li&gt;
&lt;li&gt;text-decoration-color&lt;/li&gt;
&lt;li&gt;text-emphasis-color&lt;/li&gt;
&lt;li&gt;border-color&lt;/li&gt;
&lt;li&gt;outline-color&lt;/li&gt;
&lt;li&gt;column-rule-color&lt;/li&gt;
&lt;li&gt;-webkit-tap-highlight-color&lt;/li&gt;
&lt;li&gt;SVG fill attribute&lt;/li&gt;
&lt;li&gt;SVG stroke attribute&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Additionally, the following CSS properties are set to &lt;code&gt;none&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;box-shadow&lt;/li&gt;
&lt;li&gt;text-shadow&lt;/li&gt;
&lt;li&gt;background-image (unless it is a URL)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;References&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://support.microsoft.com/en-us/windows/change-color-contrast-in-windows-fedc744c-90ac-69df-aed5-c8a90125e696" rel="noopener noreferrer"&gt;Enabling high contrast and customizing it (Windows 10 &amp;amp; 11)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blogs.windows.com/msedgedev/2020/09/17/styling-for-windows-high-contrast-with-new-standards-for-forced-colors/" rel="noopener noreferrer"&gt;Styling Edge for Windows high contrast mode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@media/forced-colors" rel="noopener noreferrer"&gt;&lt;code&gt;forced-colors&lt;/code&gt; media query (Modern browser support)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@media/forced-colors" rel="noopener noreferrer"&gt;&lt;code&gt;-ms-high-contrast&lt;/code&gt; media query (IE11 and Legacy Edge support)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.w3.org/TR/css-color-adjust-1/#forced-colors-properties" rel="noopener noreferrer"&gt;forced-colors W3C standards&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Rendering native elements and system colors
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Default&lt;/th&gt;
&lt;th&gt;HC Chrome/Edge&lt;/th&gt;
&lt;th&gt;HC Firefox&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;img alt="baseline-default" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F142636%2F149374315-57db1d2a-0714-49d5-8345-8c2cf1919edc.png"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img alt="baseline-hc-chr" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F142636%2F149374339-1c4b1ee3-d6fe-4b78-9bf6-9d5373813d4b.png"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img alt="baseline-hc-ff" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F142636%2F149374379-85f2fd80-7eaa-4957-a3a1-85df2f59f69f.png"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Rendering specifics
&lt;/h2&gt;

&lt;h3&gt;
  
  
  System colors
&lt;/h3&gt;

&lt;p&gt;Chromium-based browsers (Edge and Chrome) and Firefox both respect the forced color and style adjustments of Windows in high contrast mode. Both browsers types use the system colors rather than user specified colors for most elements. The system colors names and specification is often seen as deprecated, but that is the recommended way to specify a color and have it work in high contrast mode. The table below shows the system color name and its purpose. The system color names are case insensitive. &lt;code&gt;Canvas&lt;/code&gt; and &lt;code&gt;CanvasText&lt;/code&gt; are meant to replace &lt;code&gt;Window&lt;/code&gt; and &lt;code&gt;WindowText&lt;/code&gt;. However, all of them are currently supported in both browser types on Windows. System colors are not set in CSS but rather set in the Windows theme controls and then can be used as colors in CSS.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;System Color&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ActiveText&lt;/td&gt;
&lt;td&gt;Text of active links&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ButtonBorder&lt;/td&gt;
&lt;td&gt;Base border color of controls&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ButtonFace&lt;/td&gt;
&lt;td&gt;Background color of controls&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ButtonText&lt;/td&gt;
&lt;td&gt;Foreground color of controls&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Canvas&lt;/td&gt;
&lt;td&gt;Background of application content or documents&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CanvasText&lt;/td&gt;
&lt;td&gt;Foreground color in application content or documents&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Field&lt;/td&gt;
&lt;td&gt;Background of input fields&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FieldText&lt;/td&gt;
&lt;td&gt;Text in input fields&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GrayText&lt;/td&gt;
&lt;td&gt;Foreground color for disabled items (e.g. a disabled control)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Highlight&lt;/td&gt;
&lt;td&gt;Background of selected items&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HighlightText&lt;/td&gt;
&lt;td&gt;Foreground color of selected items&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LinkText&lt;/td&gt;
&lt;td&gt;Text of non-active, non-visited links&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VisitedText&lt;/td&gt;
&lt;td&gt;Text of visited links&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Window&lt;/td&gt;
&lt;td&gt;Window background&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WindowText&lt;/td&gt;
&lt;td&gt;Text in windows&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Media queries
&lt;/h3&gt;

&lt;p&gt;A simple media query can determine if the page is being rendered in high contrast mode or not. The recommended way to determine this is to use the &lt;code&gt;forced-colors&lt;/code&gt; media query. The deprecated &lt;code&gt;-ms-high-contrast&lt;/code&gt; query still works on Edge, but is expected to be removed "soon". If you are still supporting Internet Explorer or Legacy Edge then you would want to use this deprecated media query. For example, this snippet would set the &lt;code&gt;color&lt;/code&gt; and &lt;code&gt;background-color&lt;/code&gt; of an element with a &lt;code&gt;selected&lt;/code&gt; class to be the inverse of a "normal" element on the page only when the system is in high contrast mode.&lt;/p&gt;

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

&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;forced-colors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;active&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nc"&gt;.selected&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;CanvasText&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Canvas&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;There is an escape hatch that should be used &lt;strong&gt;very&lt;/strong&gt; sparingly. Setting a CSS selector to &lt;code&gt;forced-color-adjust: none&lt;/code&gt; opts out of the high contrast color mode. While it may seem tempting to do this where ever high contrast mode is causing UI problems, it is not a recommended practice. Users have turned on high contrast mode for a reason. You should work with it if at all possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  UPDATE - &lt;code&gt;forced-colors&lt;/code&gt; emulation now available
&lt;/h2&gt;

&lt;p&gt;As of Chromium 98 (both Chrome 98 and Edge 98) you can set &lt;code&gt;forced-colors: active&lt;/code&gt; in the "Rendering" pane of DevTools.&lt;br&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%2Fuploads%2Farticles%2Fg09tsd9zl3hmymrm7lq7.png" class="article-body-image-wrapper"&gt;&lt;img alt="Setting forced-colors to active in Rendering pane of DevTools" 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%2Farticles%2Fg09tsd9zl3hmymrm7lq7.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Browser differences
&lt;/h3&gt;

&lt;p&gt;While both browser types render high contrast, there are some obvious differences between the browsers. The most obvious difference is in rendering SVGs with a &lt;code&gt;fill&lt;/code&gt; of &lt;code&gt;currentColor&lt;/code&gt;. Chrome and Edge on Windows have a specific user-agent style for SVG that sets &lt;code&gt;forced-color-adjust: none&lt;/code&gt;. This allows one to easily set the color on an SVG in those browsers. However, there is no guaranty that the SVG will have appropriate contrast or even be visible. On Firefox, SVG's currentColor is forced to the WindowText/CanvasText color. This ensures that the icon is visible, but eliminates any color information that the SVG is expected to convey.&lt;/p&gt;

&lt;p&gt;Another, less obvious difference is that Chrome and Edge also set the value of the &lt;code&gt;prefers-color-scheme&lt;/code&gt; in high contrast mode depending on the Window/Canvas color used by the high contrast theme. High contrast themes with backgrounds below a certain luminosity get &lt;code&gt;prefers-color-scheme: dark&lt;/code&gt; while background values above that threshold get &lt;code&gt;prefers-color-scheme: light&lt;/code&gt; set, regardless of other system preferences. This is not the case in Firefox, which follows the system preference and defaults to &lt;code&gt;prefers-color-scheme: light&lt;/code&gt; regardless of the actual theme colors. Because of the way that Firefox overwrites SVG &lt;code&gt;currentColor&lt;/code&gt; along with the other rendering changes, the value of &lt;code&gt;prefers-color-scheme&lt;/code&gt; has little impact on what the user sees. In Chrome and Edge, the primary difference is also in SVG's. Since they maintain the CSS specified color for &lt;code&gt;currentColor&lt;/code&gt;, if there are different color values depending on the &lt;code&gt;prefers-color-scheme&lt;/code&gt; value then those colors are seen by the user.&lt;/p&gt;

&lt;h2&gt;
  
  
  Challenges
&lt;/h2&gt;

&lt;p&gt;The most notable challenges with high contrast mode are that box-shadow and background-color compute to &lt;code&gt;none&lt;/code&gt;. This means that any component attempting to show state or other information using either of these properties will not show properly if at all. The difference in the way that SVG's are rendered causes issues with several components and creates significant differences between Firefox and Chrome or Edge browsers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Opportunities
&lt;/h2&gt;

&lt;p&gt;Few developers or quality assurance engineers test for high contrast issues. There are not currently any good automated tests or tools for setting &lt;code&gt;forced-colors&lt;/code&gt; to &lt;code&gt;active&lt;/code&gt; and looking for visual regressions. This really has to be done by someone manually, at this time. Spending even a small amount of time reviewing your UI for high contrast issues and fixing the highest impact items will go a long way to distinguish your product from others for high contrast users.&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>frontend</category>
      <category>highcontrast</category>
      <category>windows</category>
    </item>
    <item>
      <title>Generating strongly typed reducer actions for React</title>
      <dc:creator>Matt Priour</dc:creator>
      <pubDate>Thu, 30 Sep 2021 17:13:25 +0000</pubDate>
      <link>https://dev.to/mpriour/generating-strongly-typed-reducer-actions-for-react-j77</link>
      <guid>https://dev.to/mpriour/generating-strongly-typed-reducer-actions-for-react-j77</guid>
      <description>&lt;p&gt;Using reducers in the React Context api leaves a lot of room for error, even when using TypeScript. A reducer takes a single argument and returns a state. The common format for the argument is an object with an &lt;code&gt;action&lt;/code&gt; property and a &lt;code&gt;payload&lt;/code&gt; or &lt;code&gt;value&lt;/code&gt; property. The &lt;code&gt;action&lt;/code&gt;'s value is generally a string such as &lt;code&gt;setTitle&lt;/code&gt;. In the case of &lt;code&gt;action:'setTitle'&lt;/code&gt;, the &lt;code&gt;value&lt;/code&gt; would then be the title you want to set on the state object. The problems with this approach are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You have to look back at the reducer to see what the correct spelling and valid values of action are.&lt;/li&gt;
&lt;li&gt;There is no type checking of the values that are linked with the action.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;This article assumes that you have a basic familiarity with React, &lt;code&gt;useReducer&lt;/code&gt;, and TypeScript.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you just want to skip to the code, you can see the final working version on &lt;a href="https://www.typescriptlang.org/play?target=6&amp;amp;q=373#code/JYWwDg9gTgLgBAJQKYEMDGMA0cDecDCEAdjEgB5ZxpSqmEnmUCuAzksgCZNpJRwC+cAGZQIIOACIa6GBIDcAWABQy8pFhwYATzBI4ASVIgAyjBSk4AXlzK4duMA4AuOCxhRgRAOaZb9mMAwADZILm4e3r5K9nAcSCzUwGABxAD8Ye6ePn52AI5MKCSBWi5ETCAARrzK-MrK2rpwxkgwpFAsADwAKgB8VjbR9gDaAAoORHAA1khaEEJwXXAoLHAABmwwACQ4+ChggShBwABeSB3hWXAAZHAjPfyrALoAtOkLo481dUoNeoZIJhabRW1marV4nX+JjMpB631+cAAghhgMQWABZPb9HA5OBDYzjKYzOYGIxg4GPFw4wYxOwyVFEFzGKK0+wAN0OTFCpIB5Ih+M+NIEXxUSjU0HgCKhyJSRBBSJRaMxYCG01m8xlDIxe0FyjQaPggQBnG4vH6AAo3OZuVDTNbsPTiC5pYq5QBKODOskwvSWPrUmIsADugTQAAtzY6iAA6KMegOsqjLPQAcg2+g4KacuMTcBoMCYUAmOGjpatpGwjhcUejHKCXP4iiFMTQybgaZaXUCISzOcT+cLxdL0fLSGwAWC3JrdYbTdzrbY7Y2ABF4olkgze83+y1B7hh6PsHEEh4N06lq7a5ykI2+3YF6mNgBFApFbRb3MxAdF-dln3YfJCgnEoL1lK96xvOdEziIQUCYIIYGzbdWX1OUIBCaNeFEKBzVWTViDgElthrKNBGAFYiAgeAWCYMB1FIDhVjdKD7FqZtvwmUcmzY75PDaWCeAMEZRDZRxeGEiAwBWBNw2AIIOBoIh0kKLQRWUPjeAEv56FICgJKkgY7CNEAvV5f8-A4ciwHMcMXEjV1TJAfD3SsPo2QgRw1KUVC3B5EAdMYfpqFoJAAooc0cEEZYDDCmB9JYD1otijp9Fi+K4VFIQmCIV0-Ik0S4hwnBZPkxT+GdfKxKgeK3Rkg08WMo8rJssNHn6Vh2CQLgeBw4yTR67BIqWFZbR9N0-B8+BUN0mAAHkKgAK2xRrYmamBwzYuwOLgc1cRSoxYujSrCrgGckEsYriBm+aFv4DLWWKsM5IUpAiE2+wOgAeihQ7jt4e64HGpQeLFMh6NwH6rsYbAoT+qB+CAA"&gt;this TS Playground&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The optimal solution would allow us to define the state object and its valid values, then TypeScript would provide code completion and type validation for the actions and values passed to the reducer function. A less optimal solution would be to do something similar to Redux and create a series of action functions that are strongly typed and wrap calls to the reducer. Then in your code you only use action functions and never call the reducer directly. However, TypeScript's mapped types can make that extra layer unnecessary.&lt;/p&gt;

&lt;p&gt;Let's take a simple state type&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;type&lt;/span&gt; &lt;span class="nx"&gt;ItemState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;id&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="na"&gt;title&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="nx"&gt;description&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="na"&gt;quantity&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We want to create a reducer that knows that &lt;code&gt;setId&lt;/code&gt; and &lt;code&gt;setQuantity&lt;/code&gt; are valid actions but &lt;code&gt;setID&lt;/code&gt; and &lt;code&gt;setQty&lt;/code&gt; are not. It should also type check so that the value paired with &lt;code&gt;setQuantity&lt;/code&gt; is a number and not a Date or string.&lt;/p&gt;

&lt;p&gt;The first step is to create a generic utility type called &lt;code&gt;Setters&lt;/code&gt; that takes another type and produces "setPropertyName" style function names for each property on that type.&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;type&lt;/span&gt; &lt;span class="nx"&gt;Setters&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;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="nx"&gt;P&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="s2"&gt;`set&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;Capitalize&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;P&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&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="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;P&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;Capitalize&lt;/code&gt; is a built in string modifier that capitalizes the passed string. The &lt;code&gt;-?&lt;/code&gt; means that we remove the optional attribute of any property. &lt;code&gt;T[P]&lt;/code&gt; gives us the type of each property of the passed in generic type.&lt;/p&gt;

&lt;p&gt;We then use the Setters utility to generate a setters type for our state type.&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;type&lt;/span&gt; &lt;span class="nx"&gt;ItemSetters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Setters&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ItemState&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="cm"&gt;/* 
This is equivalent to writing out:
type ItemSetters = {
    setId: string,
    setTitle: string,
    setDescription: string,
    setQuantity: number
}
*/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's use another mapped type to create a map of action objects with valid action names and value types.&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;type&lt;/span&gt; &lt;span class="nx"&gt;ActionsMap&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="nx"&gt;S&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;ItemSetters&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;S&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ItemSetters&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;S&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="cm"&gt;/* 
This results in:
type ActionsMap = {
    setId: {
        action: 'setId',
        value: string
    }, ...
    setQuantity: {
        action: 'setQuantity',
        value: number
    }
}
*/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we need to extract the action/value objects out of ActionsMap and use the union of those objects as our action type in our reducer.&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;type&lt;/span&gt; &lt;span class="nx"&gt;ItemActions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ActionsMap&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;ActionsMap&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;itemReducer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ItemState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ItemActions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ItemState&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;state&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;itemReducer&lt;/code&gt; doesn't actually do anything yet. We need to fill it out with the reducer logic. What you can't see here in the code sample is the ease of doing this. With the strongly typed &lt;code&gt;ItemActions&lt;/code&gt; we will have code completion on the switch case statements we will write and type validation when we use the reducer. &lt;/p&gt;

&lt;p&gt;Here is the filled out reducer function:&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;itemReducer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ItemState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ItemActions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ItemState&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;switch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;setId&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;action&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="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;setTitle&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;state&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="nx"&gt;action&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="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;setDescription&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;action&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="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;setQuantity&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;action&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="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Action of &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; is not supported`&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;state&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;Unfortunately our &lt;code&gt;default&lt;/code&gt; statement has an error:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Property 'action' does not exist on type 'never'.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That error occurs because we covered all possible valid cases. In order to account for a possible error, we can add a dummy action type. ItemActions becomes:&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;type&lt;/span&gt; &lt;span class="nx"&gt;ItemActions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
    &lt;span class="nx"&gt;ActionsMap&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;ActionsMap&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="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;other&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using the mapped types with string template literals approach really shows its power when you need to add another property to the state. For example, let's add a boolean 'backordered' property. We just have to add 3 total lines of code.&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;type&lt;/span&gt; &lt;span class="nx"&gt;ItemState&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="na"&gt;quantity&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="na"&gt;backordered&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="p"&gt;...&lt;/span&gt;

    &lt;span class="k"&gt;switch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;action&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="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;setQuantity&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;action&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="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;setBackordered&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;backordered&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;action&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="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even better than the developer experience when adding or removing properties from state, is the experience of using the reducer. While it can't easily be shown in code snippets, the auto-complete and type validation is a game changer. No longer do you have to look back at the reducer to determine the correct spelling and what exactly type of value it is expecting. For example:&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;/* GOOD */&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;setQuantity&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="cm"&gt;/* ERROR */&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;setQuantity&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;none&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hope this approach helps you when creating and using reducers. Once I figured it out, it has saved me plenty of development time and frustration.&lt;/p&gt;

&lt;p&gt;Here is the final TypeScript annotated reducer:&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;type&lt;/span&gt; &lt;span class="nx"&gt;ItemState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;id&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="na"&gt;title&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="nx"&gt;description&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="na"&gt;quantity&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="na"&gt;backordered&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="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Setters&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;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="nx"&gt;P&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="s2"&gt;`set&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;Capitalize&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;P&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&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="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;P&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;ItemSetters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Setters&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ItemState&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;ActionsMap&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="nx"&gt;S&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;ItemSetters&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;S&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ItemSetters&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;S&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;type&lt;/span&gt; &lt;span class="nx"&gt;ItemActions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
    &lt;span class="nx"&gt;ActionsMap&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;ActionsMap&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="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;other&lt;/span&gt;&lt;span class="dl"&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;itemReducer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ItemState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ItemActions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ItemState&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;switch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;setId&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;action&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="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;setTitle&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;state&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="nx"&gt;action&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="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;setDescription&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;action&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="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;setQuantity&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;action&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="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;setBackordered&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;backordered&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;action&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="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Action of &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; is not supported`&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;state&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;



</description>
      <category>react</category>
      <category>typescript</category>
      <category>usereducer</category>
      <category>mappedtypes</category>
    </item>
  </channel>
</rss>
