title: improving for...in loop to be faster in Typescript
body: <p>so I've been asked to improve a code that uses &quot;for...in&quot; of typescript to be faster.</p>
  <p>this is the original code:</p>
  <pre><code>    export interface AddressBook {
      emp_id: string | null;
      first: string;
      last: string;
      email: string;
  }
  export interface Payroll {
      emp_id: string;
      vacationDays: number;
  }
  interface Employee {
      id: string;
      name: string;
      startDate: Date;
      endDate: Date | null;
  }
  export interface EmailApi {
      sendEmail(email: string, subject: string, body: string): void;
  }
  function yearsSince(startDate: Date, endDate: Date): number {
      const millisecondsPerYear = 365 * 24 * 60 * 60 * 1000;
      return Math.trunc((endDate.getTime() - startDate.getTime()) / millisecondsPerYear);
  }
  /**
   * We haved decided to grant bonus vacation to every employee, 1 day per year of experience
   * we need to email them a notice.
   */
  
  function grantVacation(
      emailApi: EmailApi,
      payroll: Payroll[],
      addresses: AddressBook[],
      employees: Employee[],
  ) {
      for (var index in payroll) {
          let payrollInfo = payroll[index];
          let addressInfo = addresses.find(x =&gt; x.emp_id == payrollInfo.emp_id);
          let empInfo = employees.find(x =&gt; x.id == payrollInfo.emp_id);
          let today = new Date();
          let yearsEmployed = 0;
          if (empInfo != undefined) {
              yearsEmployed = yearsSince(empInfo.startDate, today);
          }
          let newVacationBalance = yearsEmployed + payrollInfo.vacationDays;
          if (addressInfo != undefined &amp;&amp; empInfo != undefined) {
              emailApi.sendEmail(
                  addressInfo.email,
                  &quot;Good news!&quot;,
                  `Dear ${empInfo.name}\n` +
                  `based on your ${yearsEmployed} years of employment, you have been granted ${yearsEmployed} days of vacation, bringing your total to ${newVacationBalance}`
              );
          }
      }
      console.timeEnd();
  }
  
  // for the testing part I'll implement sendEmail as printing:
  class myEmailApi implements EmailApi {
      sendEmail(email: string, subject: string, body: string): void {
          console.log('********************');
          console.log(`To ${email}, Subject: ${subject}, body: ${body}`);
          console.log('********************');
      }
  }
  
  let myPayroll: Payroll[] = [
      { emp_id: &quot;1&quot;, vacationDays: 1 },
      { emp_id: &quot;2&quot;, vacationDays: 2 },
      { emp_id: &quot;3&quot;, vacationDays: 3 },
      { emp_id: &quot;4&quot;, vacationDays: 4 },
      { emp_id: &quot;5&quot;, vacationDays: 5 },
      { emp_id: &quot;6&quot;, vacationDays: 6 }
  ];
  
  let myAdress: AddressBook[] = [
      { emp_id: &quot;1&quot;, first: &quot;emp&quot;, last: &quot;number 1&quot;, email: &quot;emp1@gmail.com&quot; },
      { emp_id: &quot;2&quot;, first: &quot;emp&quot;, last: &quot;number 2&quot;, email: &quot;emp2@gmail.com&quot; },
      { emp_id: &quot;3&quot;, first: &quot;emp&quot;, last: &quot;number 3&quot;, email: &quot;emp3@gmail.com&quot; },
      { emp_id: &quot;4&quot;, first: &quot;emp&quot;, last: &quot;number 4&quot;, email: &quot;emp4@gmail.com&quot; },
      { emp_id: &quot;5&quot;, first: &quot;emp&quot;, last: &quot;number 5&quot;, email: &quot;emp5@gmail.com&quot; },
      { emp_id: &quot;6&quot;, first: &quot;emp&quot;, last: &quot;number 6&quot;, email: &quot;emp6@gmail.com&quot; },
  ];
  
  let myEmployees: Employee[] = [
      { id: &quot;1&quot;, name: &quot;emp number 1&quot;, startDate: new Date(&quot;2020-01-01&quot;), endDate: new Date(&quot;2025-01-01&quot;) },
      { id: &quot;2&quot;, name: &quot;emp number 2&quot;, startDate: new Date(&quot;2019-01-01&quot;), endDate: new Date(&quot;2025-01-01&quot;) },
      { id: &quot;3&quot;, name: &quot;emp number 3&quot;, startDate: new Date(&quot;2018-01-01&quot;), endDate: new Date(&quot;2025-01-01&quot;) },
      { id: &quot;4&quot;, name: &quot;emp number 4&quot;, startDate: new Date(&quot;2017-01-01&quot;), endDate: new Date(&quot;2025-01-01&quot;) },
      { id: &quot;5&quot;, name: &quot;emp number 5&quot;, startDate: new Date(&quot;2016-01-01&quot;), endDate: new Date(&quot;2025-01-01&quot;) },
      { id: &quot;6&quot;, name: &quot;emp number 6&quot;, startDate: new Date(&quot;2015-01-01&quot;), endDate: new Date(&quot;2025-01-01&quot;) },
  ];
  
  grantVacation(new myEmailApi(), myPayroll, myAdress, myEmployees);
  </code></pre>
  <p>There is nothing special here, this is a demo for sending email to every employee in the company after calculating the new vacation days of the employees.</p>
  <p>So I've already read that using &quot;for...in&quot; is really slow in comperance to the other loops (while, for, foreach) and should not be used since it uses a lookup mechnism for every property which makes the code really slow.</p>
  <p>I tried to improve the code like this (using async) but when I measured the time I found out both version are somewhat the same, or even worse for the improvment which means my solution at least didn't improve the performance</p>
  <p>the improved version of my code is:</p>
  <pre><code>export interface AddressBook {
      emp_id: string | null;
      first: string;
      last: string;
      email: string;
  }
  export interface Payroll {
      emp_id: string;
      vacationDays: number;
  }
  interface Employee {
      id: string;
      name: string;
      startDate: Date;
      endDate: Date | null;
  }
  export interface EmailApi {
      sendEmail(email: string, subject: string, body: string): void;
  }
  function yearsSince(startDate: Date, endDate: Date): number {
      const millisecondsPerYear = 365 * 24 * 60 * 60 * 1000;
      return Math.trunc((endDate.getTime() - startDate.getTime()) / millisecondsPerYear);
  }
  /**
   * We haved decided to grant bonus vacation to every employee, 1 day per year of experience
   * we need to email them a notice.
   */
  
  function calculateVacation(payrollInfo: Payroll, empInfo: Employee): Promise&lt;any&gt; {
      // &quot;wrap&quot; a sync function inside of a promise and finish the calulation.
      return new Promise((resolve) =&gt; {
          let today = new Date();
          let yearsEmployed = 0;
  
          if (empInfo != undefined) {
              yearsEmployed = yearsSince(empInfo.startDate, today);
          }
          let newVacationBalance = yearsEmployed + payrollInfo.vacationDays;
          // return all the relevant values from this promise as a single array to use.
          resolve([empInfo?.name, yearsEmployed, newVacationBalance]);
      });
  }
  
  async function asyncSendEmail(emailApi: EmailApi, payrollInfo: Payroll, addresses: AddressBook[], employees: Employee[]) {
      //Moran's note: adding a timer to see the performance.
      const startTime = Date.now();
      let addressInfo = addresses.find(x =&gt; x.emp_id == payrollInfo.emp_id);
      await Promise.all(employees.map(empInfo =&gt; {
          if (empInfo.id == payrollInfo.emp_id) {
              calculateVacation(payrollInfo, empInfo)
                  .then(([empInfoName, yearsEmployed, newVacationBalance]) =&gt; {
                      if (addressInfo != undefined) {
                          emailApi.sendEmail(
                              addressInfo.email,
                              &quot;Good news!&quot;,
                              `Dear ${empInfoName}\n` +
                              `based on your ${yearsEmployed} years of employment, you have been granted ${yearsEmployed} days of vacation, bringing your total to ${newVacationBalance}`
                          );
                      }
                  });
          }
      }));
      const msElapsed = Date.now() - startTime;
      console.log(`Async function took ${msElapsed} ms to complete.`);
  }
  
  function grantVacation(
      emailApi: EmailApi,
      payroll: Payroll[],
      addresses: AddressBook[],
      employees: Employee[]) {
  
      for (let i = 0; i &lt; payroll.length; i++) {
          let payrollInfo = payroll[i];
          asyncSendEmail(emailApi, payrollInfo, addresses, employees);
      }
  }
  
  // for the testing part I'll implement sendEmail as printing:
  class myEmailApi implements EmailApi {
      sendEmail(email: string, subject: string, body: string): void {
          console.log('********************');
          console.log(`To ${email}, Subject: ${subject}, body: ${body}`);
          console.log('********************');
      }
  }
  
  let myPayroll: Payroll[] = [
      { emp_id: &quot;1&quot;, vacationDays: 1 },
      { emp_id: &quot;2&quot;, vacationDays: 2 },
      { emp_id: &quot;3&quot;, vacationDays: 3 },
      { emp_id: &quot;4&quot;, vacationDays: 4 },
      { emp_id: &quot;5&quot;, vacationDays: 5 },
      { emp_id: &quot;6&quot;, vacationDays: 6 }
  ];
  
  let myAdress: AddressBook[] = [
      { emp_id: &quot;1&quot;, first: &quot;emp&quot;, last: &quot;number 1&quot;, email: &quot;emp1@gmail.com&quot; },
      { emp_id: &quot;2&quot;, first: &quot;emp&quot;, last: &quot;number 2&quot;, email: &quot;emp2@gmail.com&quot; },
      { emp_id: &quot;3&quot;, first: &quot;emp&quot;, last: &quot;number 3&quot;, email: &quot;emp3@gmail.com&quot; },
      { emp_id: &quot;4&quot;, first: &quot;emp&quot;, last: &quot;number 4&quot;, email: &quot;emp4@gmail.com&quot; },
      { emp_id: &quot;5&quot;, first: &quot;emp&quot;, last: &quot;number 5&quot;, email: &quot;emp5@gmail.com&quot; },
      { emp_id: &quot;6&quot;, first: &quot;emp&quot;, last: &quot;number 6&quot;, email: &quot;emp6@gmail.com&quot; },
  ];
  
  let myEmployees: Employee[] = [
      { id: &quot;1&quot;, name: &quot;emp number 1&quot;, startDate: new Date(&quot;2020-01-01&quot;), endDate: new Date(&quot;2025-01-01&quot;) },
      { id: &quot;2&quot;, name: &quot;emp number 2&quot;, startDate: new Date(&quot;2019-01-01&quot;), endDate: new Date(&quot;2025-01-01&quot;) },
      { id: &quot;3&quot;, name: &quot;emp number 3&quot;, startDate: new Date(&quot;2018-01-01&quot;), endDate: new Date(&quot;2025-01-01&quot;) },
      { id: &quot;4&quot;, name: &quot;emp number 4&quot;, startDate: new Date(&quot;2017-01-01&quot;), endDate: new Date(&quot;2025-01-01&quot;) },
      { id: &quot;5&quot;, name: &quot;emp number 5&quot;, startDate: new Date(&quot;2016-01-01&quot;), endDate: new Date(&quot;2025-01-01&quot;) },
      { id: &quot;6&quot;, name: &quot;emp number 6&quot;, startDate: new Date(&quot;2015-01-01&quot;), endDate: new Date(&quot;2025-01-01&quot;) },
  ];
  
  grantVacation(new myEmailApi(), myPayroll, myAdress, myEmployees);
  
  </code></pre>
  <p>I would really like to know what did I do wrong? maybe my way of implementing it as async missed some basic knowledge?
  maybe the code is okay but when measuring the time for the given tested data (I could make it even greater then 6) is just too small?</p>
  <p>thanks in advance</p>