diff --git a/CHANGELOG.md b/CHANGELOG.md
index 27027cbfb3c..09cdf2104cd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,9 @@
- Interpret `keyFields: [...]` and `keyArgs: [...]` configurations in `InMemoryCache` type/field policies as `ReadonlyArray`s, since they are never mutated internally.
[@julienfouilhe](https://github.com/julienfouilhe) in [#9339](https://github.com/apollographql/apollo-client/pull/9339)
+- Avoid declaring a global type for the `__DEV__` constant, to avoid conflict with other such global declarations.
+ [@benjamn](https://github.com/benjamn) in [#9386](https://github.com/apollographql/apollo-client/pull/9386)
+
### Bug Fixes
- Fix `useSubscription` executing `skip`ped subscription when input changes.
diff --git a/config/distSpotFixes.ts b/config/distSpotFixes.ts
new file mode 100644
index 00000000000..41b8afebd79
--- /dev/null
+++ b/config/distSpotFixes.ts
@@ -0,0 +1,25 @@
+import * as fs from "fs";
+import { EOL } from "os";
+import { distDir } from './helpers';
+
+export function applyDistSpotFixes() {
+ sanitizeDEV();
+}
+
+function sanitizeDEV() {
+ const globalDTsPath = `${distDir}/utilities/globals/global.d.ts`;
+ const globalDTs = fs.readFileSync(globalDTsPath, "utf8");
+ // The global.d.ts types are useful within the @apollo/client codebase to
+ // provide a type for the global __DEV__ constant, but actually shipping that
+ // declaration as a globally-declared type runs too much risk of conflict with
+ // other __DEV__ declarations attempting to achieve the same thing, most
+ // notably the one in @types/react-native/index.d.ts. We preserve the default
+ // export so that index.d.ts can remain unchanged, but otherwise we remove all
+ // traces of __DEV__ from global.d.ts.
+ if (/__DEV__/.test(globalDTs)) {
+ fs.writeFileSync(globalDTsPath, [
+ "declare const _default: typeof globalThis;",
+ "export default _default;",
+ ].join(EOL));
+ }
+}
diff --git a/config/resolveModuleIds.ts b/config/postprocessDist.ts
similarity index 98%
rename from config/resolveModuleIds.ts
rename to config/postprocessDist.ts
index f8798c654d1..cddb75ff7e2 100644
--- a/config/resolveModuleIds.ts
+++ b/config/postprocessDist.ts
@@ -3,6 +3,9 @@ import * as path from "path";
import resolve from "resolve";
import { distDir, eachFile, reparse, reprint } from './helpers';
+import { applyDistSpotFixes } from "./distSpotFixes";
+applyDistSpotFixes();
+
// The primary goal of the 'npm run resolve' script is to make ECMAScript
// modules exposed by Apollo Client easier to consume natively in web browsers,
// without bundling, and without help from package.json files. It accomplishes
diff --git a/package.json b/package.json
index 6d53c4902a6..bc07bc2c653 100644
--- a/package.json
+++ b/package.json
@@ -31,14 +31,14 @@
"scripts": {
"prebuild": "npm run clean",
"build": "tsc",
- "postbuild": "npm run update-version && npm run invariants && npm run sourcemaps && npm run rollup && npm run prepdist && npm run resolve && npm run verify-version",
+ "postbuild": "npm run update-version && npm run invariants && npm run sourcemaps && npm run rollup && npm run prepdist && npm run postprocess-dist && npm run verify-version",
"update-version": "node config/version.js update",
"verify-version": "node config/version.js verify",
"invariants": "ts-node-script config/processInvariants.ts",
"sourcemaps": "ts-node-script config/rewriteSourceMaps.ts",
"rollup": "rollup -c ./config/rollup.config.js",
"prepdist": "node ./config/prepareDist.js",
- "resolve": "ts-node-script config/resolveModuleIds.ts",
+ "postprocess-dist": "ts-node-script config/postprocessDist.ts",
"clean": "rimraf -r dist coverage lib temp",
"ci:precheck": "node config/precheck.js",
"test": "jest --config ./config/jest.config.js",
diff --git a/src/utilities/globals/global.ts b/src/utilities/globals/global.ts
index c776fdda335..375689eb62c 100644
--- a/src/utilities/globals/global.ts
+++ b/src/utilities/globals/global.ts
@@ -1,6 +1,22 @@
import { maybe } from "./maybe";
declare global {
+ // Despite our attempts to reuse the React Native __DEV__ constant instead of
+ // inventing something new and Apollo-specific, declaring a useful type for
+ // __DEV__ unfortunately conflicts (TS2451) with the global declaration in
+ // @types/react-native/index.d.ts.
+ //
+ // To hide that harmless conflict, we @ts-ignore this line, which should
+ // continue to provide a type for __DEV__ elsewhere in the Apollo Client
+ // codebase, even when @types/react-native is not in use.
+ //
+ // However, because TypeScript drops @ts-ignore comments when generating .d.ts
+ // files (https://github.com/microsoft/TypeScript/issues/38628), we also
+ // sanitize the dist/utilities/globals/global.d.ts file to avoid declaring
+ // __DEV__ globally altogether when @apollo/client is installed in the
+ // node_modules directory of an application.
+ //
+ // @ts-ignore
const __DEV__: boolean | undefined;
}