Browse Source

3.1: using keyof for typed dynamic property access.

Frederic G. MARAND 5 years ago
parent
commit
bf654913d7

+ 5 - 0
.idea/codeStyles/Project.xml

@@ -0,0 +1,5 @@
+<component name="ProjectCodeStyleConfiguration">
+  <code_scheme name="Project" version="173">
+    <option name="SOFT_MARGINS" value="80" />
+  </code_scheme>
+</component>

+ 1 - 1
.idea/codeStyles/codeStyleConfig.xml

@@ -1,5 +1,5 @@
 <component name="ProjectCodeStyleConfiguration">
   <state>
-    <option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
+    <option name="USE_PER_PROJECT_SETTINGS" value="true" />
   </state>
 </component>

+ 35 - 36
.idea/workspace.xml

@@ -2,8 +2,10 @@
 <project version="4">
   <component name="ChangeListManager">
     <list default="true" id="c6f02f4e-af06-43d1-8bc0-507af01d0573" name="Default Changelist" comment="">
-      <change beforePath="$PROJECT_DIR$/course/package-lock.json" beforeDir="false" afterPath="$PROJECT_DIR$/course/package-lock.json" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/course/package.json" beforeDir="false" afterPath="$PROJECT_DIR$/course/package.json" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/.idea/codeStyles/Project.xml" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/.idea/codeStyles/codeStyleConfig.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/codeStyles/codeStyleConfig.xml" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/course/src/app/services/reportItem.service.ts" beforeDir="false" afterPath="$PROJECT_DIR$/course/src/app/services/reportItem.service.ts" afterDir="false" />
     </list>
     <option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
     <option name="SHOW_DIALOG" value="false" />
@@ -28,7 +30,7 @@
           <entry key="gitignore" value="2" />
           <entry key="groovy" value="1" />
           <entry key="json" value="16" />
-          <entry key="ts" value="28" />
+          <entry key="ts" value="29" />
           <entry key="txt" value="1" />
         </counts>
       </usages-collector>
@@ -38,20 +40,20 @@
           <entry key="JSON" value="3" />
           <entry key="PLAIN_TEXT" value="2" />
           <entry key="Scratch" value="3" />
-          <entry key="TypeScript" value="28" />
+          <entry key="TypeScript" value="29" />
           <entry key="tsconfig" value="13" />
         </counts>
       </usages-collector>
       <usages-collector id="statistics.file.extensions.edit">
         <counts>
           <entry key="json" value="62" />
-          <entry key="ts" value="898" />
+          <entry key="ts" value="1633" />
         </counts>
       </usages-collector>
       <usages-collector id="statistics.file.types.edit">
         <counts>
           <entry key="JSON" value="5" />
-          <entry key="TypeScript" value="898" />
+          <entry key="TypeScript" value="1633" />
           <entry key="tsconfig" value="57" />
         </counts>
       </usages-collector>
@@ -70,10 +72,10 @@
   <component name="FileEditorManager">
     <leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
       <file pinned="false" current-in-tab="true">
-        <entry file="file://$PROJECT_DIR$/course/tsconfig.json">
+        <entry file="file://$PROJECT_DIR$/course/src/app/services/reportItem.service.ts">
           <provider selected="true" editor-type-id="text-editor">
-            <state relative-caret-position="360">
-              <caret line="24" column="3" selection-start-line="24" selection-start-column="3" selection-end-line="24" selection-end-column="3" />
+            <state relative-caret-position="15">
+              <caret line="1" column="3" selection-start-line="1" selection-start-column="3" selection-end-line="1" selection-end-column="3" />
             </state>
           </provider>
         </entry>
@@ -98,12 +100,12 @@
         <option value="$PROJECT_DIR$/course/src/app/app-routing.module.ts" />
         <option value="$PROJECT_DIR$/course/src/app/services/messenger.service.ts" />
         <option value="$PROJECT_DIR$/course/src/app/app.module.ts" />
-        <option value="$PROJECT_DIR$/course/src/app/services/reportItem.service.ts" />
         <option value="$PROJECT_DIR$/course/src/app/base-report.component.ts" />
         <option value="$PROJECT_DIR$/course/src/app/services/reportData.service.ts" />
         <option value="$PROJECT_DIR$/course/src/app/edit-report.component.ts" />
         <option value="$PROJECT_DIR$/course/src/app/reports.component.ts" />
         <option value="$PROJECT_DIR$/course/tsconfig.json" />
+        <option value="$PROJECT_DIR$/course/src/app/services/reportItem.service.ts" />
       </list>
     </option>
   </component>
