From aa9de3621209c59f365f22e28b24fc8c5ce7b173 Mon Sep 17 00:00:00 2001 From: Brendan Kenny Date: Fri, 16 Jun 2023 15:04:36 -0500 Subject: [PATCH] make bindReporter generic over metric type --- src/lib/bindReporter.ts | 8 +++--- src/lib/initMetric.ts | 12 ++++++--- src/lib/polyfills/interactionCountPolyfill.ts | 5 ++-- src/onCLS.ts | 8 +++--- src/onFCP.ts | 5 ++-- src/onFID.ts | 7 +++-- src/onINP.ts | 5 ++-- src/onLCP.ts | 5 ++-- src/onTTFB.ts | 5 ++-- src/types/base.ts | 27 ++++++++++--------- src/types/cls.ts | 4 +-- src/types/fcp.ts | 4 +-- src/types/fid.ts | 4 +-- src/types/inp.ts | 4 +-- src/types/lcp.ts | 4 +-- src/types/ttfb.ts | 4 +-- 16 files changed, 56 insertions(+), 55 deletions(-) diff --git a/src/lib/bindReporter.ts b/src/lib/bindReporter.ts index 941061d2..f145f3b9 100644 --- a/src/lib/bindReporter.ts +++ b/src/lib/bindReporter.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import {Metric, MetricRatingThresholds, ReportCallback} from '../types.js'; +import {Metric, MetricRatingThresholds} from '../types.js'; const getRating = ( value: number, @@ -29,9 +29,9 @@ const getRating = ( return 'good'; }; -export const bindReporter = ( - callback: ReportCallback, - metric: Metric, +export const bindReporter = ( + callback: (metric: Extract) => void, + metric: Extract, thresholds: MetricRatingThresholds, reportAllChanges?: boolean ) => { diff --git a/src/lib/initMetric.ts b/src/lib/initMetric.ts index 4691db72..a5ff183a 100644 --- a/src/lib/initMetric.ts +++ b/src/lib/initMetric.ts @@ -20,7 +20,10 @@ import {getActivationStart} from './getActivationStart.js'; import {getNavigationEntry} from './getNavigationEntry.js'; import {Metric} from '../types.js'; -export const initMetric = (name: Metric['name'], value?: number): Metric => { +export const initMetric = ( + name: MetricName, + value?: number +) => { const navEntry = getNavigationEntry(); let navigationType: Metric['navigationType'] = 'navigate'; @@ -39,12 +42,15 @@ export const initMetric = (name: Metric['name'], value?: number): Metric => { } } + // Use `entries` type specific for the metric. + const entries: Extract['entries'] = []; + return { name, value: typeof value === 'undefined' ? -1 : value, - rating: 'good', // Will be updated if the value changes. + rating: 'good' as const, // Will be updated if the value changes. delta: 0, - entries: [], + entries, id: generateUniqueID(), navigationType, }; diff --git a/src/lib/polyfills/interactionCountPolyfill.ts b/src/lib/polyfills/interactionCountPolyfill.ts index fd29d103..e363376e 100644 --- a/src/lib/polyfills/interactionCountPolyfill.ts +++ b/src/lib/polyfills/interactionCountPolyfill.ts @@ -15,7 +15,6 @@ */ import {observe} from '../observe.js'; -import {Metric} from '../../types.js'; declare global { interface Performance { @@ -27,8 +26,8 @@ let interactionCountEstimate = 0; let minKnownInteractionId = Infinity; let maxKnownInteractionId = 0; -const updateEstimate = (entries: Metric['entries']) => { - (entries as PerformanceEventTiming[]).forEach((e) => { +const updateEstimate = (entries: PerformanceEventTiming[]) => { + entries.forEach((e) => { if (e.interactionId) { minKnownInteractionId = Math.min(minKnownInteractionId, e.interactionId); maxKnownInteractionId = Math.max(maxKnownInteractionId, e.interactionId); diff --git a/src/onCLS.ts b/src/onCLS.ts index ed066b66..6698a34a 100644 --- a/src/onCLS.ts +++ b/src/onCLS.ts @@ -26,7 +26,6 @@ import { CLSMetric, CLSReportCallback, MetricRatingThresholds, - ReportCallback, ReportOpts, } from './types.js'; @@ -66,9 +65,8 @@ export const onCLS = (onReport: CLSReportCallback, opts?: ReportOpts) => { let report: ReturnType; let sessionValue = 0; - let sessionEntries: PerformanceEntry[] = []; + let sessionEntries: LayoutShift[] = []; - // const handleEntries = (entries: Metric['entries']) => { const handleEntries = (entries: LayoutShift[]) => { entries.forEach((entry) => { // Only count layout shifts without recent user input. @@ -106,7 +104,7 @@ export const onCLS = (onReport: CLSReportCallback, opts?: ReportOpts) => { const po = observe('layout-shift', handleEntries); if (po) { report = bindReporter( - onReport as ReportCallback, + onReport, metric, CLSThresholds, opts!.reportAllChanges @@ -123,7 +121,7 @@ export const onCLS = (onReport: CLSReportCallback, opts?: ReportOpts) => { sessionValue = 0; metric = initMetric('CLS', 0); report = bindReporter( - onReport as ReportCallback, + onReport, metric, CLSThresholds, opts!.reportAllChanges diff --git a/src/onFCP.ts b/src/onFCP.ts index fc55baf4..a781cab8 100644 --- a/src/onFCP.ts +++ b/src/onFCP.ts @@ -26,7 +26,6 @@ import { FCPMetric, FCPReportCallback, MetricRatingThresholds, - ReportCallback, ReportOpts, } from './types.js'; @@ -71,7 +70,7 @@ export const onFCP = (onReport: FCPReportCallback, opts?: ReportOpts) => { if (po) { report = bindReporter( - onReport as ReportCallback, + onReport, metric, FCPThresholds, opts!.reportAllChanges @@ -82,7 +81,7 @@ export const onFCP = (onReport: FCPReportCallback, opts?: ReportOpts) => { onBFCacheRestore((event) => { metric = initMetric('FCP'); report = bindReporter( - onReport as ReportCallback, + onReport, metric, FCPThresholds, opts!.reportAllChanges diff --git a/src/onFID.ts b/src/onFID.ts index 8cafe272..0eed4cc1 100644 --- a/src/onFID.ts +++ b/src/onFID.ts @@ -31,7 +31,6 @@ import { FIDReportCallback, FirstInputPolyfillCallback, MetricRatingThresholds, - ReportCallback, ReportOpts, } from './types.js'; @@ -71,7 +70,7 @@ export const onFID = (onReport: FIDReportCallback, opts?: ReportOpts) => { const po = observe('first-input', handleEntries); report = bindReporter( - onReport as ReportCallback, + onReport, metric, FIDThresholds, opts!.reportAllChanges @@ -100,7 +99,7 @@ export const onFID = (onReport: FIDReportCallback, opts?: ReportOpts) => { onBFCacheRestore(() => { metric = initMetric('FID'); report = bindReporter( - onReport as ReportCallback, + onReport, metric, FIDThresholds, opts!.reportAllChanges @@ -117,7 +116,7 @@ export const onFID = (onReport: FIDReportCallback, opts?: ReportOpts) => { onBFCacheRestore(() => { metric = initMetric('FID'); report = bindReporter( - onReport as ReportCallback, + onReport, metric, FIDThresholds, opts!.reportAllChanges diff --git a/src/onINP.ts b/src/onINP.ts index d0c66385..473af397 100644 --- a/src/onINP.ts +++ b/src/onINP.ts @@ -28,7 +28,6 @@ import { INPMetric, INPReportCallback, MetricRatingThresholds, - ReportCallback, ReportOpts, } from './types.js'; @@ -212,7 +211,7 @@ export const onINP = (onReport: INPReportCallback, opts?: ReportOpts) => { } as PerformanceObserverInit); report = bindReporter( - onReport as ReportCallback, + onReport, metric, INPThresholds, opts!.reportAllChanges @@ -246,7 +245,7 @@ export const onINP = (onReport: INPReportCallback, opts?: ReportOpts) => { metric = initMetric('INP'); report = bindReporter( - onReport as ReportCallback, + onReport, metric, INPThresholds, opts!.reportAllChanges diff --git a/src/onLCP.ts b/src/onLCP.ts index 70eeeafd..14a0dfaa 100644 --- a/src/onLCP.ts +++ b/src/onLCP.ts @@ -28,7 +28,6 @@ import { LCPMetric, MetricRatingThresholds, LCPReportCallback, - ReportCallback, ReportOpts, } from './types.js'; @@ -82,7 +81,7 @@ export const onLCP = (onReport: LCPReportCallback, opts?: ReportOpts) => { if (po) { report = bindReporter( - onReport as ReportCallback, + onReport, metric, LCPThresholds, opts!.reportAllChanges @@ -111,7 +110,7 @@ export const onLCP = (onReport: LCPReportCallback, opts?: ReportOpts) => { onBFCacheRestore((event) => { metric = initMetric('LCP'); report = bindReporter( - onReport as ReportCallback, + onReport, metric, LCPThresholds, opts!.reportAllChanges diff --git a/src/onTTFB.ts b/src/onTTFB.ts index 63d11d38..f6a8fec9 100644 --- a/src/onTTFB.ts +++ b/src/onTTFB.ts @@ -20,7 +20,6 @@ import {onBFCacheRestore} from './lib/bfcache.js'; import {getNavigationEntry} from './lib/getNavigationEntry.js'; import { MetricRatingThresholds, - ReportCallback, ReportOpts, TTFBReportCallback, } from './types.js'; @@ -66,7 +65,7 @@ export const onTTFB = (onReport: TTFBReportCallback, opts?: ReportOpts) => { let metric = initMetric('TTFB'); let report = bindReporter( - onReport as ReportCallback, + onReport, metric, TTFBThresholds, opts.reportAllChanges @@ -100,7 +99,7 @@ export const onTTFB = (onReport: TTFBReportCallback, opts?: ReportOpts) => { onBFCacheRestore(() => { metric = initMetric('TTFB', 0); report = bindReporter( - onReport as ReportCallback, + onReport, metric, TTFBThresholds, opts!.reportAllChanges diff --git a/src/types/base.ts b/src/types/base.ts index 3cce6b7f..bc1af37c 100644 --- a/src/types/base.ts +++ b/src/types/base.ts @@ -18,8 +18,14 @@ import { FirstInputPolyfillEntry, NavigationTimingPolyfillEntry, } from './polyfills.js'; +import type {CLSMetric} from './cls.js'; +import type {FCPMetric} from './fcp.js'; +import type {FIDMetric} from './fid.js'; +import type {INPMetric} from './inp.js'; +import type {LCPMetric} from './lcp.js'; +import type {TTFBMetric} from './ttfb.js'; -export interface Metric { +export interface MetricBase { /** * The name of the metric (in acronym form). */ @@ -85,17 +91,14 @@ export interface Metric { | 'restore'; } -/** - * A version of the `Metric` that is used with the attribution build. - */ -export interface MetricWithAttribution extends Metric { - /** - * An object containing potentially-helpful debugging information that - * can be sent along with the metric value for the current page visit in - * order to help identify issues happening to real-users in the field. - */ - attribution: {[key: string]: unknown}; -} +/** The union of supported metric types. */ +export type Metric = + | CLSMetric + | FCPMetric + | FIDMetric + | INPMetric + | LCPMetric + | TTFBMetric; /** * The thresholds of metric's "good", "needs improvement", and "poor" ratings. diff --git a/src/types/cls.ts b/src/types/cls.ts index a8f91be9..2288d46e 100644 --- a/src/types/cls.ts +++ b/src/types/cls.ts @@ -14,12 +14,12 @@ * limitations under the License. */ -import {LoadState, Metric} from './base.js'; +import type {LoadState, MetricBase} from './base.js'; /** * A CLS-specific version of the Metric object. */ -export interface CLSMetric extends Metric { +export interface CLSMetric extends MetricBase { name: 'CLS'; entries: LayoutShift[]; } diff --git a/src/types/fcp.ts b/src/types/fcp.ts index 0d8484a8..2f671e91 100644 --- a/src/types/fcp.ts +++ b/src/types/fcp.ts @@ -14,13 +14,13 @@ * limitations under the License. */ -import {LoadState, Metric} from './base.js'; +import type {LoadState, MetricBase} from './base.js'; import {NavigationTimingPolyfillEntry} from './polyfills.js'; /** * An FCP-specific version of the Metric object. */ -export interface FCPMetric extends Metric { +export interface FCPMetric extends MetricBase { name: 'FCP'; entries: PerformancePaintTiming[]; } diff --git a/src/types/fid.ts b/src/types/fid.ts index 6bb3e59c..76658789 100644 --- a/src/types/fid.ts +++ b/src/types/fid.ts @@ -14,13 +14,13 @@ * limitations under the License. */ -import {LoadState, Metric} from './base.js'; +import type {LoadState, MetricBase} from './base.js'; import {FirstInputPolyfillEntry} from './polyfills.js'; /** * An FID-specific version of the Metric object. */ -export interface FIDMetric extends Metric { +export interface FIDMetric extends MetricBase { name: 'FID'; entries: (PerformanceEventTiming | FirstInputPolyfillEntry)[]; } diff --git a/src/types/inp.ts b/src/types/inp.ts index e7e4ad3f..ddc3b0a7 100644 --- a/src/types/inp.ts +++ b/src/types/inp.ts @@ -14,12 +14,12 @@ * limitations under the License. */ -import {LoadState, Metric} from './base.js'; +import type {LoadState, MetricBase} from './base.js'; /** * An INP-specific version of the Metric object. */ -export interface INPMetric extends Metric { +export interface INPMetric extends MetricBase { name: 'INP'; entries: PerformanceEventTiming[]; } diff --git a/src/types/lcp.ts b/src/types/lcp.ts index 43c0f924..9a2159d8 100644 --- a/src/types/lcp.ts +++ b/src/types/lcp.ts @@ -14,13 +14,13 @@ * limitations under the License. */ -import {Metric} from './base.js'; +import type {MetricBase} from './base.js'; import {NavigationTimingPolyfillEntry} from './polyfills.js'; /** * An LCP-specific version of the Metric object. */ -export interface LCPMetric extends Metric { +export interface LCPMetric extends MetricBase { name: 'LCP'; entries: LargestContentfulPaint[]; } diff --git a/src/types/ttfb.ts b/src/types/ttfb.ts index 93148840..9cec27e1 100644 --- a/src/types/ttfb.ts +++ b/src/types/ttfb.ts @@ -14,13 +14,13 @@ * limitations under the License. */ -import {Metric} from './base.js'; +import type {MetricBase} from './base.js'; import {NavigationTimingPolyfillEntry} from './polyfills.js'; /** * A TTFB-specific version of the Metric object. */ -export interface TTFBMetric extends Metric { +export interface TTFBMetric extends MetricBase { name: 'TTFB'; entries: PerformanceNavigationTiming[] | NavigationTimingPolyfillEntry[]; }