Repository: GoogleChrome/lighthouse
Pull request #5874 (2018-08-20 22:51:40)

core(tsc): remove more reliance on implicit index signatures
part of #5873

No real theme here, just scattered fixes where none needed major interventions. Resolves 23 errors when using `typescript@next`.

The other side of some of these fixes is going explicitly `any` or `ts-ignore`, but it didn't seem worth losing refactoring, intellisense, etc for most of these


Patch:
diff --git a/lighthouse-cli/bin.js b/lighthouse-cli/bin.js
index d02844d89..4baa04b15 100644
--- a/lighthouse-cli/bin.js
+++ b/lighthouse-cli/bin.js
@@ -107,6 +107,7 @@ function run() {
       }
     })
     .then(_ => {
+      // @ts-ignore TODO(bckenny): Sentry type checking
       Sentry.init({
         url,
         flags: cliFlags,
diff --git a/lighthouse-core/audits/dobetterweb/dom-size.js b/lighthouse-core/audits/dobetterweb/dom-size.js
index de0872d36..38cb9e6e0 100644
--- a/lighthouse-core/audits/dobetterweb/dom-size.js
+++ b/lighthouse-core/audits/dobetterweb/dom-size.js
@@ -101,6 +101,7 @@ class DOMSize extends Audit {
       {key: 'width', itemType: 'text', text: str_(UIStrings.columnDOMWidth)},
     ];
 
+    /** @type {Array<Object<string, LH.Audit.DetailsItem>>} */
     const items = [
       {
         totalNodes: Util.formatNumber(stats.totalDOMNodes),
diff --git a/lighthouse-core/audits/user-timings.js b/lighthouse-core/audits/user-timings.js
index 6429bfd7c..d3015f13d 100644
--- a/lighthouse-core/audits/user-timings.js
+++ b/lighthouse-core/audits/user-timings.js
@@ -56,6 +56,7 @@ class UserTimings extends Audit {
   static filterTrace(tabTrace) {
     /** @type {Array<MarkEvent|MeasureEvent>} */
     const userTimings = [];
+    /** @type {Record<string, number>} */
     const measuresStartTimes = {};
 
     // Get all blink.user_timing events
diff --git a/lighthouse-core/gather/computed/metrics/lantern-metric.js b/lighthouse-core/gather/computed/metrics/lantern-metric.js
index 43a15c2b0..425ce6d06 100644
--- a/lighthouse-core/gather/computed/metrics/lantern-metric.js
+++ b/lighthouse-core/gather/computed/metrics/lantern-metric.js
@@ -85,6 +85,7 @@ class LanternMetricArtifact extends ComputedArtifact {
     const optimisticGraph = this.getOptimisticGraph(graph, traceOfTab);
     const pessimisticGraph = this.getPessimisticGraph(graph, traceOfTab);
 
+    /** @type {{flexibleOrdering?: boolean, label?: string}} */
     let simulateOptions = {label: `optimistic${metricName}`};
     const optimisticSimulation = simulator.simulate(optimisticGraph, simulateOptions);
 
diff --git a/lighthouse-core/lib/dependency-graph/simulator/network-analyzer.js b/lighthouse-core/lib/dependency-graph/simulator/network-analyzer.js
index 2eaac3dd7..c2ad615fa 100644
--- a/lighthouse-core/lib/dependency-graph/simulator/network-analyzer.js
+++ b/lighthouse-core/lib/dependency-graph/simulator/network-analyzer.js
@@ -11,8 +11,11 @@ const NetworkRequest = require('../../network-request');
 // Assume that 40% of TTFB was server response time by default for static assets
 const DEFAULT_SERVER_RESPONSE_PERCENTAGE = 0.4;
 
-// For certain resource types, server response time takes up a greater percentage of TTFB (dynamic
-// assets like HTML documents, XHR/API calls, etc)
+/**
+ * For certain resource types, server response time takes up a greater percentage of TTFB (dynamic
+ * assets like HTML documents, XHR/API calls, etc)
+ * @type {Partial<Record<LH.Crdp.Page.ResourceType, number>>}
+ */
 const SERVER_RESPONSE_PERCENTAGE_OF_TTFB = {
   Document: 0.9,
   XHR: 0.9,
@@ -73,9 +76,11 @@ class NetworkAnalyzer {
     return summaryByKey;
   }
 
+  /** @typedef {{record: LH.Artifacts.NetworkRequest, timing: LH.Crdp.Network.ResourceTiming, connectionReused?: boolean}} RequestInfo */
+
   /**
    * @param {LH.Artifacts.NetworkRequest[]} records
-   * @param {function(any):any} iteratee
+   * @param {(e: RequestInfo) => number | number[] | undefined} iteratee
    * @return {Map<string, number[]>}
    */
   static _estimateValueByOrigin(records, iteratee) {
@@ -190,6 +195,7 @@ class NetworkAnalyzer {
   static _estimateRTTByOriginViaHeadersEndTiming(records) {
     return NetworkAnalyzer._estimateValueByOrigin(records, ({record, timing, connectionReused}) => {
       if (!Number.isFinite(timing.receiveHeadersEnd) || timing.receiveHeadersEnd < 0) return;
+      if (!record.resourceType) return;
 
       const serverResponseTimePercentage = SERVER_RESPONSE_PERCENTAGE_OF_TTFB[record.resourceType]
         || DEFAULT_SERVER_RESPONSE_PERCENTAGE;
diff --git a/lighthouse-core/lib/i18n.js b/lighthouse-core/lib/i18n.js
index 05512a2f3..274137464 100644
--- a/lighthouse-core/lib/i18n.js
+++ b/lighthouse-core/lib/i18n.js
@@ -175,6 +175,7 @@ function _formatPathAsString(pathInLHR) {
  */
 function getRendererFormattedStrings(locale) {
   const icuMessageIds = Object.keys(LOCALES[locale]).filter(f => f.includes('core/report/html/'));
+  /** @type {LH.I18NRendererStrings} */
   const strings = {};
   for (const icuMessageId of icuMessageIds) {
     const [filename, varName] = icuMessageId.split(' | ');
@@ -190,6 +191,7 @@ function getRendererFormattedStrings(locale) {
  * @param {Record<string, string>} fileStrings
  */
 function createMessageInstanceIdFn(filename, fileStrings) {
+  /** @type {Record<string, string>} */
   const mergedStrings = {...UIStrings, ...fileStrings};
 
   /** @param {string} icuMessage @param {*} [values] */
@@ -284,6 +286,7 @@ function replaceIcuMessageInstanceIds(lhr, locale) {
     }
   }
 
+  /** @type {LH.I18NMessages} */
   const icuMessagePaths = {};
   replaceInObject(lhr, icuMessagePaths);
   return icuMessagePaths;
diff --git a/lighthouse-core/lib/locales/index.js b/lighthouse-core/lib/locales/index.js
index aa4baed52..26c4cc7ce 100644
--- a/lighthouse-core/lib/locales/index.js
+++ b/lighthouse-core/lib/locales/index.js
@@ -5,6 +5,13 @@
  */
 'use strict';
 
+/** @fileoverview
+ * Define message file to be used for a given locale. A few aliases are defined below.
+ *
+ * Google locale inheritance rules: https://goto.google.com/ccssm
+ * CLDR language aliases: https://www.unicode.org/cldr/charts/latest/supplemental/aliases.html
+ */
+
 /** @typedef {Record<string, {message: string}>} LocaleMessages */
 
 // The keys within this const must exactly match the LH.Locale type in externs.d.ts
@@ -48,6 +55,7 @@ const locales = {
   'iw': require('./he.json'), // Alias of 'he'
   'ja': require('./ja.json'),
   'ko': require('./ko.json'),
+  'ln': require('./fr.json'), // Alias of 'fr'
   'lt': require('./lt.json'),
   'lv': require('./lv.json'),
   'mo': require('./ro.json'), // Alias of 'ro'
diff --git a/lighthouse-core/report/html/renderer/psi.js b/lighthouse-core/report/html/renderer/psi.js
index 1d81ef08e..93d81503f 100644
--- a/lighthouse-core/report/html/renderer/psi.js
+++ b/lighthouse-core/report/html/renderer/psi.js
@@ -37,6 +37,9 @@ function prepareLabData(LHResultJsonString, document) {
   const lhResult = /** @type {LH.Result} */ JSON.parse(LHResultJsonString);
   const dom = new DOM(document);
 
+  // Assume fresh styles needed on every call, so mark all template styles as unused.
+  dom.resetTemplates();
+
   const reportLHR = Util.prepareReportResult(lhResult);
   const perfCategory = reportLHR.reportCategories.find(cat => cat.id === 'performance');
   if (!perfCategory) throw new Error(`No performance category. Can't make lab data section`);
diff --git a/lighthouse-core/report/html/renderer/report-ui-features.js b/lighthouse-core/report/html/renderer/report-ui-features.js
index c3ea5bcb0..97d590c59 100644
--- a/lighthouse-core/report/html/renderer/report-ui-features.js
+++ b/lighthouse-core/report/html/renderer/report-ui-features.js
@@ -90,7 +90,7 @@ class ReportUIFeatures {
     this._setupHeaderAnimation();
     this._resetUIState();
     this._document.addEventListener('keydown', this.printShortCutDetect);
-    // @ts-ignore - tsc thinks document can't listen for `copy`
+    // @ts-ignore - TODO(bckenny): tsc thinks document can't listen for `copy`. Remove ignore in 3.1.
     this._document.addEventListener('copy', this.onCopy);
   }
 
@@ -447,6 +447,7 @@ class ReportUIFeatures {
    */
   getReportHtml() {
     this._resetUIState();
+    // @ts-ignore - technically documentElement can be null, but that's dumb - https://dom.spec.whatwg.org/#document-element
     return this._document.documentElement.outerHTML;
   }
 
diff --git a/lighthouse-core/report/html/renderer/util.js b/lighthouse-core/report/html/renderer/util.js
index b5c3ad0c3..b059a2c75 100644
--- a/lighthouse-core/report/html/renderer/util.js
+++ b/lighthouse-core/report/html/renderer/util.js
@@ -223,6 +223,7 @@ class Util {
    * @return {string}
    */
   static formatDateTime(date) {
+    /** @type {Intl.DateTimeFormatOptions} */
     const options = {
       month: 'short', day: 'numeric', year: 'numeric',
       hour: 'numeric', minute: 'numeric', timeZoneName: 'short',
@@ -444,6 +445,10 @@ class Util {
  */
 Util.numberDateLocale = 'en';
 
+/**
+ * Report-renderer-specific strings.
+ * @type {LH.I18NRendererStrings}
+ */
 Util.UIStrings = {
   /** Disclaimer shown to users below the metric values (First Contentful Paint, Time to Interactive, etc) to warn them that the numbers they see will likely change slightly the next time they run Lighthouse. */
   varianceDisclaimer: 'Values are estimated and may vary.',
diff --git a/lighthouse-core/runner.js b/lighthouse-core/runner.js
index c0eeb0d2b..117f115ed 100644
--- a/lighthouse-core/runner.js
+++ b/lighthouse-core/runner.js
@@ -368,6 +368,7 @@ class Runner {
       const ArtifactClass = require('./gather/computed/' + filename);
       const artifact = new ArtifactClass(computedArtifacts);
       // define the request* function that will be exposed on `artifacts`
+      // @ts-ignore - doesn't have an index signature, so can't be set dynamically.
       computedArtifacts['request' + artifact.name] = artifact.request.bind(artifact);
     });
 
diff --git a/lighthouse-core/scoring.js b/lighthouse-core/scoring.js
index 1768c782b..ddbab9fdb 100644
--- a/lighthouse-core/scoring.js
+++ b/lighthouse-core/scoring.js
@@ -50,6 +50,7 @@ class ReportScoring {
    * @return {Object<string, LH.Result.Category>}
    */
   static scoreAllCategories(configCategories, resultsByAuditId) {
+    /** @type {Record<string, LH.Result.Category>} */
     const scoredCategories = {};
 
     for (const [categoryId, configCategory] of Object.entries(configCategories)) {
diff --git a/lighthouse-core/scripts/i18n/collect-strings.js b/lighthouse-core/scripts/i18n/collect-strings.js
index f67274823..4a5fc225e 100644
--- a/lighthouse-core/scripts/i18n/collect-strings.js
+++ b/lighthouse-core/scripts/i18n/collect-strings.js
@@ -103,6 +103,7 @@ function collectAllStringsInDir(dir, strings = {}) {
  */
 function writeStringsToLocaleFormat(locale, strings) {
   const fullPath = path.join(LH_ROOT, `lighthouse-core/lib/locales/${locale}.json`);
+  /** @type {Record<string, ICUMessageDefn>} */
   const output = {};
   const sortedEntries = Object.entries(strings).sort(([keyA], [keyB]) => keyA.localeCompare(keyB));
   for (const [key, defn] of sortedEntries) {
diff --git a/lighthouse-extension/app/src/lighthouse-ext-background.js b/lighthouse-extension/app/src/lighthouse-ext-background.js
index 4b8b46146..59d11c125 100644
--- a/lighthouse-extension/app/src/lighthouse-ext-background.js
+++ b/lighthouse-extension/app/src/lighthouse-ext-background.js
@@ -122,7 +122,9 @@ function createReportPageAsBlob(reportHtml) {
  */
 function saveSettings(settings) {
   const storage = {
+    /** @type {Record<string, boolean>} */
     [STORAGE_KEY]: {},
+    /** @type {Record<string, boolean>} */
     [SETTINGS_KEY]: {},
   };
 
@@ -149,6 +151,7 @@ function loadSettings() {
     chrome.storage.local.get([STORAGE_KEY, SETTINGS_KEY], result => {
       // Start with list of all default categories set to true so list is
       // always up to date.
+      /** @type {Record<string, boolean>} */
       const defaultCategories = {};
       background.getDefaultCategories().forEach(category => {
         defaultCategories[category.id] = true;


Test patch:
diff --git a/lighthouse-core/test/lib/dependency-graph/simulator/network-analyzer-test.js b/lighthouse-core/test/lib/dependency-graph/simulator/network-analyzer-test.js
index 2bdae4f4e..db6444f71 100644
--- a/lighthouse-core/test/lib/dependency-graph/simulator/network-analyzer-test.js
+++ b/lighthouse-core/test/lib/dependency-graph/simulator/network-analyzer-test.js
@@ -170,7 +170,7 @@ describe('DependencyGraph/Simulator/NetworkAnalyzer', () => {
 
     it('should infer from TTFB when available', () => {
       const timing = {receiveHeadersEnd: 1000};
-      const record = createRecord({startTime: 0, endTime: 1, timing});
+      const record = createRecord({startTime: 0, endTime: 1, timing, resourceType: 'Other'});
       const result = NetworkAnalyzer.estimateRTTByOrigin([record], {
         coarseEstimateMultiplier: 1,
       });