---
title: "Migrate JavaScript to TypeScript"
source: https://docs.autohand.ai/tutorials/migrate-js-to-typescript
---

# Migrate JavaScript to TypeScript

Add type safety to an existing JavaScript project file by file with proper type definitions. This tutorial migrates a src/utils/ directory, but the same approach scales to an entire codebase.

Intermediate 25 min

autohand "Migrate src/utils/ from JavaScript to TypeScript. Add proper type annotations, create interfaces for shared data structures, and update imports. Start with the files that have no dependencies on other files."

## What you'll learn

-   How to plan a bottom-up migration order based on file dependencies
-   How to configure TypeScript for incremental migration with mixed JS/TS files
-   How to prompt Autohand to generate proper type annotations and interfaces
-   How to review generated types and fix compiler errors iteratively

## Before you start

-   Autohand Code installed
-   Node.js 18 or newer
-   A JavaScript project with a `package.json`
-   Git with a clean working tree for clean diffs

## Plan the migration order

The safest migration order is bottom-up: leaf modules with no internal dependencies first, then the modules that depend on them, then the entry points last.

Ask Autohand to map the dependency graph for your target directory:

You will get output like:

Work through this list in order. Each file you migrate reduces the unknown surface area for the next one.

## Configure TypeScript

Before migrating any files, set up a TypeScript configuration that allows mixed JS/TS files. This means the project keeps building throughout the migration.

The resulting `tsconfig.json` will look something like this:

With `allowJs: true`, TypeScript is happy to import from both `.js` and `.ts` files. You can migrate one file at a time without breaking anything.

## Run the migration prompt

Start with the first leaf module from your dependency order. The prompt instructs Autohand to rename the file, add annotations, and extract interfaces.

For the second layer of files, reference the already-migrated types:

**Tip:** If Autohand generates a type you are not sure about, ask it to explain: `autohand "Explain the ValidationResult interface you just created and why each field is typed the way it is."`

## Review generated types

Here is what a typical migration output looks like. The original JavaScript:

The migrated TypeScript:

The key things to check in each migrated file are:

-   No `any` types unless absolutely unavoidable (and if so, there should be a comment explaining why)
-   Interfaces are placed in the file where the shape is first defined, or in a shared `types.ts` if used across multiple files
-   Optional fields are marked with `?`, not typed as `T | undefined`
-   Function return types are explicit on public exports

## Fix type errors

After migrating each file, run the TypeScript compiler to catch errors before moving forward.

When type errors appear, paste them back to Autohand:

Autohand will read the file, understand the context around each error, and propose specific fixes. For the errors above, it might tighten the input validation upstream or add a type guard to narrow the union type.

**Tip:** If you see many `TS7006 implicitly has any type` errors, it means the function parameters were not typed. Rather than fixing them one by one, run the original migration prompt again with stricter instructions: `autohand "Re-migrate this file and ensure every parameter has an explicit type annotation."`

## Migrate the next batch

Once the first directory is done and the compiler reports zero errors, move to the next area of the codebase. Update the migration prompt to include context from what you have already done:

When the entire codebase is migrated, tighten the TypeScript config:

Setting `allowJs: false` at the end ensures no new JavaScript files can slip into the codebase going forward. Run `npx tsc --noEmit` one final time and fix any remaining errors before merging.

## What you learned

-   You mapped file dependencies and migrated leaf modules first to avoid breaking imports
-   You configured TypeScript for incremental migration with `allowJs: true`
-   You prompted Autohand to add type annotations, extract interfaces, and avoid `any`
-   You tightened the TypeScript config after completing the migration to prevent new JS files

Try next autohand "Migrate src/api/ to TypeScript. The types in src/utils/ are already defined. Import and reuse those types wherever applicable."

### Related tutorials

[

#### Refactor Legacy jQuery to Modern Framework

Remove jQuery before adding TypeScript for a cleaner migration with fewer implicit any types.

](/docs/tutorials/refactor-jquery-to-modern.html)[

#### Break a Monolith into Modules

Once you have TypeScript, use it to enforce module boundaries and clean interfaces between parts of your codebase.

](/docs/tutorials/break-monolith-into-modules.html)