Skip to content

Commit b99ee25

Browse files
authored
ref(utils): Use type predicates in is utility functions (#4124)
We have a number of `is` utility functions (`isString`, `isError`, and so on), and while they tell the human reading the code something about the value in question, they don't tell TypeScript anything, because it doesn't see them as type checks. As a result, we end up with a lot of code like this: ``` if( isString(msg) ) { const words = (msg as string).split(' '); } ``` where we have to typecast our variables, despite their type already having been checked immediately beforehand. In order to fix this, TS lets you return a type predicate[1] from a type-checking function rather than a simple boolean, and that lets it know what the human reader knows - if `isString(msg)` is true, then `msg` must be a string. This switches all of our `is` functions to use type predicates, and removes all of the typecasts which are no longer necessary as a result of this change. [1] https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates
1 parent 76b8231 commit b99ee25

File tree

13 files changed

+40
-36
lines changed

13 files changed

+40
-36
lines changed

packages/browser/src/eventbuilder.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,14 @@ export function eventFromUnknownInput(
6565
): Event {
6666
let event: Event;
6767

68-
if (isErrorEvent(exception as ErrorEvent) && (exception as ErrorEvent).error) {
68+
if (isErrorEvent(exception)) {
6969
// If it is an ErrorEvent with `error` property, extract it to get actual Error
70-
const errorEvent = exception as ErrorEvent;
7170
// eslint-disable-next-line no-param-reassign
72-
exception = errorEvent.error;
73-
event = eventFromStacktrace(computeStackTrace(exception as Error));
71+
exception = exception.error;
72+
event = eventFromStacktrace(computeStackTrace(exception));
7473
return event;
7574
}
76-
if (isDOMError(exception as DOMError) || isDOMException(exception as DOMException)) {
75+
if (isDOMError(exception) || isDOMException(exception)) {
7776
// If it is a DOMError or DOMException (which are legacy APIs, but still supported in some browsers)
7877
// then we just extract the name, code, and message, as they don't provide anything else
7978
// https://developer.mozilla.org/en-US/docs/Web/API/DOMError
@@ -90,9 +89,9 @@ export function eventFromUnknownInput(
9089

9190
return event;
9291
}
93-
if (isError(exception as Error)) {
92+
if (isError(exception)) {
9493
// we have a real Error object, do nothing
95-
event = eventFromStacktrace(computeStackTrace(exception as Error));
94+
event = eventFromStacktrace(computeStackTrace(exception));
9695
return event;
9796
}
9897
if (isPlainObject(exception) || isEvent(exception)) {

packages/integrations/src/ember.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ export class Ember implements Integration {
5858
getCurrentHub().withScope(scope => {
5959
if (isInstanceOf(reason, Error)) {
6060
scope.setExtra('context', 'Unhandled Promise error detected');
61-
getCurrentHub().captureException(reason, { originalException: reason as Error });
61+
getCurrentHub().captureException(reason, { originalException: reason });
6262
} else {
6363
scope.setExtra('reason', reason);
6464
getCurrentHub().captureMessage('Unhandled Promise error detected');

packages/integrations/src/extraerrordata.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ export class ExtraErrorData implements Integration {
9797
continue;
9898
}
9999
const value = error[key];
100-
extraErrorInfo[key] = isError(value) ? (value as Error).toString() : value;
100+
extraErrorInfo[key] = isError(value) ? value.toString() : value;
101101
}
102102

103103
// Check if someone attached `toJSON` method to grab even more properties (eg. axios is doing that)
@@ -106,7 +106,7 @@ export class ExtraErrorData implements Integration {
106106

107107
for (const key of Object.keys(serializedError)) {
108108
const value = serializedError[key];
109-
extraErrorInfo[key] = isError(value) ? (value as Error).toString() : value;
109+
extraErrorInfo[key] = isError(value) ? value.toString() : value;
110110
}
111111
}
112112

packages/nextjs/src/utils/instrumentServer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ function makeWrappedReqHandler(origReqHandler: ReqHandler): WrappedReqHandler {
227227
// If there is a trace header set, extract the data from it (parentSpanId, traceId, and sampling decision)
228228
let traceparentData;
229229
if (req.headers && isString(req.headers['sentry-trace'])) {
230-
traceparentData = extractTraceparentData(req.headers['sentry-trace'] as string);
230+
traceparentData = extractTraceparentData(req.headers['sentry-trace']);
231231
logger.log(`[Tracing] Continuing trace ${traceparentData?.traceId}.`);
232232
}
233233

packages/nextjs/src/utils/withSentry.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ export const withSentry = (origHandler: NextApiHandler): WrappedNextApiHandler =
3939
// If there is a trace header set, extract the data from it (parentSpanId, traceId, and sampling decision)
4040
let traceparentData;
4141
if (req.headers && isString(req.headers['sentry-trace'])) {
42-
traceparentData = extractTraceparentData(req.headers['sentry-trace'] as string);
42+
traceparentData = extractTraceparentData(req.headers['sentry-trace']);
4343
logger.log(`[Tracing] Continuing trace ${traceparentData?.traceId}.`);
4444
}
4545

packages/node/src/backend.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export class NodeBackend extends BaseBackend<NodeOptions> {
4141
const message = `Non-Error exception captured with keys: ${extractExceptionKeysForMessage(exception)}`;
4242

4343
getCurrentHub().configureScope(scope => {
44-
scope.setExtra('__serialized__', normalizeToSize(exception as Record<string, unknown>));
44+
scope.setExtra('__serialized__', normalizeToSize(exception));
4545
});
4646

4747
ex = (hint && hint.syntheticException) || new Error(message);

packages/node/src/handlers.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ export function tracingHandler(): (
5656
// If there is a trace header set, we extract the data from it (parentSpanId, traceId, and sampling decision)
5757
let traceparentData;
5858
if (req.headers && isString(req.headers['sentry-trace'])) {
59-
traceparentData = extractTraceparentData(req.headers['sentry-trace'] as string);
59+
traceparentData = extractTraceparentData(req.headers['sentry-trace']);
6060
}
6161

6262
const transaction = startTransaction(

packages/serverless/src/awslambda.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ export function wrapHandler<TEvent, TResult>(
256256
let traceparentData;
257257
const eventWithHeaders = event as { headers?: { [key: string]: string } };
258258
if (eventWithHeaders.headers && isString(eventWithHeaders.headers['sentry-trace'])) {
259-
traceparentData = extractTraceparentData(eventWithHeaders.headers['sentry-trace'] as string);
259+
traceparentData = extractTraceparentData(eventWithHeaders.headers['sentry-trace']);
260260
}
261261
const transaction = startTransaction({
262262
name: context.functionName,

packages/serverless/src/gcpfunction/http.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ function _wrapHttpFunction(fn: HttpFunction, wrapOptions: Partial<HttpFunctionWr
5353
let traceparentData;
5454
const reqWithHeaders = req as { headers?: { [key: string]: string } };
5555
if (reqWithHeaders.headers && isString(reqWithHeaders.headers['sentry-trace'])) {
56-
traceparentData = extractTraceparentData(reqWithHeaders.headers['sentry-trace'] as string);
56+
traceparentData = extractTraceparentData(reqWithHeaders.headers['sentry-trace']);
5757
}
5858
const transaction = startTransaction({
5959
name: `${reqMethod} ${reqUrl}`,

packages/tracing/src/browser/request.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ export function fetchCallback(
185185
const options = (handlerData.args[1] = (handlerData.args[1] as { [key: string]: any }) || {});
186186
let headers = options.headers;
187187
if (isInstanceOf(request, Request)) {
188-
headers = (request as Request).headers;
188+
headers = request.headers;
189189
}
190190
if (headers) {
191191
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access

0 commit comments

Comments
 (0)