Skip to content

Commit 343506b

Browse files
authored
ref: Refactor some any (#14477)
Refactoring some `as any` type casts we have to avoid this.
1 parent 3aafb40 commit 343506b

File tree

16 files changed

+78
-69
lines changed

16 files changed

+78
-69
lines changed

biome.json

+3
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@
4444
"angular.json",
4545
"ember/instance-initializers/**",
4646
"ember/types.d.ts",
47+
"solidstart/*.d.ts",
48+
"solidstart/client/",
49+
"solidstart/server/",
4750
".output",
4851
".vinxi"
4952
]

packages/browser-utils/src/instrument/dom.ts

+11-20
Original file line numberDiff line numberDiff line change
@@ -64,24 +64,21 @@ export function instrumentDOM(): void {
6464
// could potentially prevent the event from bubbling up to our global listeners. This way, our handler are still
6565
// guaranteed to fire at least once.)
6666
['EventTarget', 'Node'].forEach((target: string) => {
67-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
68-
const proto = (WINDOW as any)[target] && (WINDOW as any)[target].prototype;
69-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, no-prototype-builtins
67+
const globalObject = WINDOW as unknown as Record<string, { prototype?: object }>;
68+
const targetObj = globalObject[target];
69+
const proto = targetObj && targetObj.prototype;
70+
71+
// eslint-disable-next-line no-prototype-builtins
7072
if (!proto || !proto.hasOwnProperty || !proto.hasOwnProperty('addEventListener')) {
7173
return;
7274
}
7375

7476
fill(proto, 'addEventListener', function (originalAddEventListener: AddEventListener): AddEventListener {
75-
return function (
76-
this: Element,
77-
type: string,
78-
listener: EventListenerOrEventListenerObject,
79-
options?: boolean | AddEventListenerOptions,
80-
): AddEventListener {
77+
return function (this: InstrumentedElement, type, listener, options): AddEventListener {
8178
if (type === 'click' || type == 'keypress') {
8279
try {
83-
const el = this as InstrumentedElement;
84-
const handlers = (el.__sentry_instrumentation_handlers__ = el.__sentry_instrumentation_handlers__ || {});
80+
const handlers = (this.__sentry_instrumentation_handlers__ =
81+
this.__sentry_instrumentation_handlers__ || {});
8582
const handlerForType = (handlers[type] = handlers[type] || { refCount: 0 });
8683

8784
if (!handlerForType.handler) {
@@ -105,16 +102,10 @@ export function instrumentDOM(): void {
105102
proto,
106103
'removeEventListener',
107104
function (originalRemoveEventListener: RemoveEventListener): RemoveEventListener {
108-
return function (
109-
this: Element,
110-
type: string,
111-
listener: EventListenerOrEventListenerObject,
112-
options?: boolean | EventListenerOptions,
113-
): () => void {
105+
return function (this: InstrumentedElement, type, listener, options): () => void {
114106
if (type === 'click' || type == 'keypress') {
115107
try {
116-
const el = this as InstrumentedElement;
117-
const handlers = el.__sentry_instrumentation_handlers__ || {};
108+
const handlers = this.__sentry_instrumentation_handlers__ || {};
118109
const handlerForType = handlers[type];
119110

120111
if (handlerForType) {
@@ -128,7 +119,7 @@ export function instrumentDOM(): void {
128119

129120
// If there are no longer any custom handlers of any type on this element, cleanup everything.
130121
if (Object.keys(handlers).length === 0) {
131-
delete el.__sentry_instrumentation_handlers__;
122+
delete this.__sentry_instrumentation_handlers__;
132123
}
133124
}
134125
} catch (e) {

packages/browser/src/integrations/reportingobserver.ts

+14-6
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,13 @@ interface ReportingObserverOptions {
4646
types?: ReportTypes[];
4747
}
4848

49+
/** This is experimental and the types are not included with TypeScript, sadly. */
50+
interface ReportingObserverClass {
51+
new (handler: (reports: Report[]) => void, options: { buffered?: boolean; types?: ReportTypes[] }): {
52+
observe: () => void;
53+
};
54+
}
55+
4956
const SETUP_CLIENTS = new WeakMap<Client, boolean>();
5057

5158
const _reportingObserverIntegration = ((options: ReportingObserverOptions = {}) => {
@@ -99,13 +106,14 @@ const _reportingObserverIntegration = ((options: ReportingObserverOptions = {})
99106
return;
100107
}
101108

102-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
103-
const observer = new (WINDOW as any).ReportingObserver(handler, {
104-
buffered: true,
105-
types,
106-
});
109+
const observer = new (WINDOW as typeof WINDOW & { ReportingObserver: ReportingObserverClass }).ReportingObserver(
110+
handler,
111+
{
112+
buffered: true,
113+
types,
114+
},
115+
);
107116

108-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
109117
observer.observe();
110118
},
111119

packages/cloudflare/src/handler.ts

+24-12
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,7 @@ export function withSentry<E extends ExportedHandler<any>>(
4040
): E {
4141
setAsyncLocalStorageAsyncContextStrategy();
4242

43-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
44-
if ('fetch' in handler && typeof handler.fetch === 'function' && !(handler.fetch as any).__SENTRY_INSTRUMENTED__) {
43+
if ('fetch' in handler && typeof handler.fetch === 'function' && !isInstrumented(handler.fetch)) {
4544
handler.fetch = new Proxy(handler.fetch, {
4645
apply(target, thisArg, args: Parameters<ExportedHandlerFetchHandler<ExtractEnv<E>>>) {
4746
const [request, env, context] = args;
@@ -50,16 +49,10 @@ export function withSentry<E extends ExportedHandler<any>>(
5049
},
5150
});
5251

53-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
54-
(handler.fetch as any).__SENTRY_INSTRUMENTED__ = true;
52+
markAsInstrumented(handler.fetch);
5553
}
5654

57-
if (
58-
'scheduled' in handler &&
59-
typeof handler.scheduled === 'function' &&
60-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
61-
!(handler.scheduled as any).__SENTRY_INSTRUMENTED__
62-
) {
55+
if ('scheduled' in handler && typeof handler.scheduled === 'function' && !isInstrumented(handler.scheduled)) {
6356
handler.scheduled = new Proxy(handler.scheduled, {
6457
apply(target, thisArg, args: Parameters<ExportedHandlerScheduledHandler<ExtractEnv<E>>>) {
6558
const [event, env, context] = args;
@@ -97,9 +90,28 @@ export function withSentry<E extends ExportedHandler<any>>(
9790
},
9891
});
9992

100-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
101-
(handler.scheduled as any).__SENTRY_INSTRUMENTED__ = true;
93+
markAsInstrumented(handler.scheduled);
10294
}
10395

10496
return handler;
10597
}
98+
99+
type SentryInstrumented<T> = T & {
100+
__SENTRY_INSTRUMENTED__?: boolean;
101+
};
102+
103+
function markAsInstrumented<T>(handler: T): void {
104+
try {
105+
(handler as SentryInstrumented<T>).__SENTRY_INSTRUMENTED__ = true;
106+
} catch {
107+
// ignore errors here
108+
}
109+
}
110+
111+
function isInstrumented<T>(handler: T): boolean | undefined {
112+
try {
113+
return (handler as SentryInstrumented<T>).__SENTRY_INSTRUMENTED__;
114+
} catch {
115+
return false;
116+
}
117+
}

packages/core/src/metrics/aggregator.ts

+3-7
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,8 @@ export class MetricsAggregator implements MetricsAggregatorBase {
2020
// that we store in memory.
2121
private _bucketsTotalWeight;
2222

23-
// Cast to any so that it can use Node.js timeout
24-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
25-
private readonly _interval: any;
23+
// We adjust the type here to add the `unref()` part, as setInterval can technically return a number of a NodeJS.Timer.
24+
private readonly _interval: ReturnType<typeof setInterval> & { unref?: () => void };
2625

2726
// SDKs are required to shift the flush interval by random() * rollup_in_seconds.
2827
// That shift is determined once per startup to create jittering.
@@ -40,11 +39,8 @@ export class MetricsAggregator implements MetricsAggregatorBase {
4039
this._buckets = new Map();
4140
this._bucketsTotalWeight = 0;
4241

43-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
44-
this._interval = setInterval(() => this._flush(), DEFAULT_FLUSH_INTERVAL) as any;
45-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
42+
this._interval = setInterval(() => this._flush(), DEFAULT_FLUSH_INTERVAL);
4643
if (this._interval.unref) {
47-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
4844
this._interval.unref();
4945
}
5046

packages/core/src/transports/base.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,7 @@ export function createTransport(
6161
return resolvedSyncPromise({});
6262
}
6363

64-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
65-
const filteredEnvelope: Envelope = createEnvelope(envelope[0], filteredEnvelopeItems as any);
64+
const filteredEnvelope: Envelope = createEnvelope(envelope[0], filteredEnvelopeItems as (typeof envelope)[1]);
6665

6766
// Creates client report for each item in an envelope
6867
const recordEnvelopeLoss = (reason: EventDropReason): void => {

packages/core/src/utils-hoist/isBrowser.ts

+2-4
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ type ElectronProcess = { type?: string };
1313

1414
// Electron renderers with nodeIntegration enabled are detected as Node.js so we specifically test for them
1515
function isElectronNodeRenderer(): boolean {
16-
return (
17-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
18-
(GLOBAL_OBJ as any).process !== undefined && ((GLOBAL_OBJ as any).process as ElectronProcess).type === 'renderer'
19-
);
16+
const process = (GLOBAL_OBJ as typeof GLOBAL_OBJ & { process?: ElectronProcess }).process;
17+
return !!process && process.type === 'renderer';
2018
}

packages/core/src/utils-hoist/misc.ts

+7-2
Original file line numberDiff line numberDiff line change
@@ -211,8 +211,7 @@ export function addContextToFrame(lines: string[], frame: StackFrame, linesOfCon
211211
* @returns `true` if the exception has already been captured, `false` if not (with the side effect of marking it seen)
212212
*/
213213
export function checkOrSetAlreadyCaught(exception: unknown): boolean {
214-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
215-
if (exception && (exception as any).__sentry_captured__) {
214+
if (isAlreadyCaptured(exception)) {
216215
return true;
217216
}
218217

@@ -227,6 +226,12 @@ export function checkOrSetAlreadyCaught(exception: unknown): boolean {
227226
return false;
228227
}
229228

229+
function isAlreadyCaptured(exception: unknown): boolean | void {
230+
try {
231+
return (exception as { __sentry_captured__?: boolean }).__sentry_captured__;
232+
} catch {} // eslint-disable-line no-empty
233+
}
234+
230235
/**
231236
* Checks whether the given input is already an array, and if it isn't, wraps it in one.
232237
*

packages/core/src/utils-hoist/object.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,8 @@ function isPojo(input: unknown): input is Record<string, unknown> {
296296
export function objectify(wat: unknown): typeof Object {
297297
let objectified;
298298
switch (true) {
299-
case wat === undefined || wat === null:
299+
// this will catch both undefined and null
300+
case wat == undefined:
300301
objectified = new String(wat);
301302
break;
302303

packages/google-cloud-serverless/src/gcpfunction/http.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,7 @@ export function wrapHttpFunction(fn: HttpFunction, wrapOptions: Partial<WrapperO
2727

2828
// Functions emulator from firebase-tools has a hack-ish workaround that saves the actual function
2929
// passed to `onRequest(...)` and in fact runs it so we need to wrap it too.
30-
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access
31-
const emulatorFunc = (fn as any).__emulator_func as HttpFunction | undefined;
30+
const emulatorFunc = (fn as HttpFunction & { __emulator_func?: HttpFunction }).__emulator_func;
3231
if (emulatorFunc) {
3332
overrides = { __emulator_func: proxyFunction(emulatorFunc, wrap) };
3433
}

packages/nextjs/src/client/routing/pagesRouterRoutingInstrumentation.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ import RouterImport from 'next/router';
1414
// next/router v10 is CJS
1515
//
1616
// For ESM/CJS interoperability 'reasons', depending on how this file is loaded, Router might be on the default export
17-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
18-
const Router: typeof RouterImport = RouterImport.events ? RouterImport : (RouterImport as any).default;
17+
const Router: typeof RouterImport = RouterImport.events
18+
? RouterImport
19+
: (RouterImport as unknown as { default: typeof RouterImport }).default;
1920

2021
import { DEBUG_BUILD } from '../../common/debug-build';
2122

packages/nextjs/src/common/utils/tracingUtils.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@ let nextjsEscapedAsyncStorage: AsyncLocalStorage<true>;
6868
* first time.
6969
*/
7070
export function escapeNextjsTracing<T>(cb: () => T): T {
71-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
72-
const MaybeGlobalAsyncLocalStorage = (GLOBAL_OBJ as any).AsyncLocalStorage;
71+
const MaybeGlobalAsyncLocalStorage = (GLOBAL_OBJ as { AsyncLocalStorage?: new () => AsyncLocalStorage<true> })
72+
.AsyncLocalStorage;
7373

7474
if (!MaybeGlobalAsyncLocalStorage) {
7575
DEBUG_BUILD &&

packages/nextjs/src/config/templates/serverComponentWrapperTemplate.ts

+2-4
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,13 @@ if (typeof serverComponent === 'function') {
4141
// Current assumption is that Next.js applies some loader magic to userfiles, but not files in node_modules. This file
4242
// is technically a userfile so it gets the loader magic applied.
4343
wrappedServerComponent = new Proxy(serverComponent, {
44-
apply: (originalFunction, thisArg, args) => {
44+
apply: (originalFunction: (...args: unknown[]) => unknown, thisArg, args) => {
4545
let sentryTraceHeader: string | undefined | null = undefined;
4646
let baggageHeader: string | undefined | null = undefined;
4747
let headers: WebFetchHeaders | undefined = undefined;
4848

4949
// We try-catch here just in `requestAsyncStorage` is undefined since it may not be defined
5050
try {
51-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
5251
const requestAsyncStore = requestAsyncStorage?.getStore() as ReturnType<RequestAsyncStorage['getStore']>;
5352
sentryTraceHeader = requestAsyncStore?.headers.get('sentry-trace') ?? undefined;
5453
baggageHeader = requestAsyncStore?.headers.get('baggage') ?? undefined;
@@ -57,8 +56,7 @@ if (typeof serverComponent === 'function') {
5756
/** empty */
5857
}
5958

60-
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access
61-
return Sentry.wrapServerComponentWithSentry(originalFunction as any, {
59+
return Sentry.wrapServerComponentWithSentry(originalFunction, {
6260
componentRoute: '__ROUTE__',
6361
componentType: '__COMPONENT_TYPE__',
6462
sentryTraceHeader,

packages/node/src/integrations/context.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,7 @@ async function getOsContext(): Promise<OsContext> {
171171

172172
function getCultureContext(): CultureContext | undefined {
173173
try {
174-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
175-
if (typeof (process.versions as unknown as any).icu !== 'string') {
174+
if (typeof process.versions.icu !== 'string') {
176175
// Node was built without ICU support
177176
return;
178177
}

packages/node/src/proxy/base.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,7 @@ export abstract class Agent extends http.Agent {
8181
if (options) {
8282
// First check the `secureEndpoint` property explicitly, since this
8383
// means that a parent `Agent` is "passing through" to this instance.
84-
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access
85-
if (typeof (options as any).secureEndpoint === 'boolean') {
84+
if (typeof (options as Partial<typeof options>).secureEndpoint === 'boolean') {
8685
return options.secureEndpoint;
8786
}
8887

packages/react/src/reactrouter.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ function computeRootMatch(pathname: string): Match {
223223

224224
/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access */
225225
export function withSentryRouting<P extends Record<string, any>, R extends React.ComponentType<P>>(Route: R): R {
226-
const componentDisplayName = (Route as any).displayName || (Route as any).name;
226+
const componentDisplayName = Route.displayName || Route.name;
227227

228228
const WrappedRoute: React.FC<P> = (props: P) => {
229229
if (props && props.computedMatch && props.computedMatch.isExact) {

0 commit comments

Comments
 (0)