diff --git a/packages/utils/src/perf_hooks.d.ts b/packages/utils/src/perf_hooks.d.ts new file mode 100644 index 000000000..e3bf6fb1a --- /dev/null +++ b/packages/utils/src/perf_hooks.d.ts @@ -0,0 +1,48 @@ +import type { + MarkerPayload, + TrackEntryPayload, + WithDevToolsPayload, +} from './lib/user-timing-extensibility-api.type'; + +export {}; + +type DetailPayloadWithDevtools = WithDevToolsPayload< + TrackEntryPayload | MarkerPayload +>; + +declare module 'node:perf_hooks' { + export interface PerformanceMarkOptions { + detail?: DetailPayloadWithDevtools; + startTime?: DOMHighResTimeStamp; + } + + export interface PerformanceMeasureOptions { + detail?: DetailPayloadWithDevtools; + start?: string | number; + end?: string | number; + duration?: number; + } + + const performance: { + mark( + name: string, + options?: { + detail?: DetailPayloadWithDevtools; + }, + ): PerformanceMark; + + measure( + name: string, + startOrOptions?: + | string + | number + | { + detail?: DetailPayloadWithDevtools; + start?: string | number; + end?: string | number; + duration?: number; + }, + end?: string | number, + ): PerformanceMeasure; + }; +} diff --git a/packages/utils/src/perf_hooks.type.test.ts b/packages/utils/src/perf_hooks.type.test.ts new file mode 100644 index 000000000..fb50c1fdd --- /dev/null +++ b/packages/utils/src/perf_hooks.type.test.ts @@ -0,0 +1,76 @@ +import { type PerformanceMarkOptions, performance } from 'node:perf_hooks'; +import { describe, expectTypeOf, it } from 'vitest'; + +describe('perf_hooks.type', () => { + it('PerformanceMarkOptions should be type safe', () => { + expectTypeOf<{ + startTime: number; + detail: { + devtools: { + dataType: 'marker'; + color: 'error'; + }; + }; + }>().toMatchTypeOf(); + + expectTypeOf<{ + startTime: number; + detail: { + devtools: { + dataType: 'markerr'; + }; + }; + }>().not.toMatchTypeOf(); + }); + + it('perf_hooks.mark should be type safe', () => { + performance.mark('name', { + detail: { + devtools: { + dataType: 'marker', + color: 'error', + }, + }, + }); + + performance.mark('name', { + detail: { + devtools: { + /* @ts-expect-error - dataType should be marker | track */ + dataType: 'markerrr', + color: 'error', + }, + }, + }); + }); + + it('PerformanceMeasureOptions should be type safe', () => { + expectTypeOf<{ + start: string; + end: string; + detail: { + devtools: { + dataType: 'track-entry'; + track: 'test-track'; + color: 'primary'; + }; + }; + }>().toMatchTypeOf(); + }); + + it('perf_hooks.measure should be type safe', () => { + performance.measure('measure-name', 'start-mark', 'end-mark'); + + performance.measure('measure-name', { + start: 'start-mark', + end: 'end-mark', + detail: { + /* @ts-expect-error - track is required */ + devtools: { + dataType: 'track-entry', + color: 'primary', + }, + }, + }); + }); +}); diff --git a/packages/utils/tsconfig.lib.json b/packages/utils/tsconfig.lib.json index 17dadcedf..973149960 100644 --- a/packages/utils/tsconfig.lib.json +++ b/packages/utils/tsconfig.lib.json @@ -5,7 +5,7 @@ "declaration": true, "types": ["node"] }, - "include": ["src/**/*.ts"], + "include": ["src/**/*.{ts,d.ts}"], "exclude": [ "vitest.unit.config.ts", "vitest.int.config.ts", diff --git a/packages/utils/tsconfig.test.json b/packages/utils/tsconfig.test.json index 54cacd82f..65a45077f 100644 --- a/packages/utils/tsconfig.test.json +++ b/packages/utils/tsconfig.test.json @@ -13,6 +13,7 @@ "src/**/*.test.js", "src/**/*.test.jsx", "src/**/*.d.ts", - "../../testing/test-setup/src/vitest.d.ts" + "../../testing/test-setup/src/vitest.d.ts", + "src/perf_hooks.type.ts" ] }