# How to Convert jQuery to JavaScript: A TypeScript-Powered Migration Guide for Beginners

> Learn to convert jQuery to vanilla JavaScript with TypeScript. Install type definitions, enable strict checks, and replace $ selectors using compiler diagnostics for a smooth migration.

- Repository: [Microsoft/TypeScript](https://github.com/microsoft/typescript)
- Tags: migration-guide
- Published: 2026-02-16

---

**Converting jQuery to vanilla JavaScript involves installing type definitions to map existing usage, enabling strict TypeScript checks to catch unsafe patterns, then systematically replacing `$` selectors with native DOM APIs while leveraging the compiler's precise diagnostics to ensure complete migration.**

Moving away from jQuery reduces bundle size and eliminates unnecessary abstractions, and the TypeScript compiler from the `microsoft/TypeScript` repository provides built-in tooling to guide this transition safely. By treating the migration as a type-driven refactoring, you can convert legacy code to modern standards without breaking functionality. Below is a proven workflow that uses the compiler's own error detection and native API typings to replace jQuery step-by-step.

## Step 1: Map Existing jQuery Usage with Type Definitions

Before removing any code, you must establish a baseline of where jQuery is actually used. Installing the official type definitions allows the compiler to recognize every `$` reference in your project.

Install the types as a dev dependency:

```bash
npm install -D @types/jquery

```

This step is critical because, as implemented in `microsoft/TypeScript`, the language service contains a specific diagnostic that prompts users to install these exact typings when `$` is missing. In [`src/services/codefixes/importFixes.ts`](https://github.com/microsoft/TypeScript/blob/main/src/services/codefixes/importFixes.ts) (lines 176–182), the compiler defines the message: *"Cannot find name '$'. Do you need to install type definitions for jQuery?"* This same mechanism will later help you confirm when you have successfully removed all jQuery references.

## Step 2: Enable Strict Type Checking to Expose Unsafe Patterns

With type definitions in place, configure your [`tsconfig.json`](https://github.com/microsoft/TypeScript/blob/main/tsconfig.json) to surface hidden assumptions in the jQuery code. Enable strict mode to prevent the `$` object from silently returning `any` types.

Set the following compiler options:

```json
{
  "compilerOptions": {
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true
  }
}

```

These settings force explicit typing on DOM interactions. Once you remove the jQuery types in later steps, the compiler will immediately flag every location where unsafe shortcuts were previously allowed, creating a precise checklist of required changes.

## Step 3: Identify Every `$` Reference for Systematic Replacement

After uninstalling `@types/jquery` and removing the library from your [`package.json`](https://github.com/microsoft/TypeScript/blob/main/package.json), run the compiler to generate an exhaustive list of remaining jQuery calls.

Execute a type check without emitting files:

```bash
tsc --noEmit

```

The resulting *"Cannot find name '$'"* errors provide a line-by-line inventory of what needs rewriting. This pattern is tested explicitly in the TypeScript source itself; in [`src/testRunner/unittests/tsserver/typingsInstaller.ts`](https://github.com/microsoft/TypeScript/blob/main/src/testRunner/unittests/tsserver/typingsInstaller.ts) (lines 90–101), the test suite demonstrates a mock project that declares `$` and then validates the missing-identifier diagnostic. You can use this same approach to track your migration progress programmatically.

## Step 4: Replace jQuery DOM Helpers with Native Browser APIs

With your checklist of `$` usages ready, replace each jQuery method with its native equivalent. The TypeScript DOM library—defined in [`lib.dom.d.ts`](https://github.com/microsoft/TypeScript/blob/main/lib.dom.d.ts)—provides full type definitions for these replacements.

### Selectors and Event Listeners

Replace jQuery's `$()` wrapper with standard selection methods and attach listeners using the native event API:

```typescript
// jQuery approach
const items = $('.menu-item');
$('#btn').on('click', (e) => console.log(e.target));

// Vanilla JavaScript with TypeScript types
const items: NodeListOf<HTMLElement> = document.querySelectorAll('.menu-item');
const btn = document.getElementById('btn');
btn?.addEventListener('click', (e) => console.log(e.target));

```

Using `document.querySelectorAll` returns a `NodeListOf<HTMLElement>`, which provides typed access to element properties without runtime wrappers.

### AJAX and Network Requests

Swap jQuery's `$.ajax`, `$.get`, and `$.post` with the standard `fetch` API. This eliminates callback-based patterns in favor of native `Promise` objects that integrate cleanly with TypeScript's async/await typing:

```typescript
// jQuery AJAX
$.get('/api/data', (data) => {
    console.log(data);
});

// Modern fetch with async/await
async function loadData(): Promise<void> {
    const response = await fetch('/api/data');
    const data = await response.json();
    console.log(data);
}
loadData();

```

The `fetch` function and `Response` object are fully typed by the DOM lib included with TypeScript, ensuring type safety for headers, body parsing, and error handling.

### Animations and Effects

Replace jQuery's `.animate()` chains with CSS transitions or the Web Animations API for hardware-accelerated performance:

```typescript
// jQuery animation
$('#box').animate({ opacity: 0 }, 500);

// Web Animations API
const box = document.getElementById('box');
box?.animate([{ opacity: 1 }, { opacity: 0 }], { duration: 500 });

```

The `Element.animate` method is defined in the TypeScript DOM library and accepts typed keyframe objects and timing parameters.

## Step 5: Remove the jQuery Dependency and Validate

Once all compiler errors are resolved, eliminate the runtime dependency entirely. Remove import statements and script tags, then prune your dependencies:

```bash
npm uninstall jquery @types/jquery
npm prune

```

Run your full test suite to verify functional parity. The `microsoft/TypeScript` repository demonstrates robust CI practices in [`.github/workflows/ci.yml`](https://github.com/microsoft/TypeScript/blob/main/.github/workflows/ci.yml), which you can emulate to automate testing in your own pipeline. Additionally, configure ESLint with rules like `no-undef` to catch any stray global `$` references that the type checker might have missed in non-TypeScript files.

## Summary

- **Install type definitions first** (`@types/jquery`) to establish a baseline of all jQuery usage, leveraging the diagnostic logic found in [`src/services/codefixes/importFixes.ts`](https://github.com/microsoft/TypeScript/blob/main/src/services/codefixes/importFixes.ts).
- **Enable strict mode** in [`tsconfig.json`](https://github.com/microsoft/TypeScript/blob/main/tsconfig.json) to force explicit typing and expose unsafe jQuery shortcuts before you begin rewriting.
- **Use `--noEmit` errors** as a migration checklist, following the testing pattern shown in [`src/testRunner/unittests/tsserver/typingsInstaller.ts`](https://github.com/microsoft/TypeScript/blob/main/src/testRunner/unittests/tsserver/typingsInstaller.ts).
- **Map jQuery methods to native APIs**: `querySelectorAll` for selection, `addEventListener` for events, `fetch` for AJAX, and the Web Animations API for effects—all fully typed in [`lib.dom.d.ts`](https://github.com/microsoft/TypeScript/blob/main/lib.dom.d.ts).
- **Remove the dependency** only after the compiler reports zero `$` errors, then validate with automated tests and linting.

## Frequently Asked Questions

### Do I need to rewrite everything at once when converting jQuery to JavaScript?

No. A phased approach is safer. Keep the jQuery types installed initially to see the full scope of usage, then remove them section by section. The TypeScript compiler will emit *"Cannot find name '$'"* errors only for the files you have processed, allowing you to migrate incrementally while maintaining a working build.

### Why does TypeScript suggest installing jQuery types automatically?

The language service includes a specific code fix, defined in [`src/services/codefixes/importFixes.ts`](https://github.com/microsoft/TypeScript/blob/main/src/services/codefixes/importFixes.ts) (lines 176–182), that detects the absence of the `$` identifier and suggests installing `@types/jquery`. This diagnostic exists because jQuery is historically common, and the compiler is designed to help developers quickly resolve missing identifier errors for popular libraries.

### Can I use TypeScript to migrate jQuery code even if the project isn't fully typed yet?

Yes. Start by enabling `noImplicitAny` rather than full `strict` mode. This will catch the most dangerous implicit `any` returns from jQuery methods without forcing you to type every variable immediately. You can tighten the rules gradually as you replace jQuery calls with explicitly typed native DOM APIs.

### What is the performance benefit of replacing jQuery animations with native APIs?

Native animations using the Web Animations API or CSS transitions are GPU-accelerated and do not incur the overhead of jQuery's animation queue or property parsing. As shown in the [`lib.dom.d.ts`](https://github.com/microsoft/TypeScript/blob/main/lib.dom.d.ts) definitions, the native `Element.animate` method operates directly on the browser's compositor thread, resulting in smoother frame rates and lower memory usage compared to jQuery's JavaScript-based tweening engine.