DEV Community

Weather Clock Dash
Weather Clock Dash

Posted on

TypeScript Development with Firefox: Source Maps, DOM Types, Extensions, and Build Tools

TypeScript development with Firefox is a strong combination. Firefox's DevTools have excellent TypeScript support through source maps, and there are Firefox-specific considerations when developing TypeScript-heavy applications. This guide covers the development workflow, common issues, and debugging patterns.

TypeScript in the Browser Context

TypeScript doesn't run natively in the browser — it compiles to JavaScript. The browser sees JavaScript, but with source maps configured correctly, Firefox DevTools shows you the original TypeScript source.

// tsconfig.json for web development
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ES2022",
    "moduleResolution": "bundler",
    "strict": true,
    "sourceMap": true,        // generates .js.map files
    "outDir": "./dist",
    "lib": ["DOM", "DOM.Iterable", "ES2022"]
  }
}
Enter fullscreen mode Exit fullscreen mode

The critical setting: "sourceMap": true. This generates .js.map files that Firefox uses to show TypeScript in the debugger.

Firefox Debugger with TypeScript

With source maps active, the Firefox Debugger shows TypeScript files in the Sources panel. Set breakpoints directly in .ts files — they pause at the right TypeScript location even though the browser runs compiled JavaScript.

Key features:

  • Type information shown in hover tooltips (if the bundler preserves it)
  • TypeScript file names in error stack traces
  • Accurate variable inspection (variable names match TypeScript names, not mangled JavaScript)

If source maps aren't loading: check Network tab for failed .map file requests, or check that your bundler is outputting source maps to the correct path.

TypeScript DOM Types

TypeScript's lib.dom.d.ts declarations match the browser APIs. For Firefox-specific APIs:

// Firefox-specific APIs don't have TypeScript types by default
// Augment the global types:
declare global {
  interface Window {
    InstallTrigger?: {
      install(urls: Record<string, string>): void;
    };
  }
}

// Check for Firefox
const isFirefox = typeof window.InstallTrigger !== 'undefined';
Enter fullscreen mode Exit fullscreen mode

For WebExtensions TypeScript types:

npm install --save-dev @types/webextension-polyfill
Enter fullscreen mode Exit fullscreen mode

Strict Mode and Browser Compatibility

TypeScript's strict mode catches bugs that become runtime errors in Firefox:

// Strict catches this:
function getElement(id: string) {
  return document.getElementById(id); // Returns Element | null
}

// Without strict check, this would throw at runtime in Firefox:
const el = getElement('missing');
el.style.color = 'red'; // Runtime: Cannot set properties of null

// With strict, TypeScript forces the null check:
const el = getElement('missing');
if (el) {
  el.style.color = 'red'; // Safe
}
Enter fullscreen mode Exit fullscreen mode

TypeScript with Web APIs

Browser APIs have TypeScript types that reflect Firefox's implementation:

// getUserMedia is typed
const stream = await navigator.mediaDevices.getUserMedia({
  video: { width: 1280, height: 720 },
  audio: true
});
// TypeScript knows stream is MediaStream

// Fetch API with typed responses
async function fetchUser(id: number): Promise<User> {
  const response = await fetch(`/api/users/${id}`);
  if (!response.ok) throw new Error(`HTTP ${response.status}`);
  const data = await response.json() as User; // type assertion
  return data;
}

// IndexedDB with typed wrapper
interface UserStore {
  id: number;
  name: string;
  email: string;
}
Enter fullscreen mode Exit fullscreen mode

TypeScript Build Tools for Firefox Development

Vite (recommended for most projects):

npm create vite@latest my-app -- --template vanilla-ts
cd my-app && npm install && npm run dev
Enter fullscreen mode Exit fullscreen mode

Vite generates source maps by default in dev mode. Firefox DevTools shows TypeScript files directly.

webpack:

// webpack.config.js
module.exports = {
  devtool: 'source-map', // Full source maps for production debugging
  // devtool: 'eval-source-map', // Faster rebuilds in development
  module: {
    rules: [{ test: /\.tsx?$/, use: 'ts-loader', exclude: /node_modules/ }]
  }
};
Enter fullscreen mode Exit fullscreen mode

esbuild (fastest builds):

esbuild src/main.ts --bundle --sourcemap --outfile=dist/bundle.js
Enter fullscreen mode Exit fullscreen mode

Firefox Extension Development with TypeScript

TypeScript is well-suited for Firefox extension development:

// manifest.json (still plain JSON)
// TypeScript for background script:
browser.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
  // TypeScript knows the types of all parameters
  if (changeInfo.status === 'complete' && tab.url) {
    handleTabComplete(tabId, tab.url);
  }
});

function handleTabComplete(tabId: number, url: string): void {
  // typed parameters prevent common errors
}
Enter fullscreen mode Exit fullscreen mode

The webext-browser package provides TypeScript types for the WebExtensions API:

npm install --save-dev @types/firefox-webext-browser
Enter fullscreen mode Exit fullscreen mode

Type-Safe API Integration

Use TypeScript interfaces to type your API responses:

interface GitHubUser {
  login: string;
  id: number;
  name: string | null;
  public_repos: number;
}

async function getGitHubUser(username: string): Promise<GitHubUser> {
  const response = await fetch(`https://api.github.com/users/${username}`);
  const data: unknown = await response.json();

  // Runtime validation (zod is popular for this):
  // return UserSchema.parse(data);

  // Or type assertion with comment:
  return data as GitHubUser;
}
Enter fullscreen mode Exit fullscreen mode

Debugging TypeScript Errors in Firefox

When TypeScript compiles to JavaScript, type errors appear in the terminal (tsc compiler), not in Firefox. But runtime errors in Firefox have useful stack traces:

  1. TypeError in Firefox console → click the file link → jumps to TypeScript source (with source maps)
  2. The error message often points to where TypeScript's optional chaining (?.) would have prevented the issue

Patterns that prevent Firefox runtime errors:

// Instead of:
document.getElementById('app').style.color = 'red'; // Possible null

// TypeScript forces:
const app = document.getElementById('app');
if (app instanceof HTMLElement) {
  app.style.color = 'red'; // Type-narrowed to HTMLElement
}

// Or:
(document.getElementById('app') as HTMLElement).style.color = 'red'; // Explicit assertion
Enter fullscreen mode Exit fullscreen mode

Testing TypeScript in Firefox

For cross-browser TypeScript testing with Playwright:

import { test, expect, Browser } from '@playwright/test';

test('works in Firefox', async ({ browser }: { browser: Browser }) => {
  const page = await browser.newPage();
  await page.goto('http://localhost:5173');
  await expect(page.locator('#result')).toHaveText('Success');
});
Enter fullscreen mode Exit fullscreen mode

Configure playwright.config.ts:

import { defineConfig } from '@playwright/test';

export default defineConfig({
  projects: [
    { name: 'chromium', use: { browserName: 'chromium' } },
    { name: 'firefox', use: { browserName: 'firefox' } },
    { name: 'webkit', use: { browserName: 'webkit' } }
  ]
});
Enter fullscreen mode Exit fullscreen mode

Top comments (0)