@@ -162,31 +164,28 @@
             <path>
               <item name="Pluralsight-GetTheMostFromTypescript" type="b2602c69:ProjectViewProjectNode" />
               <item name="Pluralsight-GetTheMostFromTypescript" type="462c0819:PsiDirectoryNode" />
-              <item name="02" type="462c0819:PsiDirectoryNode" />
-            </path>
-            <path>
-              <item name="Pluralsight-GetTheMostFromTypescript" type="b2602c69:ProjectViewProjectNode" />
-              <item name="Pluralsight-GetTheMostFromTypescript" type="462c0819:PsiDirectoryNode" />
-              <item name="02" type="462c0819:PsiDirectoryNode" />
-              <item name="demos" type="462c0819:PsiDirectoryNode" />
+              <item name="course" type="462c0819:PsiDirectoryNode" />
             </path>
             <path>
               <item name="Pluralsight-GetTheMostFromTypescript" type="b2602c69:ProjectViewProjectNode" />
               <item name="Pluralsight-GetTheMostFromTypescript" type="462c0819:PsiDirectoryNode" />
-              <item name="02" type="462c0819:PsiDirectoryNode" />
-              <item name="demos" type="462c0819:PsiDirectoryNode" />
-              <item name="After" type="462c0819:PsiDirectoryNode" />
+              <item name="course" type="462c0819:PsiDirectoryNode" />
+              <item name="src" type="462c0819:PsiDirectoryNode" />
             </path>
             <path>
               <item name="Pluralsight-GetTheMostFromTypescript" type="b2602c69:ProjectViewProjectNode" />
               <item name="Pluralsight-GetTheMostFromTypescript" type="462c0819:PsiDirectoryNode" />
               <item name="course" type="462c0819:PsiDirectoryNode" />
+              <item name="src" type="462c0819:PsiDirectoryNode" />
+              <item name="app" type="462c0819:PsiDirectoryNode" />
             </path>
             <path>
               <item name="Pluralsight-GetTheMostFromTypescript" type="b2602c69:ProjectViewProjectNode" />
               <item name="Pluralsight-GetTheMostFromTypescript" type="462c0819:PsiDirectoryNode" />
               <item name="course" type="462c0819:PsiDirectoryNode" />
               <item name="src" type="462c0819:PsiDirectoryNode" />
+              <item name="app" type="462c0819:PsiDirectoryNode" />
+              <item name="services" type="462c0819:PsiDirectoryNode" />
             </path>
           </expand>
           <select />
@@ -212,7 +211,7 @@
     <property name="nodejs_interpreter_path.stuck_in_default_project" value="/usr/local/bin/node" />
     <property name="nodejs_npm_path_reset_for_default_project" value="true" />
     <property name="nodejs_package_manager_path" value="yarn" />
-    <property name="settings.editor.selected.configurable" value="settings.typescriptcompiler" />
+    <property name="settings.editor.selected.configurable" value="preferences.sourceCode" />
     <property name="ts.external.directory.path" value="$PROJECT_DIR$/course/node_modules/typescript/lib" />
   </component>
   <component name="RecentsManager">
@@ -257,19 +256,19 @@
       <updated>1535304175302</updated>
       <workItem from="1535304176395" duration="75000" />
       <workItem from="1535304274687" duration="6343000" />
-      <workItem from="1535393199806" duration="1867000" />
+      <workItem from="1535393199806" duration="3815000" />
     </task>
     <servers />
   </component>
   <component name="TimeTrackingManager">
-    <option name="totallyTimeSpent" value="8285000" />
+    <option name="totallyTimeSpent" value="10233000" />
   </component>
   <component name="ToolWindowManager">
     <frame x="0" y="23" width="1440" height="877" extended-state="6" />
     <editor active="true" />
     <layout>
       <window_info id="Favorites" order="0" side_tool="true" />
-      <window_info id="Structure" order="1" side_tool="true" visible="true" weight="0.1795422" />
+      <window_info active="true" id="Structure" order="1" side_tool="true" visible="true" weight="0.1795422" />
       <window_info id="npm" order="2" side_tool="true" />
       <window_info anchor="bottom" id="Event Log" order="0" sideWeight="0.5007153" side_tool="true" weight="0.3299363" />
       <window_info anchor="bottom" id="Version Control" order="1" />
@@ -277,7 +276,7 @@
       <window_info anchor="bottom" id="Metrics" order="3" />
       <window_info anchor="bottom" id="Message" order="4" />
       <window_info anchor="bottom" id="Find" order="5" weight="0.3299363" />
