Skip to content

Commit

Permalink
make bindReporter generic over metric type
Browse files Browse the repository at this point in the history
  • Loading branch information
brendankenny committed Jun 16, 2023
1 parent 233408c commit aa9de36
Show file tree
Hide file tree
Showing 16 changed files with 56 additions and 55 deletions.
8 changes: 4 additions & 4 deletions src/lib/bindReporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -29,9 +29,9 @@ const getRating = (
return 'good';
};

export const bindReporter = (
callback: ReportCallback,
metric: Metric,
export const bindReporter = <MetricName extends Metric['name']>(
callback: (metric: Extract<Metric, {name: MetricName}>) => void,
metric: Extract<Metric, {name: MetricName}>,
thresholds: MetricRatingThresholds,
reportAllChanges?: boolean
) => {
Expand Down
12 changes: 9 additions & 3 deletions src/lib/initMetric.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 = <MetricName extends Metric['name']>(
name: MetricName,
value?: number
) => {
const navEntry = getNavigationEntry();
let navigationType: Metric['navigationType'] = 'navigate';

Expand All @@ -39,12 +42,15 @@ export const initMetric = (name: Metric['name'], value?: number): Metric => {
}
}

// Use `entries` type specific for the metric.
const entries: Extract<Metric, {name: MetricName}>['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,
};
Expand Down
5 changes: 2 additions & 3 deletions src/lib/polyfills/interactionCountPolyfill.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
*/

import {observe} from '../observe.js';
import {Metric} from '../../types.js';

declare global {
interface Performance {
Expand All @@ -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);
Expand Down
8 changes: 3 additions & 5 deletions src/onCLS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import {
CLSMetric,
CLSReportCallback,
MetricRatingThresholds,
ReportCallback,
ReportOpts,
} from './types.js';

Expand Down Expand Up @@ -66,9 +65,8 @@ export const onCLS = (onReport: CLSReportCallback, opts?: ReportOpts) => {
let report: ReturnType<typeof bindReporter>;

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.
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down
5 changes: 2 additions & 3 deletions src/onFCP.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import {
FCPMetric,
FCPReportCallback,
MetricRatingThresholds,
ReportCallback,
ReportOpts,
} from './types.js';

Expand Down Expand Up @@ -71,7 +70,7 @@ export const onFCP = (onReport: FCPReportCallback, opts?: ReportOpts) => {

if (po) {
report = bindReporter(
onReport as ReportCallback,
onReport,
metric,
FCPThresholds,
opts!.reportAllChanges
Expand All @@ -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
Expand Down
7 changes: 3 additions & 4 deletions src/onFID.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ import {
FIDReportCallback,
FirstInputPolyfillCallback,
MetricRatingThresholds,
ReportCallback,
ReportOpts,
} from './types.js';

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down
5 changes: 2 additions & 3 deletions src/onINP.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import {
INPMetric,
INPReportCallback,
MetricRatingThresholds,
ReportCallback,
ReportOpts,
} from './types.js';

Expand Down Expand Up @@ -212,7 +211,7 @@ export const onINP = (onReport: INPReportCallback, opts?: ReportOpts) => {
} as PerformanceObserverInit);

report = bindReporter(
onReport as ReportCallback,
onReport,
metric,
INPThresholds,
opts!.reportAllChanges
Expand Down Expand Up @@ -246,7 +245,7 @@ export const onINP = (onReport: INPReportCallback, opts?: ReportOpts) => {

metric = initMetric('INP');
report = bindReporter(
onReport as ReportCallback,
onReport,
metric,
INPThresholds,
opts!.reportAllChanges
Expand Down
5 changes: 2 additions & 3 deletions src/onLCP.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import {
LCPMetric,
MetricRatingThresholds,
LCPReportCallback,
ReportCallback,
ReportOpts,
} from './types.js';

Expand Down Expand Up @@ -82,7 +81,7 @@ export const onLCP = (onReport: LCPReportCallback, opts?: ReportOpts) => {

if (po) {
report = bindReporter(
onReport as ReportCallback,
onReport,
metric,
LCPThresholds,
opts!.reportAllChanges
Expand Down Expand Up @@ -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
Expand Down
5 changes: 2 additions & 3 deletions src/onTTFB.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import {onBFCacheRestore} from './lib/bfcache.js';
import {getNavigationEntry} from './lib/getNavigationEntry.js';
import {
MetricRatingThresholds,
ReportCallback,
ReportOpts,
TTFBReportCallback,
} from './types.js';
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
27 changes: 15 additions & 12 deletions src/types/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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).
*/
Expand Down Expand Up @@ -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.
Expand Down
4 changes: 2 additions & 2 deletions src/types/cls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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[];
}
Expand Down
4 changes: 2 additions & 2 deletions src/types/fcp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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[];
}
Expand Down
4 changes: 2 additions & 2 deletions src/types/fid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)[];
}
Expand Down
4 changes: 2 additions & 2 deletions src/types/inp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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[];
}
Expand Down
4 changes: 2 additions & 2 deletions src/types/lcp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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[];
}
Expand Down
4 changes: 2 additions & 2 deletions src/types/ttfb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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[];
}
Expand Down

0 comments on commit aa9de36

Please sign in to comment.