> ## Documentation Index
> Fetch the complete documentation index at: https://extension.js.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Types for the chrome and browser APIs

> From Extension.js 4.1.19, the types for chrome.*, browser.*, and process.env install with the extension package. Older versions need @types/chrome installed by hand.

Extension.js compiles TypeScript with SWC, which strips types and never checks them. Type checking is a separate step that you run with `tsc`. This page covers how that step resolves `chrome.*`, `browser.*`, and `process.env`.

## What Extension.js generates

When a project uses TypeScript, `extension dev` and `extension build` write an `extension-env.d.ts` file beside `package.json`. It is regenerated on every run, so do not edit it.

The file pulls in the ambient types that the `extension` package publishes:

```ts extension-env.d.ts theme={null}
/// <reference types="extension/types" />
/// <reference types="extension/types/polyfill" />
```

Those references give you:

| Reference | What it declares |
| - | - |
| `extension/types` | The `browser` global, the `chrome` namespace, `process.env` and `import.meta.env` keys |
| `extension/types/polyfill` | The `browser.*` namespace shape from `webextension-polyfill` |
| Wildcard modules | `import` of `.css`, `.module.css`, `.png`, `.svg`, and other assets, plus `?raw` and `?url` imports |

The `EXTENSION_*` environment keys are typed here too. That is why `process.env.EXTENSION_MODE` resolves without extra setup.

When the `extension` package does not resolve from the project, for example a project that only runs the CLI through `npx`, the two references find nothing. The generated file then also carries the wildcard module declarations inline, so stylesheet, image, `?raw`, and `?url` imports still type-check.

## Types that install with Extension.js

From Extension.js 4.1.19, the `extension` package lists the three type packages that its references need as dependencies:

| Package | What it types |
| - | - |
| `@types/chrome` | The `chrome.*` namespace |
| `@types/webextension-polyfill` | The `browser.*` namespace |
| `@types/node` | `process.env` |

They install with `extension`, so `tsc` resolves `chrome.*` and `browser.*` in a new project without an extra install:

```bash theme={null}
npx tsc --noEmit
```

The build does not need these packages. SWC never reads the types, so the build succeeds with or without them.

## Pin your own version

The `extension` package accepts any version of the three type packages. When your project declares one of them, npm, pnpm, and Bun reuse the copy that your project installs.

When your `tsconfig.json` has no `types` array, TypeScript also loads the copy that your project declares. The version in your own `package.json` wins:

```json package.json theme={null}
{
  "devDependencies": {
    "@types/chrome": "^0.0.287"
  }
}
```

## Projects on Extension.js 4.1.18 or older

Before 4.1.19, `extension/types` referenced `chrome` but did not install `@types/chrome`. A project that calls `chrome.*` without its own copy fails `tsc`:

```plaintext theme={null}
src/background.ts(19,1): error TS2304: Cannot find name 'chrome'.
src/content/scripts.ts(87,30): error TS2503: Cannot find namespace 'chrome'.
```

Upgrade `extension` to 4.1.19 or later. If you stay on an older version, install the package by hand:

<CodeGroup>
  ```bash npm theme={null}
  npm install -D @types/chrome
  ```

  ```bash pnpm theme={null}
  pnpm add -D @types/chrome
  ```

  ```bash yarn theme={null}
  yarn add -D @types/chrome
  ```

  ```bash bun theme={null}
  bun add -d @types/chrome
  ```

  ```bash deno theme={null}
  deno add -D npm:@types/chrome
  ```
</CodeGroup>

On those versions, `browser` has the type `any` until `@types/webextension-polyfill` is installed. To type `browser.*`, install that package too:

<CodeGroup>
  ```bash npm theme={null}
  npm install -D @types/webextension-polyfill
  ```

  ```bash pnpm theme={null}
  pnpm add -D @types/webextension-polyfill
  ```

  ```bash yarn theme={null}
  yarn add -D @types/webextension-polyfill
  ```

  ```bash bun theme={null}
  bun add -d @types/webextension-polyfill
  ```

  ```bash deno theme={null}
  deno add -D npm:@types/webextension-polyfill
  ```
</CodeGroup>

## Type errors on browser.\* after an upgrade

From 4.1.19, `browser` has the full `webextension-polyfill` type instead of `any`. Code that passed `tsc` before can show new type errors, for example a call to an API that the polyfill does not declare.

Fix the call, or use `chrome.*` for an API that only Chromium ships. Read [Cross-browser compatibility](/docs/features/cross-browser-compatibility) for the runtime side of the same choice.

## Keep extension-env.d.ts in the include list

The generated file only helps when TypeScript reads it. The scaffolded `tsconfig.json` names it:

```json tsconfig.json theme={null}
{
  "include": ["./", "extension-env.d.ts"],
  "exclude": ["node_modules", "dist"]
}
```

When Extension.js writes a `tsconfig.json` for a project that has none, that file carries no `include` array. TypeScript then reads every file under the project folder, so it finds `extension-env.d.ts` anyway. An `include` array of your own that omits the file breaks asset imports and the `browser` global.

## Symptoms and fixes

| Symptom | Cause | Fix |
| - | - | - |
| `Cannot find name 'chrome'` | Extension.js 4.1.18 or older, and no `@types/chrome` | Upgrade to 4.1.19, or install `@types/chrome` |
| `Cannot find namespace 'chrome'` | Same cause, in a type position | Upgrade to 4.1.19, or install `@types/chrome` |
| `Cannot find module './styles.css'` | `extension-env.d.ts` is out of `include` | Add the file to `include` |
| `Cannot find name 'browser'` | The project never ran `dev` or `build` | Run either command once to generate types |
| New type errors on `browser.*` calls | From 4.1.19, `browser` is typed instead of `any` | Fix the call, or use `chrome.*` for a Chromium-only API |

## Best practices

* Treat `extension-env.d.ts` as build output. Commit it if you like, but never edit it.
* Declare a type package in your own `devDependencies` only when you need a specific version of it.
* Run `tsc --noEmit` in continuous integration. The Extension.js build does not fail on type errors.

## Next steps

* Read the rest of the [TypeScript setup](/docs/languages-and-frameworks/typescript).
* Learn about [environment variables](/docs/features/environment-variables) that the types declare.
* Review [cross-browser compatibility](/docs/features/cross-browser-compatibility).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.