-      <window_info active="true" anchor="bottom" id="Run" order="6" sideWeight="0.49928468" visible="true" weight="0.3299363" />
+      <window_info anchor="bottom" id="Run" order="6" sideWeight="0.49928468" visible="true" weight="0.23694268" />
       <window_info anchor="bottom" id="Debug" order="7" weight="0.4" />
       <window_info anchor="bottom" id="Cvs" order="8" weight="0.25" />
       <window_info anchor="bottom" id="Inspection" order="9" weight="0.4" />
@@ -290,9 +289,9 @@
       <window_info anchor="right" id="Commander" order="2" weight="0.4" />
       <window_info anchor="right" id="Ant Build" order="3" weight="0.25" />
       <window_info anchor="right" content_ui="combo" id="Hierarchy" order="4" weight="0.25" />
-      <window_info anchor="right" content_ui="combo" id="Project" order="5" sideWeight="0.49619773" visible="true" weight="0.27110156" />
+      <window_info anchor="right" content_ui="combo" id="Project" order="5" sideWeight="0.49582636" visible="true" weight="0.27110156" />
       <window_info anchor="right" id="Remote Host" order="6" show_stripe_button="false" />
-      <window_info anchor="right" x="0" y="0" width="310" height="677" id="Documentation" order="7" sideWeight="0.5038023" side_tool="true" weight="0.27110156" />
+      <window_info anchor="right" x="0" y="0" width="310" height="677" id="Documentation" order="7" sideWeight="0.50417364" side_tool="true" weight="0.27110156" />
     </layout>
   </component>
   <component name="TypeScriptGeneratedFilesManager">
@@ -379,13 +378,6 @@
         </state>
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/course/src/app/services/reportItem.service.ts">
-      <provider selected="true" editor-type-id="text-editor">
-        <state relative-caret-position="220">
-          <caret line="36" column="72" selection-start-line="36" selection-start-column="72" selection-end-line="36" selection-end-column="72" />
-        </state>
-      </provider>
-    </entry>
     <entry file="file://$PROJECT_DIR$/course/src/app/base-report.component.ts">
       <provider selected="true" editor-type-id="text-editor">
         <state relative-caret-position="349">
@@ -423,8 +415,15 @@
     </entry>
     <entry file="file://$PROJECT_DIR$/course/tsconfig.json">
       <provider selected="true" editor-type-id="text-editor">
-        <state relative-caret-position="360">
-          <caret line="24" column="3" selection-start-line="24" selection-start-column="3" selection-end-line="24" selection-end-column="3" />
+        <state relative-caret-position="195">
+          <caret line="13" column="29" selection-start-line="13" selection-start-column="29" selection-end-line="13" selection-end-column="29" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/course/src/app/services/reportItem.service.ts">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="15">
+          <caret line="1" column="3" selection-start-line="1" selection-start-column="3" selection-end-line="1" selection-end-column="3" />
         </state>
       </provider>
     </entry>

+ 26 - 0
course/src/app/services/reportItem.service.ts

@@ -1,4 +1,5 @@
 import { Injectable } from '@angular/core';
+// import {bootstrapItem} from "../../../node_modules/@angular/cli/lib/ast-tools";
 
 export enum ReportItemType {
     food = 'Food',
@@ -16,6 +17,27 @@ export type ReportItem = {
     date: Date;
 };
 
+function validateRequired(item: ReportItem): boolean {
+    // false is a valid value for these, so exclude them from check.
+    const exclude: (keyof ReportItem)[] = ['hasReceipt'];
+
+    return Object.keys(item)
+        .reduce((isValid, memberKey: keyof ReportItem) => {
+            if (!isValid) {
+                return isValid;
+            }
+
+            if (memberKey === 'date') {
+                // date is of type Date, because of the keyof typing.
+                const date = item[memberKey];
+                if (date < new Date(1970)) {
+                    return false;
+                }
+            }
+            return exclude.includes(memberKey) || !!item[memberKey];
+        }, true);
+}
+
 function validateFoodItem(item: ReportItem): string {
     if (item.amount >= 50 && !item.hasReceipt) {
         return 'A food item with a value greater than $50 must have a receipt';
@@ -51,6 +73,10 @@ export class ReportItemService {
     }
 
     isValid(item: ReportItem): string {
+        if (!validateRequired(item)) {
+            return 'One of the required fields was not filled.';
+        }
+
         switch (item.type) {
             case ReportItemType.food: {
                 const validatedFood = validateFoodItem(item);