From a2390a5c059342bcac2a5297728181dd9939f562 Mon Sep 17 00:00:00 2001 From: Mohammad Faiz Date: Thu, 28 May 2026 23:08:30 +0530 Subject: [PATCH] fix: correct isCancel type to narrow to CanceledError (#10952) * fix(index.d.cts): correct isCancel type to narrow to CanceledError instead of Cancel * test(types): cover CJS isCancel narrowing * test(types): assert isCancel preserves generic --------- Co-authored-by: Jason Saayman --- PRE_RELEASE_CHANGELOG.md | 1 + index.d.cts | 2 +- .../module/cjs/tests/helpers/cjs-is-cancel-typing.ts | 12 ++++++++++++ tests/module/cjs/tests/typings.module.test.cjs | 11 +++++++++++ 4 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 tests/module/cjs/tests/helpers/cjs-is-cancel-typing.ts diff --git a/PRE_RELEASE_CHANGELOG.md b/PRE_RELEASE_CHANGELOG.md index 226a861f..c3d503fd 100644 --- a/PRE_RELEASE_CHANGELOG.md +++ b/PRE_RELEASE_CHANGELOG.md @@ -11,6 +11,7 @@ - **AxiosHeaders:** Silently skip empty response header names emitted by some React Native Android responses instead of throwing. (**#6959**, **#10875**) - **Config Security:** Ignore inherited `params` and `paramsSerializer` values when resolving request config, preventing prototype-pollution gadgets from changing serialized URLs. (**#10922**) - **Types:** Add the missing readonly `name: 'CanceledError'` declaration to CommonJS `CanceledError` typings to match the ESM declarations. (**#10922**) +- **Types:** Correct the CommonJS `isCancel` type guard to narrow cancellation errors to `CanceledError`, matching the ESM declaration. (**#10952**) - **HTTP Adapter - Auth on Redirect:** HTTP Basic credentials supplied via `config.auth` are now restored on same-origin redirects, fixing a regression caused by `follow-redirects` >= 1.15.8 that broke `POST` requests answered with a 303 Location. Cross-origin redirects continue to drop credentials, preserving the existing T-R2 mitigation in `THREATMODEL.md`. (**#6929**) - **HTTP Adapter - Socket Path:** Ignore inherited `socketPath` and `allowedSocketPaths` config values when building Node.js requests, preventing prototype-pollution SSRF via Unix sockets. (**#10901**) - **React Native FormData:** Clear the default `Content-Type` header for React Native `FormData` requests so Android can build multipart bodies with the correct boundary. (**#10898**) diff --git a/index.d.cts b/index.d.cts index 2e17a8e4..837558ee 100644 --- a/index.d.cts +++ b/index.d.cts @@ -696,7 +696,7 @@ declare namespace axios { CanceledError: typeof CanceledError; HttpStatusCode: typeof HttpStatusCode; readonly VERSION: string; - isCancel(value: any): value is Cancel; + isCancel(value: any): value is CanceledError; all(values: Array>): Promise; spread(callback: (...args: T[]) => R): (array: T[]) => R; isAxiosError(payload: any): payload is AxiosError; diff --git a/tests/module/cjs/tests/helpers/cjs-is-cancel-typing.ts b/tests/module/cjs/tests/helpers/cjs-is-cancel-typing.ts new file mode 100644 index 00000000..5c95955b --- /dev/null +++ b/tests/module/cjs/tests/helpers/cjs-is-cancel-typing.ts @@ -0,0 +1,12 @@ +import axios = require('axios'); + +declare const thrown: unknown; + +if (axios.isCancel<{ ok: true }>(thrown)) { + const canceled: InstanceType = thrown; + const data: { ok: true } | undefined = thrown.response?.data; + // @ts-expect-error -- The generic response data must not be widened to any. + const wrongData: { ok: false } | undefined = thrown.response?.data; + + console.log(canceled.message, data, wrongData); +} diff --git a/tests/module/cjs/tests/typings.module.test.cjs b/tests/module/cjs/tests/typings.module.test.cjs index b9936d78..d5d360bc 100644 --- a/tests/module/cjs/tests/typings.module.test.cjs +++ b/tests/module/cjs/tests/typings.module.test.cjs @@ -25,4 +25,15 @@ describe('module cjs typings compatibility', () => { cleanupTempFixture(fixturePath); } }); + + it('narrows isCancel to CanceledError in commonjs typings', () => { + const sourcePath = path.join(repoRoot, 'tests/module/cjs/tests/helpers/cjs-is-cancel-typing.ts'); + const fixturePath = createTempFixture(suiteRoot, 'typings-cjs-is-cancel', sourcePath, tsconfig); + + try { + runCommand('node', [tscBin, '--noEmit', '-p', 'tsconfig.json'], { cwd: fixturePath }); + } finally { + cleanupTempFixture(fixturePath); + } + }); });